blob: 682de4874fe18f270796c619318603b077638786 [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"
21 "github.com/opencord/voltha-go/common/log"
22 "github.com/opencord/voltha-go/db/model"
23 "github.com/opencord/voltha-go/kafka"
khenaidoo79232702018-12-04 11:00:41 -050024 ic "github.com/opencord/voltha-go/protos/inter_container"
khenaidoo19d7b632018-10-30 10:49:50 -040025 ofp "github.com/opencord/voltha-go/protos/openflow_13"
khenaidoob9203542018-09-17 22:56:37 -040026 "github.com/opencord/voltha-go/protos/voltha"
27 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/status"
29 "reflect"
30 "runtime"
31 "sync"
32)
33
34type DeviceManager struct {
35 deviceAgents map[string]*DeviceAgent
36 adapterProxy *AdapterProxy
37 logicalDeviceMgr *LogicalDeviceManager
khenaidoo43c82122018-11-22 18:38:28 -050038 kafkaICProxy *kafka.InterContainerProxy
khenaidoob9203542018-09-17 22:56:37 -040039 stateTransitions *TransitionMap
khenaidoo9a468962018-09-19 15:33:13 -040040 clusterDataProxy *model.Proxy
khenaidoob9203542018-09-17 22:56:37 -040041 exitChannel chan int
42 lockDeviceAgentsMap sync.RWMutex
43}
44
khenaidoo43c82122018-11-22 18:38:28 -050045func newDeviceManager(kafkaICProxy *kafka.InterContainerProxy, cdProxy *model.Proxy) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040046 var deviceMgr DeviceManager
47 deviceMgr.exitChannel = make(chan int, 1)
48 deviceMgr.deviceAgents = make(map[string]*DeviceAgent)
khenaidoo43c82122018-11-22 18:38:28 -050049 deviceMgr.adapterProxy = NewAdapterProxy(kafkaICProxy)
50 deviceMgr.kafkaICProxy = kafkaICProxy
khenaidoo9a468962018-09-19 15:33:13 -040051 deviceMgr.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040052 deviceMgr.lockDeviceAgentsMap = sync.RWMutex{}
53 return &deviceMgr
54}
55
khenaidoo4d4802d2018-10-04 21:59:49 -040056func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040057 log.Info("starting-device-manager")
58 dMgr.logicalDeviceMgr = logicalDeviceMgr
59 dMgr.stateTransitions = NewTransitionMap(dMgr)
60 log.Info("device-manager-started")
61}
62
khenaidoo4d4802d2018-10-04 21:59:49 -040063func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040064 log.Info("stopping-device-manager")
65 dMgr.exitChannel <- 1
66 log.Info("device-manager-stopped")
67}
68
69func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
70 if ctx.Err() == nil {
71 // Returned response only of the ctx has not been cancelled/timeout/etc
72 // Channel is automatically closed when a context is Done
73 ch <- result
74 log.Debugw("sendResponse", log.Fields{"result": result})
75 } else {
76 // Should the transaction be reverted back?
77 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
78 }
79}
80
81func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
82 dMgr.lockDeviceAgentsMap.Lock()
83 defer dMgr.lockDeviceAgentsMap.Unlock()
84 if _, exist := dMgr.deviceAgents[agent.deviceId]; !exist {
85 dMgr.deviceAgents[agent.deviceId] = agent
86 }
87}
88
khenaidoo4d4802d2018-10-04 21:59:49 -040089func (dMgr *DeviceManager) deleteDeviceAgentToMap(agent *DeviceAgent) {
90 dMgr.lockDeviceAgentsMap.Lock()
91 defer dMgr.lockDeviceAgentsMap.Unlock()
92 delete(dMgr.deviceAgents, agent.deviceId)
93}
94
khenaidoob9203542018-09-17 22:56:37 -040095func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
khenaidoo4d4802d2018-10-04 21:59:49 -040096 // TODO If the device is not in memory it needs to be loaded first
khenaidoob9203542018-09-17 22:56:37 -040097 dMgr.lockDeviceAgentsMap.Lock()
98 defer dMgr.lockDeviceAgentsMap.Unlock()
99 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
100 return agent
101 }
102 return nil
103}
104
105func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400106 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400107
108 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400109 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400110 dMgr.addDeviceAgentToMap(agent)
111 agent.start(ctx)
112
khenaidoo92e62c52018-10-03 14:02:54 -0400113 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400114}
115
116func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400117 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400118 var res interface{}
119 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
120 res = agent.enableDevice(ctx)
121 log.Debugw("EnableDevice-result", log.Fields{"result": res})
122 } else {
123 res = status.Errorf(codes.NotFound, "%s", id.Id)
124 }
125
126 sendResponse(ctx, ch, res)
127}
128
khenaidoo92e62c52018-10-03 14:02:54 -0400129func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
130 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400131 var res interface{}
132 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
133 res = agent.disableDevice(ctx)
134 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400135 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400136 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400137 }
khenaidoo92e62c52018-10-03 14:02:54 -0400138
139 sendResponse(ctx, ch, res)
140}
141
khenaidoo4d4802d2018-10-04 21:59:49 -0400142func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
143 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
144 var res interface{}
145 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
146 res = agent.rebootDevice(ctx)
147 log.Debugw("rebootDevice-result", log.Fields{"result": res})
148 } else {
149 res = status.Errorf(codes.NotFound, "%s", id.Id)
150 }
151 sendResponse(ctx, ch, res)
152}
153
154func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
155 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
156 var res interface{}
157 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
158 res = agent.deleteDevice(ctx)
159 if res == nil { //Success
160 agent.stop(ctx)
161 dMgr.deleteDeviceAgentToMap(agent)
162 }
163 log.Debugw("deleteDevice-result", log.Fields{"result": res})
164 } else {
165 res = status.Errorf(codes.NotFound, "%s", id.Id)
166 }
167 sendResponse(ctx, ch, res)
168}
169
khenaidoo19d7b632018-10-30 10:49:50 -0400170func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
171 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400172 if agent := dMgr.getDeviceAgent(id); agent != nil {
173 return agent.getDevice()
174 }
175 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400176}
177
khenaidoo19d7b632018-10-30 10:49:50 -0400178func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
179 device, err := dMgr.GetDevice(id)
180 if err != nil {
181 return false, err
182 }
183 return device.Root, nil
184}
185
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500186// GetDevice retrieves the latest device information from the data model
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{}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500190 if devices := dMgr.clusterDataProxy.Get("/devices", 0, false, ""); devices != nil {
191 for _, device := range devices.([]interface{}) {
192 if agent := dMgr.getDeviceAgent(device.(*voltha.Device).Id); agent == nil {
193 agent = newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy)
194 dMgr.addDeviceAgentToMap(agent)
195 agent.start(nil)
196 }
197 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400198 }
199 }
200 return result, nil
201}
202
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500203//func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
204// log.Debug("ListDevices")
205// result := &voltha.Devices{}
206// dMgr.lockDeviceAgentsMap.Lock()
207// defer dMgr.lockDeviceAgentsMap.Unlock()
208// for _, agent := range dMgr.deviceAgents {
209// if device, err := agent.getDevice(); err == nil {
210// //cloned := proto.Clone(device).(*voltha.Device)
211// result.Items = append(result.Items, device)
212// }
213// }
214// return result, nil
215//}
216
khenaidoob9203542018-09-17 22:56:37 -0400217func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400218 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400219 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
220 return agent.updateDevice(device)
221 }
222 return status.Errorf(codes.NotFound, "%s", device.Id)
223}
224
225func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
226 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400227 if err := agent.addPort(port); err != nil {
228 return err
229 }
230 // Setup peer ports
231 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
232 for _, peerPort := range port.Peers {
233 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
234 if err := agent.addPeerPort(meAsPeer); err != nil {
235 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
236 return err
237 }
238 }
239 }
240 return nil
241 } else {
242 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400243 }
khenaidoob9203542018-09-17 22:56:37 -0400244}
245
khenaidoo19d7b632018-10-30 10:49:50 -0400246func (dMgr *DeviceManager) updateFlows(deviceId string, flows []*ofp.OfpFlowStats) error {
247 log.Debugw("updateFlows", log.Fields{"deviceid": deviceId})
248 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
249 return agent.updateFlows(flows)
250 }
251 return status.Errorf(codes.NotFound, "%s", deviceId)
252}
253
254func (dMgr *DeviceManager) updateGroups(deviceId string, groups []*ofp.OfpGroupEntry) error {
255 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
256 return agent.updateGroups(groups)
257 }
258 return status.Errorf(codes.NotFound, "%s", deviceId)
259}
260
khenaidoob9203542018-09-17 22:56:37 -0400261func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
262 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
263 return agent.updatePmConfigs(pmConfigs)
264 }
265 return status.Errorf(codes.NotFound, "%s", deviceId)
266}
267
khenaidoo79232702018-12-04 11:00:41 -0500268func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400269 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400270 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
271 return agent.getSwitchCapability(ctx)
272 }
273 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
274}
275
khenaidoo92e62c52018-10-03 14:02:54 -0400276func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
277 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400278 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400279 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400280 }
281 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400282
khenaidoob9203542018-09-17 22:56:37 -0400283}
284
khenaidoo79232702018-12-04 11:00:41 -0500285func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400286 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400287 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
288 return agent.getPortCapability(ctx, portNo)
289 }
290 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
291}
292
khenaidoo92e62c52018-10-03 14:02:54 -0400293func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
294 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400295 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400296 return agent.updateDeviceStatus(operStatus, connStatus)
297 }
298 return status.Errorf(codes.NotFound, "%s", deviceId)
299}
300
khenaidoo4d4802d2018-10-04 21:59:49 -0400301func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
302 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
303 var parentDevice *voltha.Device
304 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400305 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400306 return status.Errorf(codes.Aborted, "%s", err.Error())
307 }
308 var childDeviceIds []string
309 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
310 return status.Errorf(codes.Aborted, "%s", err.Error())
311 }
312 if len(childDeviceIds) == 0 {
313 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
314 }
315 for _, childDeviceId := range childDeviceIds {
316 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
317 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
318 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
319 }
320 }
321 }
322 return nil
323}
324
khenaidoo92e62c52018-10-03 14:02:54 -0400325func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
326 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
327 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
328 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400329 }
330 return status.Errorf(codes.NotFound, "%s", deviceId)
331}
332
333func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string, channelId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400334 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400335
336 // Create the ONU device
337 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400338 childDevice.Type = deviceType
339 childDevice.ParentId = parentDeviceId
340 childDevice.ParentPortNo = uint32(parentPortNo)
341 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400342
343 //Get parent device type
344 parent, err := dMgr.GetDevice(parentDeviceId)
345 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500346 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400347 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
348 }
349
350 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId)}
khenaidoob9203542018-09-17 22:56:37 -0400351
352 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400353 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400354 dMgr.addDeviceAgentToMap(agent)
355 agent.start(nil)
356
357 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400358 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500359 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400360 }
361
khenaidoo79232702018-12-04 11:00:41 -0500362 // Publish on the messaging bus that we have discovered new devices
363 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId)
364
khenaidoob9203542018-09-17 22:56:37 -0400365 return nil
366}
367
368func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
369 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400370 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
371 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500372 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400373 return nil
khenaidoob9203542018-09-17 22:56:37 -0400374 }
khenaidoo92e62c52018-10-03 14:02:54 -0400375 for _, handler := range handlers {
376 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
377 if err := handler(current); err != nil {
378 return err
379 }
380 }
khenaidoob9203542018-09-17 22:56:37 -0400381 return nil
382}
383
khenaidoofdbad6e2018-11-06 22:26:38 -0500384func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
385 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
386 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
387 return agent.packetOut(outPort, packet)
388 }
389 return status.Errorf(codes.NotFound, "%s", deviceId)
390}
391
392func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, packet []byte) error {
393 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
394 // Get the logical device Id based on the deviceId
395 var device *voltha.Device
396 var err error
397 if device, err = dMgr.GetDevice(deviceId); err != nil {
398 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
399 return err
400 }
khenaidoo43c82122018-11-22 18:38:28 -0500401 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500402 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
403 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
404 }
405
406 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, packet); err != nil {
407 return err
408 }
409 return nil
410}
411
khenaidoo92e62c52018-10-03 14:02:54 -0400412func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400413 log.Info("createLogicalDevice")
414 var logicalId *string
415 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400416 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400417 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
418 return err
419 }
420 // Update the parent device with the logical id
421 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
422 return nil
423}
424
khenaidoo92e62c52018-10-03 14:02:54 -0400425func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
426 log.Info("deleteLogicalDevice")
427 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400428 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400429 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
430 return err
431 }
432 // Remove the logical device Id from the parent device
433 logicalId := ""
434 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
435 return nil
436}
437
khenaidoo19d7b632018-10-30 10:49:50 -0400438func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400439 log.Info("deleteLogicalPort")
440 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400441 // Get the logical port associated with this device
442 var lPortId *voltha.LogicalPortId
443 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400444 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400445 return err
446 }
447 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
448 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400449 return err
450 }
khenaidoo92e62c52018-10-03 14:02:54 -0400451 return nil
452}
453
454func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
455 // Sanity check
456 if childDevice.Root {
457 // childDevice is the parent device
458 return childDevice
459 }
khenaidoo19d7b632018-10-30 10:49:50 -0400460 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400461 return parentDevice
462}
463
khenaidoo4d4802d2018-10-04 21:59:49 -0400464/*
465All the functions below are callback functions where they are invoked with the latest and previous data. We can
466therefore use the data as is without trying to get the latest from the model.
467*/
468
469//disableAllChildDevices is invoked as a callback when the parent device is disabled
470func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400471 log.Debug("disableAllChildDevices")
472 var childDeviceIds []string
473 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400474 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
475 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400476 }
477 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400478 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400479 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400480 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400481 for _, childDeviceId := range childDeviceIds {
482 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
483 if err = agent.disableDevice(nil); err != nil {
484 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400485 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400486 }
487 }
488 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400489 if !allChildDisable {
490 return err
491 }
khenaidoo92e62c52018-10-03 14:02:54 -0400492 return nil
493}
494
khenaidoo4d4802d2018-10-04 21:59:49 -0400495//deleteAllChildDevices is invoked as a callback when the parent device is deleted
496func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
497 log.Debug("deleteAllChildDevices")
498 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400499 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400500 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
501 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400502 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400503 if len(childDeviceIds) == 0 {
504 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
505 }
506 allChildDeleted := true
507 for _, childDeviceId := range childDeviceIds {
508 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
509 if err = agent.deleteDevice(nil); err != nil {
510 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
511 allChildDeleted = false
512 } else {
513 agent.stop(nil)
514 dMgr.deleteDeviceAgentToMap(agent)
515 }
516 }
517 }
518 if !allChildDeleted {
519 return err
520 }
521 return nil
522}
523
524//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
525func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
526 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400527 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400528 if parentDevice != nil {
529 for _, port := range parentDevice.Ports {
530 for _, peer := range port.Peers {
531 childDeviceIds = append(childDeviceIds, peer.DeviceId)
532 }
khenaidoo92e62c52018-10-03 14:02:54 -0400533 }
534 }
535 return childDeviceIds, nil
536}
537
538func (dMgr *DeviceManager) addUNILogicalPort(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400539 log.Info("addUNILogicalPort")
khenaidoo4d4802d2018-10-04 21:59:49 -0400540 if err := dMgr.logicalDeviceMgr.addUNILogicalPort(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400541 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
542 return err
543 }
544 return nil
545}
546
khenaidoo92e62c52018-10-03 14:02:54 -0400547func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400548 log.Info("activateDevice")
549 return nil
550}
551
khenaidoo92e62c52018-10-03 14:02:54 -0400552func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
553 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400554 return nil
555}
556
khenaidoo92e62c52018-10-03 14:02:54 -0400557func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400558 log.Info("abandonDevice")
559 return nil
560}
561
khenaidoo92e62c52018-10-03 14:02:54 -0400562func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400563 log.Info("reEnableDevice")
564 return nil
565}
566
khenaidoo92e62c52018-10-03 14:02:54 -0400567func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400568 log.Info("noOp")
569 return nil
570}
571
khenaidoo92e62c52018-10-03 14:02:54 -0400572func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400573 log.Info("notAllowed")
574 return errors.New("Transition-not-allowed")
575}
576
577func funcName(f interface{}) string {
578 p := reflect.ValueOf(f).Pointer()
579 rf := runtime.FuncForPC(p)
580 return rf.Name()
581}
582
583func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
584 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
585 agent.updateDeviceAttribute(attribute, value)
586 }
587}
588
589func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -0400590 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400591 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -0400592 return &device.ParentId
593 }
594 return nil
595}