blob: b36e8d493795754ddf9b5f09185e6dcfaccca66a [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
khenaidoo297cd252019-02-07 22:10:23 -050037 adapterMgr *AdapterManager
khenaidoob9203542018-09-17 22:56:37 -040038 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
khenaidood2b6df92018-12-13 16:37:20 -050042 coreInstanceId string
khenaidoob9203542018-09-17 22:56:37 -040043 exitChannel chan int
44 lockDeviceAgentsMap sync.RWMutex
45}
46
khenaidoo21d51152019-02-01 13:48:37 -050047func newDeviceManager(kafkaICProxy *kafka.InterContainerProxy, cdProxy *model.Proxy, adapterMgr *AdapterManager, coreInstanceId string) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040048 var deviceMgr DeviceManager
49 deviceMgr.exitChannel = make(chan int, 1)
50 deviceMgr.deviceAgents = make(map[string]*DeviceAgent)
khenaidoo43c82122018-11-22 18:38:28 -050051 deviceMgr.adapterProxy = NewAdapterProxy(kafkaICProxy)
52 deviceMgr.kafkaICProxy = kafkaICProxy
khenaidoo19374072018-12-11 11:05:15 -050053 deviceMgr.coreInstanceId = coreInstanceId
khenaidoo9a468962018-09-19 15:33:13 -040054 deviceMgr.clusterDataProxy = cdProxy
khenaidoo297cd252019-02-07 22:10:23 -050055 deviceMgr.adapterMgr = adapterMgr
khenaidoob9203542018-09-17 22:56:37 -040056 deviceMgr.lockDeviceAgentsMap = sync.RWMutex{}
57 return &deviceMgr
58}
59
khenaidoo4d4802d2018-10-04 21:59:49 -040060func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040061 log.Info("starting-device-manager")
62 dMgr.logicalDeviceMgr = logicalDeviceMgr
63 dMgr.stateTransitions = NewTransitionMap(dMgr)
64 log.Info("device-manager-started")
65}
66
khenaidoo4d4802d2018-10-04 21:59:49 -040067func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040068 log.Info("stopping-device-manager")
69 dMgr.exitChannel <- 1
70 log.Info("device-manager-stopped")
71}
72
73func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
74 if ctx.Err() == nil {
75 // Returned response only of the ctx has not been cancelled/timeout/etc
76 // Channel is automatically closed when a context is Done
77 ch <- result
78 log.Debugw("sendResponse", log.Fields{"result": result})
79 } else {
80 // Should the transaction be reverted back?
81 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
82 }
83}
84
85func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
86 dMgr.lockDeviceAgentsMap.Lock()
87 defer dMgr.lockDeviceAgentsMap.Unlock()
88 if _, exist := dMgr.deviceAgents[agent.deviceId]; !exist {
89 dMgr.deviceAgents[agent.deviceId] = agent
90 }
91}
92
khenaidoo4d4802d2018-10-04 21:59:49 -040093func (dMgr *DeviceManager) deleteDeviceAgentToMap(agent *DeviceAgent) {
94 dMgr.lockDeviceAgentsMap.Lock()
95 defer dMgr.lockDeviceAgentsMap.Unlock()
96 delete(dMgr.deviceAgents, agent.deviceId)
97}
98
khenaidoo297cd252019-02-07 22:10:23 -050099// getDeviceAgent returns the agent managing the device. If the device is not in memory, it will loads it, if it exists
khenaidoob9203542018-09-17 22:56:37 -0400100func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
101 dMgr.lockDeviceAgentsMap.Lock()
khenaidoob9203542018-09-17 22:56:37 -0400102 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
khenaidoo297cd252019-02-07 22:10:23 -0500103 dMgr.lockDeviceAgentsMap.Unlock()
khenaidoob9203542018-09-17 22:56:37 -0400104 return agent
khenaidoo297cd252019-02-07 22:10:23 -0500105 } else {
106 // Try to load into memory - loading will also create the device agent
107 dMgr.lockDeviceAgentsMap.Unlock()
108 if err := dMgr.load(deviceId); err == nil {
109 dMgr.lockDeviceAgentsMap.Lock()
110 defer dMgr.lockDeviceAgentsMap.Unlock()
111 if agent, ok = dMgr.deviceAgents[deviceId]; ok {
112 return agent
113 }
114 }
khenaidoob9203542018-09-17 22:56:37 -0400115 }
116 return nil
117}
118
khenaidoo297cd252019-02-07 22:10:23 -0500119// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500120func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
121 dMgr.lockDeviceAgentsMap.Lock()
122 defer dMgr.lockDeviceAgentsMap.Unlock()
123 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
124 for key, _ := range dMgr.deviceAgents {
125 result.Items = append(result.Items, &voltha.ID{Id: key})
126 }
127 return result
128}
129
khenaidoob9203542018-09-17 22:56:37 -0400130func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400131 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400132
khenaidoo5e677ae2019-02-28 17:26:29 -0500133 // Ensure this device is set as root
134 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400135 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400136 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400137 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500138 agent.start(ctx, false)
khenaidoob9203542018-09-17 22:56:37 -0400139
khenaidoo92e62c52018-10-03 14:02:54 -0400140 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400141}
142
143func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400144 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400145 var res interface{}
146 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
147 res = agent.enableDevice(ctx)
148 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400149 }
150
151 sendResponse(ctx, ch, res)
152}
153
khenaidoo92e62c52018-10-03 14:02:54 -0400154func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
155 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400156 var res interface{}
157 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
158 res = agent.disableDevice(ctx)
159 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400160 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400161 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400162 }
khenaidoo92e62c52018-10-03 14:02:54 -0400163
164 sendResponse(ctx, ch, res)
165}
166
khenaidoo4d4802d2018-10-04 21:59:49 -0400167func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
168 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
169 var res interface{}
170 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
171 res = agent.rebootDevice(ctx)
172 log.Debugw("rebootDevice-result", log.Fields{"result": res})
173 } else {
174 res = status.Errorf(codes.NotFound, "%s", id.Id)
175 }
176 sendResponse(ctx, ch, res)
177}
178
179func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
180 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
181 var res interface{}
182 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
183 res = agent.deleteDevice(ctx)
184 if res == nil { //Success
185 agent.stop(ctx)
186 dMgr.deleteDeviceAgentToMap(agent)
187 }
188 log.Debugw("deleteDevice-result", log.Fields{"result": res})
189 } else {
190 res = status.Errorf(codes.NotFound, "%s", id.Id)
191 }
192 sendResponse(ctx, ch, res)
193}
194
khenaidoo297cd252019-02-07 22:10:23 -0500195// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400196func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
197 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400198 if agent := dMgr.getDeviceAgent(id); agent != nil {
199 return agent.getDevice()
200 }
201 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400202}
203
khenaidoo297cd252019-02-07 22:10:23 -0500204func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
205 dMgr.lockDeviceAgentsMap.Lock()
206 defer dMgr.lockDeviceAgentsMap.Unlock()
207 _, exist := dMgr.deviceAgents[id]
208 return exist
209}
210
khenaidoo19d7b632018-10-30 10:49:50 -0400211func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
212 device, err := dMgr.GetDevice(id)
213 if err != nil {
214 return false, err
215 }
216 return device.Root, nil
217}
218
Stephane Barbarieaa467942019-02-06 14:09:44 -0500219// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400220func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400221 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400222 result := &voltha.Devices{}
Stephane Barbarieaa467942019-02-06 14:09:44 -0500223 if devices := dMgr.clusterDataProxy.List("/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500224 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500225 // If device is not in memory then set it up
226 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
227 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy)
228 if err := agent.start(nil, true); err != nil {
229 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
230 agent.stop(nil)
231 } else {
232 dMgr.addDeviceAgentToMap(agent)
233 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500234 }
235 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400236 }
237 }
238 return result, nil
239}
240
khenaidoo297cd252019-02-07 22:10:23 -0500241// loadDevice loads the deviceId in memory, if not present
242func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
243 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
244 // Sanity check
245 if deviceId == "" {
246 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
247 }
248 if !dMgr.IsDeviceInCache(deviceId) {
249 agent := newDeviceAgent(dMgr.adapterProxy, &voltha.Device{Id: deviceId}, dMgr, dMgr.clusterDataProxy)
250 if err := agent.start(nil, true); err != nil {
251 agent.stop(nil)
252 return nil, err
253 }
254 dMgr.addDeviceAgentToMap(agent)
255 }
256 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
257 return agent, nil
258 }
259 return nil, status.Error(codes.NotFound, deviceId) // This should nto happen
260}
261
262// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
263func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
264 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
265 if device.Root {
266 // Scenario A
267 if device.ParentId != "" {
268 // Load logical device if needed.
269 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
270 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
271 }
272 } else {
273 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
274 }
275 // Load all child devices, if needed
276 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
277 for _, childDeviceId := range childDeviceIds {
278 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
279 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId})
280 return err
281 }
282 }
283 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
284 } else {
285 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
286 }
287 }
288 return nil
289}
290
291// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
292// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
293// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
294// and the proceed with the request.
295func (dMgr *DeviceManager) load(deviceId string) error {
296 log.Debug("load...")
297 // First load the device - this may fail in case the device was deleted intentionally by the other core
298 var dAgent *DeviceAgent
299 var err error
300 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
301 log.Warnw("failure-loading-device", log.Fields{"deviceId": deviceId})
302 return err
303 }
304 // Get the loaded device details
305 var device *voltha.Device
306 if device, err = dAgent.getDevice(); err != nil {
307 return err
308 }
309
310 // If the device is in Pre-provisioning or deleted state stop here
311 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
312 return nil
313 }
314
315 // Now we face two scenarios
316 if device.Root {
317 // Load all children as well as the parent of this device (logical_device)
318 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
319 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
320 return err
321 }
322 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
323 } else {
324 // Scenario B - use the parentId of that device (root device) to trigger the loading
325 if device.ParentId != "" {
326 return dMgr.load(device.ParentId)
327 }
328 }
329 return nil
330}
331
khenaidoo7ccedd52018-12-14 16:48:54 -0500332// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
333func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
334 log.Debug("ListDeviceIDs")
335 // Report only device IDs that are in the device agent map
336 return dMgr.listDeviceIdsFromMap(), nil
337}
338
339//ReconcileDevices is a request to a voltha core to managed a list of devices based on their IDs
340func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
341 log.Debug("ReconcileDevices")
342 var res interface{}
343 if ids != nil {
344 toReconcile := len(ids.Items)
345 reconciled := 0
346 for _, id := range ids.Items {
347 // Act on the device only if its not present in the agent map
khenaidoo297cd252019-02-07 22:10:23 -0500348 if !dMgr.IsDeviceInCache(id.Id) {
khenaidoo7ccedd52018-12-14 16:48:54 -0500349 // Device Id not in memory
350 log.Debugw("reconciling-device", log.Fields{"id": id.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500351 // Load device from dB
352 agent := newDeviceAgent(dMgr.adapterProxy, &voltha.Device{Id:id.Id}, dMgr, dMgr.clusterDataProxy)
353 if err := agent.start(nil, true); err != nil {
354 log.Warnw("failure-loading-device", log.Fields{"deviceId": id.Id})
355 agent.stop(nil)
khenaidoo7ccedd52018-12-14 16:48:54 -0500356 } else {
khenaidoo297cd252019-02-07 22:10:23 -0500357 dMgr.addDeviceAgentToMap(agent)
358 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500359 }
360 } else {
361 reconciled += 1
362 }
363 }
364 if toReconcile != reconciled {
365 res = status.Errorf(codes.DataLoss, "less-device-reconciled:%d/%d", reconciled, toReconcile)
366 }
367 } else {
368 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
369 }
370 sendResponse(ctx, ch, res)
371}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500372
khenaidoob9203542018-09-17 22:56:37 -0400373func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400374 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400375 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
376 return agent.updateDevice(device)
377 }
378 return status.Errorf(codes.NotFound, "%s", device.Id)
379}
380
381func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
382 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400383 if err := agent.addPort(port); err != nil {
384 return err
385 }
386 // Setup peer ports
387 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
388 for _, peerPort := range port.Peers {
389 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
390 if err := agent.addPeerPort(meAsPeer); err != nil {
391 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
392 return err
393 }
394 }
395 }
396 return nil
397 } else {
398 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400399 }
khenaidoob9203542018-09-17 22:56:37 -0400400}
401
khenaidoo19d7b632018-10-30 10:49:50 -0400402func (dMgr *DeviceManager) updateFlows(deviceId string, flows []*ofp.OfpFlowStats) error {
403 log.Debugw("updateFlows", log.Fields{"deviceid": deviceId})
404 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
405 return agent.updateFlows(flows)
406 }
407 return status.Errorf(codes.NotFound, "%s", deviceId)
408}
409
410func (dMgr *DeviceManager) updateGroups(deviceId string, groups []*ofp.OfpGroupEntry) error {
411 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
412 return agent.updateGroups(groups)
413 }
414 return status.Errorf(codes.NotFound, "%s", deviceId)
415}
416
khenaidoob9203542018-09-17 22:56:37 -0400417func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
418 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
419 return agent.updatePmConfigs(pmConfigs)
420 }
421 return status.Errorf(codes.NotFound, "%s", deviceId)
422}
423
khenaidoo79232702018-12-04 11:00:41 -0500424func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400425 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400426 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
427 return agent.getSwitchCapability(ctx)
428 }
429 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
430}
431
khenaidoo92e62c52018-10-03 14:02:54 -0400432func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
433 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400434 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400435 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400436 }
437 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400438
khenaidoob9203542018-09-17 22:56:37 -0400439}
440
khenaidoo79232702018-12-04 11:00:41 -0500441func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400442 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400443 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
444 return agent.getPortCapability(ctx, portNo)
445 }
446 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
447}
448
khenaidoo92e62c52018-10-03 14:02:54 -0400449func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
450 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400451 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400452 return agent.updateDeviceStatus(operStatus, connStatus)
453 }
454 return status.Errorf(codes.NotFound, "%s", deviceId)
455}
456
khenaidoo4d4802d2018-10-04 21:59:49 -0400457func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
458 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
459 var parentDevice *voltha.Device
460 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400461 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400462 return status.Errorf(codes.Aborted, "%s", err.Error())
463 }
464 var childDeviceIds []string
465 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
466 return status.Errorf(codes.Aborted, "%s", err.Error())
467 }
468 if len(childDeviceIds) == 0 {
469 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
470 }
471 for _, childDeviceId := range childDeviceIds {
472 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
473 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
474 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
475 }
476 }
477 }
478 return nil
479}
480
khenaidoo92e62c52018-10-03 14:02:54 -0400481func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
482 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
483 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
484 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400485 }
486 return status.Errorf(codes.NotFound, "%s", deviceId)
487}
488
489func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string, channelId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400490 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400491
492 // Create the ONU device
493 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400494 childDevice.Type = deviceType
495 childDevice.ParentId = parentDeviceId
496 childDevice.ParentPortNo = uint32(parentPortNo)
497 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400498
499 //Get parent device type
500 parent, err := dMgr.GetDevice(parentDeviceId)
501 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500502 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400503 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
504 }
505
506 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId)}
khenaidoob9203542018-09-17 22:56:37 -0400507
508 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400509 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400510 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500511 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400512
513 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400514 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500515 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400516 }
517
khenaidoo79232702018-12-04 11:00:41 -0500518 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500519 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500520
khenaidoob9203542018-09-17 22:56:37 -0400521 return nil
522}
523
524func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
525 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400526 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
527 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500528 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400529 return nil
khenaidoob9203542018-09-17 22:56:37 -0400530 }
khenaidoo92e62c52018-10-03 14:02:54 -0400531 for _, handler := range handlers {
532 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
533 if err := handler(current); err != nil {
534 return err
535 }
536 }
khenaidoob9203542018-09-17 22:56:37 -0400537 return nil
538}
539
khenaidoofdbad6e2018-11-06 22:26:38 -0500540func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
541 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
542 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
543 return agent.packetOut(outPort, packet)
544 }
545 return status.Errorf(codes.NotFound, "%s", deviceId)
546}
547
khenaidoo297cd252019-02-07 22:10:23 -0500548func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500549 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
550 // Get the logical device Id based on the deviceId
551 var device *voltha.Device
552 var err error
553 if device, err = dMgr.GetDevice(deviceId); err != nil {
554 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
555 return err
556 }
khenaidoo43c82122018-11-22 18:38:28 -0500557 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500558 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
559 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
560 }
561
khenaidoo297cd252019-02-07 22:10:23 -0500562 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500563 return err
564 }
565 return nil
566}
567
khenaidoo92e62c52018-10-03 14:02:54 -0400568func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400569 log.Info("createLogicalDevice")
570 var logicalId *string
571 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400572 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400573 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
574 return err
575 }
576 // Update the parent device with the logical id
577 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
578 return nil
579}
580
khenaidoo92e62c52018-10-03 14:02:54 -0400581func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
582 log.Info("deleteLogicalDevice")
583 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400584 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400585 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
586 return err
587 }
588 // Remove the logical device Id from the parent device
589 logicalId := ""
590 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
591 return nil
592}
593
khenaidoo19d7b632018-10-30 10:49:50 -0400594func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400595 log.Info("deleteLogicalPort")
596 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400597 // Get the logical port associated with this device
598 var lPortId *voltha.LogicalPortId
599 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400600 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400601 return err
602 }
603 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
604 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400605 return err
606 }
khenaidoo92e62c52018-10-03 14:02:54 -0400607 return nil
608}
609
610func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
611 // Sanity check
612 if childDevice.Root {
613 // childDevice is the parent device
614 return childDevice
615 }
khenaidoo19d7b632018-10-30 10:49:50 -0400616 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400617 return parentDevice
618}
619
khenaidoo4d4802d2018-10-04 21:59:49 -0400620/*
621All the functions below are callback functions where they are invoked with the latest and previous data. We can
622therefore use the data as is without trying to get the latest from the model.
623*/
624
625//disableAllChildDevices is invoked as a callback when the parent device is disabled
626func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400627 log.Debug("disableAllChildDevices")
628 var childDeviceIds []string
629 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400630 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
631 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400632 }
633 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400634 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400635 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400636 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400637 for _, childDeviceId := range childDeviceIds {
638 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
639 if err = agent.disableDevice(nil); err != nil {
640 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400641 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400642 }
643 }
644 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400645 if !allChildDisable {
646 return err
647 }
khenaidoo92e62c52018-10-03 14:02:54 -0400648 return nil
649}
650
khenaidoo4d4802d2018-10-04 21:59:49 -0400651//deleteAllChildDevices is invoked as a callback when the parent device is deleted
652func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
653 log.Debug("deleteAllChildDevices")
654 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400655 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400656 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
657 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400658 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400659 if len(childDeviceIds) == 0 {
660 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
661 }
662 allChildDeleted := true
663 for _, childDeviceId := range childDeviceIds {
664 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
665 if err = agent.deleteDevice(nil); err != nil {
666 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
667 allChildDeleted = false
668 } else {
669 agent.stop(nil)
670 dMgr.deleteDeviceAgentToMap(agent)
671 }
672 }
673 }
674 if !allChildDeleted {
675 return err
676 }
677 return nil
678}
679
680//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
681func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
682 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400683 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400684 if parentDevice != nil {
685 for _, port := range parentDevice.Ports {
686 for _, peer := range port.Peers {
687 childDeviceIds = append(childDeviceIds, peer.DeviceId)
688 }
khenaidoo92e62c52018-10-03 14:02:54 -0400689 }
690 }
691 return childDeviceIds, nil
692}
693
khenaidoo297cd252019-02-07 22:10:23 -0500694//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
695func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
696 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
697 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
698 childDevices := make([]*voltha.Device, 0)
699 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
700 for _, deviceId := range childDeviceIds {
701 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
702 childDevices = append(childDevices, d)
703 }
704 }
705 }
706 return &voltha.Devices{Items: childDevices}, nil
707 }
708 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
709}
710
khenaidoo92e62c52018-10-03 14:02:54 -0400711func (dMgr *DeviceManager) addUNILogicalPort(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400712 log.Info("addUNILogicalPort")
khenaidoo4d4802d2018-10-04 21:59:49 -0400713 if err := dMgr.logicalDeviceMgr.addUNILogicalPort(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400714 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
715 return err
716 }
717 return nil
718}
719
khenaidoof5a5bfa2019-01-23 22:20:29 -0500720func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
721 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
722 var res interface{}
723 var err error
724 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
725 if res, err = agent.downloadImage(ctx, img); err != nil {
726 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
727 res = err
728 }
729 } else {
730 res = status.Errorf(codes.NotFound, "%s", img.Id)
731 }
732 sendResponse(ctx, ch, res)
733}
734
735func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
736 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
737 var res interface{}
738 var err error
739 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
740 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
741 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
742 res = err
743 }
744 } else {
745 res = status.Errorf(codes.NotFound, "%s", img.Id)
746 }
747 sendResponse(ctx, ch, res)
748}
749
750func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
751 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
752 var res interface{}
753 var err error
754 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
755 if res, err = agent.activateImage(ctx, img); err != nil {
756 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
757 res = err
758 }
759 } else {
760 res = status.Errorf(codes.NotFound, "%s", img.Id)
761 }
762 sendResponse(ctx, ch, res)
763}
764
765func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
766 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
767 var res interface{}
768 var err error
769 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
770 if res, err = agent.revertImage(ctx, img); err != nil {
771 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
772 res = err
773 }
774 } else {
775 res = status.Errorf(codes.NotFound, "%s", img.Id)
776 }
777 sendResponse(ctx, ch, res)
778}
779
780func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
781 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
782 var res interface{}
783 var err error
784 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
785 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
786 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
787 res = err
788 }
789 } else {
790 res = status.Errorf(codes.NotFound, "%s", img.Id)
791 }
792 sendResponse(ctx, ch, res)
793}
794
khenaidoof5a5bfa2019-01-23 22:20:29 -0500795func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
796 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
797 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
798 if err := agent.updateImageDownload(img); err != nil {
799 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
800 return err
801 }
802 } else {
803 return status.Errorf(codes.NotFound, "%s", img.Id)
804 }
805 return nil
806}
807
808func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
809 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
810 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
811 return agent.getImageDownload(ctx, img)
812 }
813 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
814}
815
816func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
817 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
818 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
819 return agent.listImageDownloads(ctx, deviceId)
820 }
821 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
822}
823
khenaidoo92e62c52018-10-03 14:02:54 -0400824func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400825 log.Info("activateDevice")
826 return nil
827}
828
khenaidoo92e62c52018-10-03 14:02:54 -0400829func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
830 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400831 return nil
832}
833
khenaidoo92e62c52018-10-03 14:02:54 -0400834func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400835 log.Info("abandonDevice")
836 return nil
837}
838
khenaidoo92e62c52018-10-03 14:02:54 -0400839func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400840 log.Info("reEnableDevice")
841 return nil
842}
843
khenaidoo92e62c52018-10-03 14:02:54 -0400844func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400845 log.Info("noOp")
846 return nil
847}
848
khenaidoo92e62c52018-10-03 14:02:54 -0400849func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400850 log.Info("notAllowed")
851 return errors.New("Transition-not-allowed")
852}
853
854func funcName(f interface{}) string {
855 p := reflect.ValueOf(f).Pointer()
856 rf := runtime.FuncForPC(p)
857 return rf.Name()
858}
859
860func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
861 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
862 agent.updateDeviceAttribute(attribute, value)
863 }
864}
865
866func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -0400867 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400868 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -0400869 return &device.ParentId
870 }
871 return nil
872}