blob: 936e945e183af9fcc078350311b087f1d5674d3e [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"
25 "github.com/opencord/voltha-go/protos/core_adapter"
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
39 kafkaProxy *kafka.KafkaMessagingProxy
40 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
khenaidoo4d4802d2018-10-04 21:59:49 -040046func newDeviceManager(kafkaProxy *kafka.KafkaMessagingProxy, 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)
50 deviceMgr.adapterProxy = NewAdapterProxy(kafkaProxy)
51 deviceMgr.kafkaProxy = kafkaProxy
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
252func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*core_adapter.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
269func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*core_adapter.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
326 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{ChannelId: uint32(channelId)}
327
328 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400329 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400330 dMgr.addDeviceAgentToMap(agent)
331 agent.start(nil)
332
333 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400334 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400335 return agent.enableDevice(nil)
336 }
337
338 return nil
339}
340
341func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
342 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400343 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
344 if handlers == nil {
345 log.Debugw("handlers-not-found", log.Fields{"deviceId": current.Id})
346 return nil
khenaidoob9203542018-09-17 22:56:37 -0400347 }
khenaidoo92e62c52018-10-03 14:02:54 -0400348 for _, handler := range handlers {
349 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
350 if err := handler(current); err != nil {
351 return err
352 }
353 }
khenaidoob9203542018-09-17 22:56:37 -0400354 return nil
355}
356
khenaidoo92e62c52018-10-03 14:02:54 -0400357func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400358 log.Info("createLogicalDevice")
359 var logicalId *string
360 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400361 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400362 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
363 return err
364 }
365 // Update the parent device with the logical id
366 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
367 return nil
368}
369
khenaidoo92e62c52018-10-03 14:02:54 -0400370func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
371 log.Info("deleteLogicalDevice")
372 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400373 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400374 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
375 return err
376 }
377 // Remove the logical device Id from the parent device
378 logicalId := ""
379 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
380 return nil
381}
382
khenaidoo19d7b632018-10-30 10:49:50 -0400383func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400384 log.Info("deleteLogicalPort")
385 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400386 // Get the logical port associated with this device
387 var lPortId *voltha.LogicalPortId
388 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
389 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id})
390 return err
391 }
392 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
393 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400394 return err
395 }
khenaidoo92e62c52018-10-03 14:02:54 -0400396 return nil
397}
398
399func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
400 // Sanity check
401 if childDevice.Root {
402 // childDevice is the parent device
403 return childDevice
404 }
khenaidoo19d7b632018-10-30 10:49:50 -0400405 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400406 return parentDevice
407}
408
khenaidoo4d4802d2018-10-04 21:59:49 -0400409/*
410All the functions below are callback functions where they are invoked with the latest and previous data. We can
411therefore use the data as is without trying to get the latest from the model.
412*/
413
414//disableAllChildDevices is invoked as a callback when the parent device is disabled
415func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400416 log.Debug("disableAllChildDevices")
417 var childDeviceIds []string
418 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400419 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
420 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400421 }
422 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400423 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400424 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400425 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400426 for _, childDeviceId := range childDeviceIds {
427 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
428 if err = agent.disableDevice(nil); err != nil {
429 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400430 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400431 }
432 }
433 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400434 if !allChildDisable {
435 return err
436 }
khenaidoo92e62c52018-10-03 14:02:54 -0400437 return nil
438}
439
khenaidoo4d4802d2018-10-04 21:59:49 -0400440//deleteAllChildDevices is invoked as a callback when the parent device is deleted
441func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
442 log.Debug("deleteAllChildDevices")
443 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400444 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400445 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
446 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400447 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400448 if len(childDeviceIds) == 0 {
449 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
450 }
451 allChildDeleted := true
452 for _, childDeviceId := range childDeviceIds {
453 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
454 if err = agent.deleteDevice(nil); err != nil {
455 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
456 allChildDeleted = false
457 } else {
458 agent.stop(nil)
459 dMgr.deleteDeviceAgentToMap(agent)
460 }
461 }
462 }
463 if !allChildDeleted {
464 return err
465 }
466 return nil
467}
468
469//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
470func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
471 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400472 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400473 if parentDevice != nil {
474 for _, port := range parentDevice.Ports {
475 for _, peer := range port.Peers {
476 childDeviceIds = append(childDeviceIds, peer.DeviceId)
477 }
khenaidoo92e62c52018-10-03 14:02:54 -0400478 }
479 }
480 return childDeviceIds, nil
481}
482
483func (dMgr *DeviceManager) addUNILogicalPort(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400484 log.Info("addUNILogicalPort")
khenaidoo4d4802d2018-10-04 21:59:49 -0400485 if err := dMgr.logicalDeviceMgr.addUNILogicalPort(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400486 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
487 return err
488 }
489 return nil
490}
491
khenaidoo92e62c52018-10-03 14:02:54 -0400492func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400493 log.Info("activateDevice")
494 return nil
495}
496
khenaidoo92e62c52018-10-03 14:02:54 -0400497func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
498 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400499 return nil
500}
501
khenaidoo92e62c52018-10-03 14:02:54 -0400502func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400503 log.Info("abandonDevice")
504 return nil
505}
506
khenaidoo92e62c52018-10-03 14:02:54 -0400507func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400508 log.Info("reEnableDevice")
509 return nil
510}
511
khenaidoo92e62c52018-10-03 14:02:54 -0400512func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400513 log.Info("noOp")
514 return nil
515}
516
khenaidoo92e62c52018-10-03 14:02:54 -0400517func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400518 log.Info("notAllowed")
519 return errors.New("Transition-not-allowed")
520}
521
522func funcName(f interface{}) string {
523 p := reflect.ValueOf(f).Pointer()
524 rf := runtime.FuncForPC(p)
525 return rf.Name()
526}
527
528func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
529 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
530 agent.updateDeviceAttribute(attribute, value)
531 }
532}
533
534func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -0400535 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400536 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -0400537 return &device.ParentId
538 }
539 return nil
540}