blob: 45584a121ba7d2d1e87602d3712864e33ff99257 [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
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"
20 "errors"
khenaidoo92e62c52018-10-03 14:02:54 -040021 "github.com/gogo/protobuf/proto"
khenaidoob9203542018-09-17 22:56:37 -040022 "github.com/opencord/voltha-go/common/log"
23 "github.com/opencord/voltha-go/db/model"
24 "github.com/opencord/voltha-go/kafka"
khenaidoo79232702018-12-04 11:00:41 -050025 ic "github.com/opencord/voltha-go/protos/inter_container"
khenaidoo19d7b632018-10-30 10:49:50 -040026 ofp "github.com/opencord/voltha-go/protos/openflow_13"
khenaidoob9203542018-09-17 22:56:37 -040027 "github.com/opencord/voltha-go/protos/voltha"
28 "google.golang.org/grpc/codes"
29 "google.golang.org/grpc/status"
30 "reflect"
31 "runtime"
32 "sync"
33)
34
35type DeviceManager struct {
36 deviceAgents map[string]*DeviceAgent
37 adapterProxy *AdapterProxy
38 logicalDeviceMgr *LogicalDeviceManager
khenaidoo43c82122018-11-22 18:38:28 -050039 kafkaICProxy *kafka.InterContainerProxy
khenaidoob9203542018-09-17 22:56:37 -040040 stateTransitions *TransitionMap
khenaidoo9a468962018-09-19 15:33:13 -040041 clusterDataProxy *model.Proxy
khenaidoob9203542018-09-17 22:56:37 -040042 exitChannel chan int
43 lockDeviceAgentsMap sync.RWMutex
44}
45
khenaidoo43c82122018-11-22 18:38:28 -050046func newDeviceManager(kafkaICProxy *kafka.InterContainerProxy, cdProxy *model.Proxy) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040047 var deviceMgr DeviceManager
48 deviceMgr.exitChannel = make(chan int, 1)
49 deviceMgr.deviceAgents = make(map[string]*DeviceAgent)
khenaidoo43c82122018-11-22 18:38:28 -050050 deviceMgr.adapterProxy = NewAdapterProxy(kafkaICProxy)
51 deviceMgr.kafkaICProxy = kafkaICProxy
khenaidoo9a468962018-09-19 15:33:13 -040052 deviceMgr.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040053 deviceMgr.lockDeviceAgentsMap = sync.RWMutex{}
54 return &deviceMgr
55}
56
khenaidoo4d4802d2018-10-04 21:59:49 -040057func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040058 log.Info("starting-device-manager")
59 dMgr.logicalDeviceMgr = logicalDeviceMgr
60 dMgr.stateTransitions = NewTransitionMap(dMgr)
61 log.Info("device-manager-started")
62}
63
khenaidoo4d4802d2018-10-04 21:59:49 -040064func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040065 log.Info("stopping-device-manager")
66 dMgr.exitChannel <- 1
67 log.Info("device-manager-stopped")
68}
69
70func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
71 if ctx.Err() == nil {
72 // Returned response only of the ctx has not been cancelled/timeout/etc
73 // Channel is automatically closed when a context is Done
74 ch <- result
75 log.Debugw("sendResponse", log.Fields{"result": result})
76 } else {
77 // Should the transaction be reverted back?
78 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
79 }
80}
81
82func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
83 dMgr.lockDeviceAgentsMap.Lock()
84 defer dMgr.lockDeviceAgentsMap.Unlock()
85 if _, exist := dMgr.deviceAgents[agent.deviceId]; !exist {
86 dMgr.deviceAgents[agent.deviceId] = agent
87 }
88}
89
khenaidoo4d4802d2018-10-04 21:59:49 -040090func (dMgr *DeviceManager) deleteDeviceAgentToMap(agent *DeviceAgent) {
91 dMgr.lockDeviceAgentsMap.Lock()
92 defer dMgr.lockDeviceAgentsMap.Unlock()
93 delete(dMgr.deviceAgents, agent.deviceId)
94}
95
khenaidoob9203542018-09-17 22:56:37 -040096func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
khenaidoo4d4802d2018-10-04 21:59:49 -040097 // TODO If the device is not in memory it needs to be loaded first
khenaidoob9203542018-09-17 22:56:37 -040098 dMgr.lockDeviceAgentsMap.Lock()
99 defer dMgr.lockDeviceAgentsMap.Unlock()
100 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
101 return agent
102 }
103 return nil
104}
105
106func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400107 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400108
109 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400110 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400111 dMgr.addDeviceAgentToMap(agent)
112 agent.start(ctx)
113
khenaidoo92e62c52018-10-03 14:02:54 -0400114 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400115}
116
117func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400118 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400119 var res interface{}
120 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
121 res = agent.enableDevice(ctx)
122 log.Debugw("EnableDevice-result", log.Fields{"result": res})
123 } else {
124 res = status.Errorf(codes.NotFound, "%s", id.Id)
125 }
126
127 sendResponse(ctx, ch, res)
128}
129
khenaidoo92e62c52018-10-03 14:02:54 -0400130func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
131 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400132 var res interface{}
133 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
134 res = agent.disableDevice(ctx)
135 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400136 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400137 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400138 }
khenaidoo92e62c52018-10-03 14:02:54 -0400139
140 sendResponse(ctx, ch, res)
141}
142
khenaidoo4d4802d2018-10-04 21:59:49 -0400143func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
144 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
145 var res interface{}
146 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
147 res = agent.rebootDevice(ctx)
148 log.Debugw("rebootDevice-result", log.Fields{"result": res})
149 } else {
150 res = status.Errorf(codes.NotFound, "%s", id.Id)
151 }
152 sendResponse(ctx, ch, res)
153}
154
155func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
156 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
157 var res interface{}
158 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
159 res = agent.deleteDevice(ctx)
160 if res == nil { //Success
161 agent.stop(ctx)
162 dMgr.deleteDeviceAgentToMap(agent)
163 }
164 log.Debugw("deleteDevice-result", log.Fields{"result": res})
165 } else {
166 res = status.Errorf(codes.NotFound, "%s", id.Id)
167 }
168 sendResponse(ctx, ch, res)
169}
170
khenaidoo19d7b632018-10-30 10:49:50 -0400171func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
172 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400173 if agent := dMgr.getDeviceAgent(id); agent != nil {
174 return agent.getDevice()
175 }
176 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400177}
178
khenaidoo19d7b632018-10-30 10:49:50 -0400179func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
180 device, err := dMgr.GetDevice(id)
181 if err != nil {
182 return false, err
183 }
184 return device.Root, nil
185}
186
khenaidoob9203542018-09-17 22:56:37 -0400187func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400188 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400189 result := &voltha.Devices{}
190 dMgr.lockDeviceAgentsMap.Lock()
191 defer dMgr.lockDeviceAgentsMap.Unlock()
192 for _, agent := range dMgr.deviceAgents {
khenaidoo92e62c52018-10-03 14:02:54 -0400193 if device, err := agent.getDevice(); err == nil {
194 cloned := proto.Clone(device).(*voltha.Device)
195 result.Items = append(result.Items, cloned)
khenaidoob9203542018-09-17 22:56:37 -0400196 }
197 }
198 return result, nil
199}
200
201func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400202 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400203 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
204 return agent.updateDevice(device)
205 }
206 return status.Errorf(codes.NotFound, "%s", device.Id)
207}
208
209func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
210 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400211 if err := agent.addPort(port); err != nil {
212 return err
213 }
214 // Setup peer ports
215 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
216 for _, peerPort := range port.Peers {
217 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
218 if err := agent.addPeerPort(meAsPeer); err != nil {
219 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
220 return err
221 }
222 }
223 }
224 return nil
225 } else {
226 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400227 }
khenaidoob9203542018-09-17 22:56:37 -0400228}
229
khenaidoo19d7b632018-10-30 10:49:50 -0400230func (dMgr *DeviceManager) updateFlows(deviceId string, flows []*ofp.OfpFlowStats) error {
231 log.Debugw("updateFlows", log.Fields{"deviceid": deviceId})
232 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
233 return agent.updateFlows(flows)
234 }
235 return status.Errorf(codes.NotFound, "%s", deviceId)
236}
237
238func (dMgr *DeviceManager) updateGroups(deviceId string, groups []*ofp.OfpGroupEntry) error {
239 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
240 return agent.updateGroups(groups)
241 }
242 return status.Errorf(codes.NotFound, "%s", deviceId)
243}
244
khenaidoob9203542018-09-17 22:56:37 -0400245func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
246 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
247 return agent.updatePmConfigs(pmConfigs)
248 }
249 return status.Errorf(codes.NotFound, "%s", deviceId)
250}
251
khenaidoo79232702018-12-04 11:00:41 -0500252func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400253 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400254 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
255 return agent.getSwitchCapability(ctx)
256 }
257 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
258}
259
khenaidoo92e62c52018-10-03 14:02:54 -0400260func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
261 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400262 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400263 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400264 }
265 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400266
khenaidoob9203542018-09-17 22:56:37 -0400267}
268
khenaidoo79232702018-12-04 11:00:41 -0500269func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400270 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400271 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
272 return agent.getPortCapability(ctx, portNo)
273 }
274 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
275}
276
khenaidoo92e62c52018-10-03 14:02:54 -0400277func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
278 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400279 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400280 return agent.updateDeviceStatus(operStatus, connStatus)
281 }
282 return status.Errorf(codes.NotFound, "%s", deviceId)
283}
284
khenaidoo4d4802d2018-10-04 21:59:49 -0400285func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
286 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
287 var parentDevice *voltha.Device
288 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400289 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400290 return status.Errorf(codes.Aborted, "%s", err.Error())
291 }
292 var childDeviceIds []string
293 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
294 return status.Errorf(codes.Aborted, "%s", err.Error())
295 }
296 if len(childDeviceIds) == 0 {
297 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
298 }
299 for _, childDeviceId := range childDeviceIds {
300 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
301 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
302 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
303 }
304 }
305 }
306 return nil
307}
308
khenaidoo92e62c52018-10-03 14:02:54 -0400309func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
310 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
311 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
312 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400313 }
314 return status.Errorf(codes.NotFound, "%s", deviceId)
315}
316
317func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string, channelId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400318 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400319
320 // Create the ONU device
321 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400322 childDevice.Type = deviceType
323 childDevice.ParentId = parentDeviceId
324 childDevice.ParentPortNo = uint32(parentPortNo)
325 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400326
327 //Get parent device type
328 parent, err := dMgr.GetDevice(parentDeviceId)
329 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500330 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400331 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
332 }
333
334 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId)}
khenaidoob9203542018-09-17 22:56:37 -0400335
336 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400337 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400338 dMgr.addDeviceAgentToMap(agent)
339 agent.start(nil)
340
341 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400342 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500343 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400344 }
345
khenaidoo79232702018-12-04 11:00:41 -0500346 // Publish on the messaging bus that we have discovered new devices
347 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId)
348
khenaidoob9203542018-09-17 22:56:37 -0400349 return nil
350}
351
352func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
353 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400354 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
355 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500356 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400357 return nil
khenaidoob9203542018-09-17 22:56:37 -0400358 }
khenaidoo92e62c52018-10-03 14:02:54 -0400359 for _, handler := range handlers {
360 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
361 if err := handler(current); err != nil {
362 return err
363 }
364 }
khenaidoob9203542018-09-17 22:56:37 -0400365 return nil
366}
367
khenaidoofdbad6e2018-11-06 22:26:38 -0500368func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
369 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
370 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
371 return agent.packetOut(outPort, packet)
372 }
373 return status.Errorf(codes.NotFound, "%s", deviceId)
374}
375
376func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, packet []byte) error {
377 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
378 // Get the logical device Id based on the deviceId
379 var device *voltha.Device
380 var err error
381 if device, err = dMgr.GetDevice(deviceId); err != nil {
382 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
383 return err
384 }
khenaidoo43c82122018-11-22 18:38:28 -0500385 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500386 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
387 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
388 }
389
390 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, packet); err != nil {
391 return err
392 }
393 return nil
394}
395
khenaidoo92e62c52018-10-03 14:02:54 -0400396func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400397 log.Info("createLogicalDevice")
398 var logicalId *string
399 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400400 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400401 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
402 return err
403 }
404 // Update the parent device with the logical id
405 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
406 return nil
407}
408
khenaidoo92e62c52018-10-03 14:02:54 -0400409func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
410 log.Info("deleteLogicalDevice")
411 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400412 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400413 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
414 return err
415 }
416 // Remove the logical device Id from the parent device
417 logicalId := ""
418 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
419 return nil
420}
421
khenaidoo19d7b632018-10-30 10:49:50 -0400422func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400423 log.Info("deleteLogicalPort")
424 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400425 // Get the logical port associated with this device
426 var lPortId *voltha.LogicalPortId
427 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400428 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400429 return err
430 }
431 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
432 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400433 return err
434 }
khenaidoo92e62c52018-10-03 14:02:54 -0400435 return nil
436}
437
438func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
439 // Sanity check
440 if childDevice.Root {
441 // childDevice is the parent device
442 return childDevice
443 }
khenaidoo19d7b632018-10-30 10:49:50 -0400444 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400445 return parentDevice
446}
447
khenaidoo4d4802d2018-10-04 21:59:49 -0400448/*
449All the functions below are callback functions where they are invoked with the latest and previous data. We can
450therefore use the data as is without trying to get the latest from the model.
451*/
452
453//disableAllChildDevices is invoked as a callback when the parent device is disabled
454func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400455 log.Debug("disableAllChildDevices")
456 var childDeviceIds []string
457 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400458 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
459 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400460 }
461 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400462 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400463 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400464 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400465 for _, childDeviceId := range childDeviceIds {
466 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
467 if err = agent.disableDevice(nil); err != nil {
468 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400469 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400470 }
471 }
472 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400473 if !allChildDisable {
474 return err
475 }
khenaidoo92e62c52018-10-03 14:02:54 -0400476 return nil
477}
478
khenaidoo4d4802d2018-10-04 21:59:49 -0400479//deleteAllChildDevices is invoked as a callback when the parent device is deleted
480func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
481 log.Debug("deleteAllChildDevices")
482 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400483 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400484 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
485 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400486 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400487 if len(childDeviceIds) == 0 {
488 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
489 }
490 allChildDeleted := true
491 for _, childDeviceId := range childDeviceIds {
492 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
493 if err = agent.deleteDevice(nil); err != nil {
494 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
495 allChildDeleted = false
496 } else {
497 agent.stop(nil)
498 dMgr.deleteDeviceAgentToMap(agent)
499 }
500 }
501 }
502 if !allChildDeleted {
503 return err
504 }
505 return nil
506}
507
508//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
509func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
510 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400511 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400512 if parentDevice != nil {
513 for _, port := range parentDevice.Ports {
514 for _, peer := range port.Peers {
515 childDeviceIds = append(childDeviceIds, peer.DeviceId)
516 }
khenaidoo92e62c52018-10-03 14:02:54 -0400517 }
518 }
519 return childDeviceIds, nil
520}
521
522func (dMgr *DeviceManager) addUNILogicalPort(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400523 log.Info("addUNILogicalPort")
khenaidoo4d4802d2018-10-04 21:59:49 -0400524 if err := dMgr.logicalDeviceMgr.addUNILogicalPort(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400525 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
526 return err
527 }
528 return nil
529}
530
khenaidoo92e62c52018-10-03 14:02:54 -0400531func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400532 log.Info("activateDevice")
533 return nil
534}
535
khenaidoo92e62c52018-10-03 14:02:54 -0400536func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
537 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400538 return nil
539}
540
khenaidoo92e62c52018-10-03 14:02:54 -0400541func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400542 log.Info("abandonDevice")
543 return nil
544}
545
khenaidoo92e62c52018-10-03 14:02:54 -0400546func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400547 log.Info("reEnableDevice")
548 return nil
549}
550
khenaidoo92e62c52018-10-03 14:02:54 -0400551func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400552 log.Info("noOp")
553 return nil
554}
555
khenaidoo92e62c52018-10-03 14:02:54 -0400556func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400557 log.Info("notAllowed")
558 return errors.New("Transition-not-allowed")
559}
560
561func funcName(f interface{}) string {
562 p := reflect.ValueOf(f).Pointer()
563 rf := runtime.FuncForPC(p)
564 return rf.Name()
565}
566
567func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
568 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
569 agent.updateDeviceAttribute(attribute, value)
570 }
571}
572
573func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -0400574 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400575 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -0400576 return &device.ParentId
577 }
578 return nil
579}