blob: c4ac343e097048a36c59f5d18a7023803c63259d [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
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400326
327 //Get parent device type
328 parent, err := dMgr.GetDevice(parentDeviceId)
329 if err != nil {
330 log.Error("no-parent-found", log.Fields{"parentId":parentDeviceId})
331 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 {
khenaidoob9203542018-09-17 22:56:37 -0400343 return agent.enableDevice(nil)
344 }
345
346 return nil
347}
348
349func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
350 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400351 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
352 if handlers == nil {
353 log.Debugw("handlers-not-found", log.Fields{"deviceId": current.Id})
354 return nil
khenaidoob9203542018-09-17 22:56:37 -0400355 }
khenaidoo92e62c52018-10-03 14:02:54 -0400356 for _, handler := range handlers {
357 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
358 if err := handler(current); err != nil {
359 return err
360 }
361 }
khenaidoob9203542018-09-17 22:56:37 -0400362 return nil
363}
364
khenaidoofdbad6e2018-11-06 22:26:38 -0500365func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
366 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
367 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
368 return agent.packetOut(outPort, packet)
369 }
370 return status.Errorf(codes.NotFound, "%s", deviceId)
371}
372
373func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, packet []byte) error {
374 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
375 // Get the logical device Id based on the deviceId
376 var device *voltha.Device
377 var err error
378 if device, err = dMgr.GetDevice(deviceId); err != nil {
379 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
380 return err
381 }
382 if !device.Root{
383 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
384 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
385 }
386
387 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, packet); err != nil {
388 return err
389 }
390 return nil
391}
392
khenaidoo92e62c52018-10-03 14:02:54 -0400393func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400394 log.Info("createLogicalDevice")
395 var logicalId *string
396 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400397 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400398 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
399 return err
400 }
401 // Update the parent device with the logical id
402 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
403 return nil
404}
405
khenaidoo92e62c52018-10-03 14:02:54 -0400406func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
407 log.Info("deleteLogicalDevice")
408 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400409 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400410 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
411 return err
412 }
413 // Remove the logical device Id from the parent device
414 logicalId := ""
415 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
416 return nil
417}
418
khenaidoo19d7b632018-10-30 10:49:50 -0400419func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400420 log.Info("deleteLogicalPort")
421 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400422 // Get the logical port associated with this device
423 var lPortId *voltha.LogicalPortId
424 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400425 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400426 return err
427 }
428 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
429 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400430 return err
431 }
khenaidoo92e62c52018-10-03 14:02:54 -0400432 return nil
433}
434
435func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
436 // Sanity check
437 if childDevice.Root {
438 // childDevice is the parent device
439 return childDevice
440 }
khenaidoo19d7b632018-10-30 10:49:50 -0400441 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400442 return parentDevice
443}
444
khenaidoo4d4802d2018-10-04 21:59:49 -0400445/*
446All the functions below are callback functions where they are invoked with the latest and previous data. We can
447therefore use the data as is without trying to get the latest from the model.
448*/
449
450//disableAllChildDevices is invoked as a callback when the parent device is disabled
451func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400452 log.Debug("disableAllChildDevices")
453 var childDeviceIds []string
454 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400455 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
456 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400457 }
458 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400459 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400460 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400461 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400462 for _, childDeviceId := range childDeviceIds {
463 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
464 if err = agent.disableDevice(nil); err != nil {
465 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400466 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400467 }
468 }
469 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400470 if !allChildDisable {
471 return err
472 }
khenaidoo92e62c52018-10-03 14:02:54 -0400473 return nil
474}
475
khenaidoo4d4802d2018-10-04 21:59:49 -0400476//deleteAllChildDevices is invoked as a callback when the parent device is deleted
477func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
478 log.Debug("deleteAllChildDevices")
479 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400480 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400481 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
482 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400483 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400484 if len(childDeviceIds) == 0 {
485 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
486 }
487 allChildDeleted := true
488 for _, childDeviceId := range childDeviceIds {
489 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
490 if err = agent.deleteDevice(nil); err != nil {
491 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
492 allChildDeleted = false
493 } else {
494 agent.stop(nil)
495 dMgr.deleteDeviceAgentToMap(agent)
496 }
497 }
498 }
499 if !allChildDeleted {
500 return err
501 }
502 return nil
503}
504
505//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
506func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
507 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400508 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400509 if parentDevice != nil {
510 for _, port := range parentDevice.Ports {
511 for _, peer := range port.Peers {
512 childDeviceIds = append(childDeviceIds, peer.DeviceId)
513 }
khenaidoo92e62c52018-10-03 14:02:54 -0400514 }
515 }
516 return childDeviceIds, nil
517}
518
519func (dMgr *DeviceManager) addUNILogicalPort(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400520 log.Info("addUNILogicalPort")
khenaidoo4d4802d2018-10-04 21:59:49 -0400521 if err := dMgr.logicalDeviceMgr.addUNILogicalPort(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400522 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
523 return err
524 }
525 return nil
526}
527
khenaidoo92e62c52018-10-03 14:02:54 -0400528func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400529 log.Info("activateDevice")
530 return nil
531}
532
khenaidoo92e62c52018-10-03 14:02:54 -0400533func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
534 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400535 return nil
536}
537
khenaidoo92e62c52018-10-03 14:02:54 -0400538func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400539 log.Info("abandonDevice")
540 return nil
541}
542
khenaidoo92e62c52018-10-03 14:02:54 -0400543func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400544 log.Info("reEnableDevice")
545 return nil
546}
547
khenaidoo92e62c52018-10-03 14:02:54 -0400548func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400549 log.Info("noOp")
550 return nil
551}
552
khenaidoo92e62c52018-10-03 14:02:54 -0400553func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400554 log.Info("notAllowed")
555 return errors.New("Transition-not-allowed")
556}
557
558func funcName(f interface{}) string {
559 p := reflect.ValueOf(f).Pointer()
560 rf := runtime.FuncForPC(p)
561 return rf.Name()
562}
563
564func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
565 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
566 agent.updateDeviceAttribute(attribute, value)
567 }
568}
569
570func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -0400571 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400572 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -0400573 return &device.ParentId
574 }
575 return nil
576}