blob: 57eb7bc950fe14dc5366c56e3ec8a29d95b21b42 [file] [log] [blame]
Stephane Barbariea75791c2019-01-24 10:58:06 -05001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package core
17
18import (
19 "context"
sbarbari17d7e222019-11-05 10:02:29 -050020 "github.com/opencord/voltha-go/db/model"
Scott Baker807addd2019-10-24 15:16:21 -070021 "github.com/opencord/voltha-lib-go/v2/pkg/log"
22 "github.com/opencord/voltha-lib-go/v2/pkg/probe"
Scott Baker555307d2019-11-04 08:58:01 -080023 "github.com/opencord/voltha-protos/v2/go/voltha"
Stephane Barbariea75791c2019-01-24 10:58:06 -050024 "google.golang.org/grpc/codes"
25 "google.golang.org/grpc/status"
26 "sync"
27)
28
29type LogicalDeviceManager struct {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040030 logicalDeviceAgents sync.Map
Stephane Barbariea75791c2019-01-24 10:58:06 -050031 deviceMgr *DeviceManager
32 grpcNbiHdlr *APIHandler
33 clusterDataProxy *model.Proxy
34 exitChannel chan int
35 lockLogicalDeviceAgentsMap sync.RWMutex
36}
37
38func newLogicalDeviceManager(deviceMgr *DeviceManager, cdProxy *model.Proxy) *LogicalDeviceManager {
39 var logicalDeviceMgr LogicalDeviceManager
40 logicalDeviceMgr.exitChannel = make(chan int, 1)
Stephane Barbariea75791c2019-01-24 10:58:06 -050041 logicalDeviceMgr.deviceMgr = deviceMgr
42 logicalDeviceMgr.clusterDataProxy = cdProxy
43 logicalDeviceMgr.lockLogicalDeviceAgentsMap = sync.RWMutex{}
44 return &logicalDeviceMgr
45}
46
47func (ldMgr *LogicalDeviceManager) setGrpcNbiHandler(grpcNbiHandler *APIHandler) {
48 ldMgr.grpcNbiHdlr = grpcNbiHandler
49}
50
51func (ldMgr *LogicalDeviceManager) start(ctx context.Context) {
52 log.Info("starting-logical-device-manager")
Hardik Windlassdc63dde2019-09-30 07:15:13 +000053 probe.UpdateStatusFromContext(ctx, "logical-device-manager", probe.ServiceStatusRunning)
Stephane Barbariea75791c2019-01-24 10:58:06 -050054 log.Info("logical-device-manager-started")
55}
56
57func (ldMgr *LogicalDeviceManager) stop(ctx context.Context) {
58 log.Info("stopping-logical-device-manager")
59 ldMgr.exitChannel <- 1
Hardik Windlassdc63dde2019-09-30 07:15:13 +000060 probe.UpdateStatusFromContext(ctx, "logical-device-manager", probe.ServiceStatusStopped)
Stephane Barbariea75791c2019-01-24 10:58:06 -050061 log.Info("logical-device-manager-stopped")
62}
63
64func (ldMgr *LogicalDeviceManager) addLogicalDeviceAgentToMap(agent *LogicalDeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040065 if _, exist := ldMgr.logicalDeviceAgents.Load(agent.logicalDeviceId); !exist {
66 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceId, agent)
Stephane Barbariea75791c2019-01-24 10:58:06 -050067 }
68}
69
70func (ldMgr *LogicalDeviceManager) getLogicalDeviceAgent(logicalDeviceId string) *LogicalDeviceAgent {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040071 if agent, ok := ldMgr.logicalDeviceAgents.Load(logicalDeviceId); ok {
72 //return agent
73 return agent.(*LogicalDeviceAgent)
Stephane Barbariea75791c2019-01-24 10:58:06 -050074 }
75 return nil
76}
77
78func (ldMgr *LogicalDeviceManager) deleteLogicalDeviceAgent(logicalDeviceId string) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040079 ldMgr.logicalDeviceAgents.Delete(logicalDeviceId)
Stephane Barbariea75791c2019-01-24 10:58:06 -050080}
81
82// GetLogicalDevice provides a cloned most up to date logical device
83func (ldMgr *LogicalDeviceManager) getLogicalDevice(id string) (*voltha.LogicalDevice, error) {
84 log.Debugw("getlogicalDevice", log.Fields{"logicaldeviceid": id})
85 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
86 return agent.GetLogicalDevice()
87 }
88 return nil, status.Errorf(codes.NotFound, "%s", id)
89}
90
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -050091func (ldMgr *LogicalDeviceManager) IsLogicalDeviceInCache(id string) bool {
92 ldMgr.lockLogicalDeviceAgentsMap.Lock()
93 defer ldMgr.lockLogicalDeviceAgentsMap.Unlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -040094 _, exist := ldMgr.logicalDeviceAgents.Load(id)
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -050095 return exist
96}
97
Stephane Barbariea75791c2019-01-24 10:58:06 -050098func (ldMgr *LogicalDeviceManager) listLogicalDevices() (*voltha.LogicalDevices, error) {
99 log.Debug("ListAllLogicalDevices")
100 result := &voltha.LogicalDevices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400101 if logicalDevices := ldMgr.clusterDataProxy.List(context.Background(), "/logical_devices", 0, false,
102 ""); logicalDevices != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500103 for _, logicalDevice := range logicalDevices.([]interface{}) {
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500104 // If device is not in memory then set it up
105 if !ldMgr.IsLogicalDeviceInCache(logicalDevice.(*voltha.LogicalDevice).Id) {
106 agent := newLogicalDeviceAgent(
Stephane Barbariea75791c2019-01-24 10:58:06 -0500107 logicalDevice.(*voltha.LogicalDevice).Id,
108 logicalDevice.(*voltha.LogicalDevice).RootDeviceId,
109 ldMgr,
110 ldMgr.deviceMgr,
111 ldMgr.clusterDataProxy,
112 )
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500113 if err := agent.start(nil, true); err != nil {
114 log.Warnw("failure-starting-agent", log.Fields{"logicalDeviceId": logicalDevice.(*voltha.LogicalDevice).Id})
115 agent.stop(nil)
116 } else {
117 ldMgr.addLogicalDeviceAgentToMap(agent)
118 }
Stephane Barbariea75791c2019-01-24 10:58:06 -0500119 }
120 result.Items = append(result.Items, logicalDevice.(*voltha.LogicalDevice))
121 }
122 }
123 return result, nil
124}
125
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500126// load loads a logical device manager in memory
127func (ldMgr *LogicalDeviceManager) load(lDeviceId string) error {
128 log.Debugw("loading-logical-device", log.Fields{"lDeviceId": lDeviceId})
129 // To prevent a race condition, let's hold the logical device agent map lock. This will prevent a loading and
130 // a create logical device callback from occurring at the same time.
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400131 if ldAgent, _ := ldMgr.logicalDeviceAgents.Load(lDeviceId); ldAgent == nil {
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500132 // Logical device not in memory - create a temp logical device Agent and let it load from memory
133 agent := newLogicalDeviceAgent(lDeviceId, "", ldMgr, ldMgr.deviceMgr, ldMgr.clusterDataProxy)
134 if err := agent.start(nil, true); err != nil {
135 agent.stop(nil)
136 return err
137 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400138 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceId, agent)
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500139 }
140 // TODO: load the child device
141 return nil
142}
143
Stephane Barbariea75791c2019-01-24 10:58:06 -0500144func (ldMgr *LogicalDeviceManager) getLogicalDeviceId(device *voltha.Device) (*string, error) {
145 // Device can either be a parent or a child device
146 if device.Root {
147 // Parent device. The ID of a parent device is the logical device ID
148 return &device.ParentId, nil
149 }
150 // Device is child device
151 // retrieve parent device using child device ID
152 if parentDevice := ldMgr.deviceMgr.getParentDevice(device); parentDevice != nil {
153 return &parentDevice.ParentId, nil
154 }
155 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
156}
157
158func (ldMgr *LogicalDeviceManager) getLogicalPortId(device *voltha.Device) (*voltha.LogicalPortId, error) {
159 // Get the logical device where this device is attached
160 var lDeviceId *string
161 var err error
162 if lDeviceId, err = ldMgr.getLogicalDeviceId(device); err != nil {
163 return nil, err
164 }
165 var lDevice *voltha.LogicalDevice
166 if lDevice, err = ldMgr.getLogicalDevice(*lDeviceId); err != nil {
167 return nil, err
168 }
169 // Go over list of ports
170 for _, port := range lDevice.Ports {
171 if port.DeviceId == device.Id {
172 return &voltha.LogicalPortId{Id: *lDeviceId, PortId: port.Id}, nil
173 }
174 }
175 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
176}
177
178func (ldMgr *LogicalDeviceManager) ListLogicalDevicePorts(ctx context.Context, id string) (*voltha.LogicalPorts, error) {
179 log.Debugw("ListLogicalDevicePorts", log.Fields{"logicaldeviceid": id})
180 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
181 return agent.ListLogicalDevicePorts()
182 }
183 return nil, status.Errorf(codes.NotFound, "%s", id)
184
185}
186
187func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlows(ctx context.Context, id string) (*voltha.Flows, error) {
188 log.Debugw("ListLogicalDeviceFlows", log.Fields{"logicaldeviceid": id})
189 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
190 return agent.ListLogicalDeviceFlows()
191 }
192 return nil, status.Errorf(codes.NotFound, "%s", id)
193
194}
195
196func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlowGroups(ctx context.Context, id string) (*voltha.FlowGroups, error) {
197 log.Debugw("ListLogicalDeviceFlowGroups", log.Fields{"logicaldeviceid": id})
198 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
199 return agent.ListLogicalDeviceFlowGroups()
200 }
201 return nil, status.Errorf(codes.NotFound, "%s", id)
202
203}
204
205func (ldMgr *LogicalDeviceManager) getLogicalPort(lPortId *voltha.LogicalPortId) (*voltha.LogicalPort, error) {
206 // Get the logical device where this device is attached
207 var err error
208 var lDevice *voltha.LogicalDevice
209 if lDevice, err = ldMgr.getLogicalDevice(lPortId.Id); err != nil {
210 return nil, err
211 }
212 // Go over list of ports
213 for _, port := range lDevice.Ports {
214 if port.Id == lPortId.PortId {
215 return port, nil
216 }
217 }
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400218 return nil, status.Errorf(codes.NotFound, "%s-%s", lPortId.Id, lPortId.PortId)
Stephane Barbariea75791c2019-01-24 10:58:06 -0500219}