blob: c40b8cde7e475bde73b6b22d140c2ace2663d4a4 [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
Matt Jeanneret4e241952019-02-28 11:16:04 -0500204func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
205 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber})
206
207 var parentDevice *voltha.Device
208 var err error
209 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
210 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
211 }
212 var childDeviceIds []string
213 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
214 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
215 }
216 if len(childDeviceIds) == 0 {
217 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
218 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
219 }
220
221 var foundChildDevice *voltha.Device
222 for _, childDeviceId := range childDeviceIds {
223 found := false
224 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
225
226 foundOnuId := false
227 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
228 if searchDevice.ParentPortNo == uint32(parentPortNo) {
229 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
230 foundOnuId = true
231 }
232 }
233
234 foundSerialNumber := false
235 if searchDevice.SerialNumber == serialNumber {
236 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
237 foundSerialNumber = true
238 }
239
240 // if both onuId and serialNumber are provided both must be true for the device to be found
241 // otherwise whichever one found a match is good enough
242 if onuId > 0 && serialNumber != "" {
243 found = foundOnuId && foundSerialNumber
244 } else {
245 found = foundOnuId || foundSerialNumber
246 }
247
248 if found == true {
249 foundChildDevice = searchDevice
250 break
251 }
252 }
253 }
254
255 if foundChildDevice != nil {
256 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
257 return foundChildDevice, nil
258 }
259
260 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
261 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
262 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
263}
264
khenaidoo297cd252019-02-07 22:10:23 -0500265func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
266 dMgr.lockDeviceAgentsMap.Lock()
267 defer dMgr.lockDeviceAgentsMap.Unlock()
268 _, exist := dMgr.deviceAgents[id]
269 return exist
270}
271
khenaidoo19d7b632018-10-30 10:49:50 -0400272func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
273 device, err := dMgr.GetDevice(id)
274 if err != nil {
275 return false, err
276 }
277 return device.Root, nil
278}
279
Stephane Barbarieaa467942019-02-06 14:09:44 -0500280// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400281func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400282 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400283 result := &voltha.Devices{}
Stephane Barbarieaa467942019-02-06 14:09:44 -0500284 if devices := dMgr.clusterDataProxy.List("/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500285 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500286 // If device is not in memory then set it up
287 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
288 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy)
289 if err := agent.start(nil, true); err != nil {
290 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
291 agent.stop(nil)
292 } else {
293 dMgr.addDeviceAgentToMap(agent)
294 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500295 }
296 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400297 }
298 }
299 return result, nil
300}
301
khenaidoo297cd252019-02-07 22:10:23 -0500302// loadDevice loads the deviceId in memory, if not present
303func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
304 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
305 // Sanity check
306 if deviceId == "" {
307 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
308 }
309 if !dMgr.IsDeviceInCache(deviceId) {
310 agent := newDeviceAgent(dMgr.adapterProxy, &voltha.Device{Id: deviceId}, dMgr, dMgr.clusterDataProxy)
311 if err := agent.start(nil, true); err != nil {
312 agent.stop(nil)
313 return nil, err
314 }
315 dMgr.addDeviceAgentToMap(agent)
316 }
317 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
318 return agent, nil
319 }
Matt Jeanneret4e241952019-02-28 11:16:04 -0500320 return nil, status.Error(codes.NotFound, deviceId) // This should not happen
khenaidoo297cd252019-02-07 22:10:23 -0500321}
322
323// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
324func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
325 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
326 if device.Root {
327 // Scenario A
328 if device.ParentId != "" {
329 // Load logical device if needed.
330 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
331 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
332 }
333 } else {
334 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
335 }
336 // Load all child devices, if needed
337 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
338 for _, childDeviceId := range childDeviceIds {
339 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
340 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId})
341 return err
342 }
343 }
344 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
345 } else {
346 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
347 }
348 }
349 return nil
350}
351
352// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
353// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
354// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
355// and the proceed with the request.
356func (dMgr *DeviceManager) load(deviceId string) error {
357 log.Debug("load...")
358 // First load the device - this may fail in case the device was deleted intentionally by the other core
359 var dAgent *DeviceAgent
360 var err error
361 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
362 log.Warnw("failure-loading-device", log.Fields{"deviceId": deviceId})
363 return err
364 }
365 // Get the loaded device details
366 var device *voltha.Device
367 if device, err = dAgent.getDevice(); err != nil {
368 return err
369 }
370
371 // If the device is in Pre-provisioning or deleted state stop here
372 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
373 return nil
374 }
375
376 // Now we face two scenarios
377 if device.Root {
378 // Load all children as well as the parent of this device (logical_device)
379 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
380 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
381 return err
382 }
383 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
384 } else {
385 // Scenario B - use the parentId of that device (root device) to trigger the loading
386 if device.ParentId != "" {
387 return dMgr.load(device.ParentId)
388 }
389 }
390 return nil
391}
392
khenaidoo7ccedd52018-12-14 16:48:54 -0500393// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
394func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
395 log.Debug("ListDeviceIDs")
396 // Report only device IDs that are in the device agent map
397 return dMgr.listDeviceIdsFromMap(), nil
398}
399
400//ReconcileDevices is a request to a voltha core to managed a list of devices based on their IDs
401func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
402 log.Debug("ReconcileDevices")
403 var res interface{}
404 if ids != nil {
405 toReconcile := len(ids.Items)
406 reconciled := 0
407 for _, id := range ids.Items {
408 // Act on the device only if its not present in the agent map
khenaidoo297cd252019-02-07 22:10:23 -0500409 if !dMgr.IsDeviceInCache(id.Id) {
khenaidoo7ccedd52018-12-14 16:48:54 -0500410 // Device Id not in memory
411 log.Debugw("reconciling-device", log.Fields{"id": id.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500412 // Load device from dB
Matt Jeanneret4e241952019-02-28 11:16:04 -0500413 agent := newDeviceAgent(dMgr.adapterProxy, &voltha.Device{Id: id.Id}, dMgr, dMgr.clusterDataProxy)
khenaidoo297cd252019-02-07 22:10:23 -0500414 if err := agent.start(nil, true); err != nil {
415 log.Warnw("failure-loading-device", log.Fields{"deviceId": id.Id})
416 agent.stop(nil)
khenaidoo7ccedd52018-12-14 16:48:54 -0500417 } else {
khenaidoo297cd252019-02-07 22:10:23 -0500418 dMgr.addDeviceAgentToMap(agent)
419 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500420 }
421 } else {
422 reconciled += 1
423 }
424 }
425 if toReconcile != reconciled {
426 res = status.Errorf(codes.DataLoss, "less-device-reconciled:%d/%d", reconciled, toReconcile)
427 }
428 } else {
429 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
430 }
431 sendResponse(ctx, ch, res)
432}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500433
khenaidoob9203542018-09-17 22:56:37 -0400434func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400435 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400436 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
437 return agent.updateDevice(device)
438 }
439 return status.Errorf(codes.NotFound, "%s", device.Id)
440}
441
442func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
443 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400444 if err := agent.addPort(port); err != nil {
445 return err
446 }
447 // Setup peer ports
448 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
449 for _, peerPort := range port.Peers {
450 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
451 if err := agent.addPeerPort(meAsPeer); err != nil {
452 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
453 return err
454 }
455 }
456 }
457 return nil
458 } else {
459 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400460 }
khenaidoob9203542018-09-17 22:56:37 -0400461}
462
khenaidoo19d7b632018-10-30 10:49:50 -0400463func (dMgr *DeviceManager) updateFlows(deviceId string, flows []*ofp.OfpFlowStats) error {
464 log.Debugw("updateFlows", log.Fields{"deviceid": deviceId})
465 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
466 return agent.updateFlows(flows)
467 }
468 return status.Errorf(codes.NotFound, "%s", deviceId)
469}
470
471func (dMgr *DeviceManager) updateGroups(deviceId string, groups []*ofp.OfpGroupEntry) error {
472 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
473 return agent.updateGroups(groups)
474 }
475 return status.Errorf(codes.NotFound, "%s", deviceId)
476}
477
khenaidoob9203542018-09-17 22:56:37 -0400478func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
479 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
480 return agent.updatePmConfigs(pmConfigs)
481 }
482 return status.Errorf(codes.NotFound, "%s", deviceId)
483}
484
khenaidoo79232702018-12-04 11:00:41 -0500485func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400486 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400487 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
488 return agent.getSwitchCapability(ctx)
489 }
490 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
491}
492
khenaidoo92e62c52018-10-03 14:02:54 -0400493func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
494 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400495 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400496 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400497 }
498 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400499
khenaidoob9203542018-09-17 22:56:37 -0400500}
501
khenaidoo79232702018-12-04 11:00:41 -0500502func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400503 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400504 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
505 return agent.getPortCapability(ctx, portNo)
506 }
507 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
508}
509
khenaidoo92e62c52018-10-03 14:02:54 -0400510func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
511 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400512 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400513 return agent.updateDeviceStatus(operStatus, connStatus)
514 }
515 return status.Errorf(codes.NotFound, "%s", deviceId)
516}
517
khenaidoo4d4802d2018-10-04 21:59:49 -0400518func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
519 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
520 var parentDevice *voltha.Device
521 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400522 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400523 return status.Errorf(codes.Aborted, "%s", err.Error())
524 }
525 var childDeviceIds []string
526 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
527 return status.Errorf(codes.Aborted, "%s", err.Error())
528 }
529 if len(childDeviceIds) == 0 {
530 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
531 }
532 for _, childDeviceId := range childDeviceIds {
533 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
534 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
535 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
536 }
537 }
538 }
539 return nil
540}
541
khenaidoo92e62c52018-10-03 14:02:54 -0400542func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
543 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
544 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
545 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400546 }
547 return status.Errorf(codes.NotFound, "%s", deviceId)
548}
549
Matt Jeanneret4e241952019-02-28 11:16:04 -0500550func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
551 channelId int64, vendorId string, serialNumber string, onuId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400552 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400553
554 // Create the ONU device
555 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400556 childDevice.Type = deviceType
557 childDevice.ParentId = parentDeviceId
558 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500559 childDevice.VendorId = vendorId
560 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400561 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400562
563 //Get parent device type
564 parent, err := dMgr.GetDevice(parentDeviceId)
565 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500566 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400567 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
568 }
569
Matt Jeanneret4e241952019-02-28 11:16:04 -0500570 if _, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
571 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
572 return status.Errorf(codes.AlreadyExists, "%s", serialNumber)
573 }
574
575 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400576
577 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400578 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400579 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500580 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400581
582 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400583 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500584 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400585 }
586
khenaidoo79232702018-12-04 11:00:41 -0500587 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500588 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500589
khenaidoob9203542018-09-17 22:56:37 -0400590 return nil
591}
592
593func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
594 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400595 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
596 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500597 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400598 return nil
khenaidoob9203542018-09-17 22:56:37 -0400599 }
khenaidoo92e62c52018-10-03 14:02:54 -0400600 for _, handler := range handlers {
601 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
602 if err := handler(current); err != nil {
603 return err
604 }
605 }
khenaidoob9203542018-09-17 22:56:37 -0400606 return nil
607}
608
khenaidoofdbad6e2018-11-06 22:26:38 -0500609func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
610 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
611 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
612 return agent.packetOut(outPort, packet)
613 }
614 return status.Errorf(codes.NotFound, "%s", deviceId)
615}
616
khenaidoo297cd252019-02-07 22:10:23 -0500617func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500618 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
619 // Get the logical device Id based on the deviceId
620 var device *voltha.Device
621 var err error
622 if device, err = dMgr.GetDevice(deviceId); err != nil {
623 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
624 return err
625 }
khenaidoo43c82122018-11-22 18:38:28 -0500626 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500627 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
628 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
629 }
630
khenaidoo297cd252019-02-07 22:10:23 -0500631 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500632 return err
633 }
634 return nil
635}
636
khenaidoo92e62c52018-10-03 14:02:54 -0400637func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400638 log.Info("createLogicalDevice")
639 var logicalId *string
640 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400641 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400642 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
643 return err
644 }
645 // Update the parent device with the logical id
646 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
647 return nil
648}
649
khenaidoo92e62c52018-10-03 14:02:54 -0400650func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
651 log.Info("deleteLogicalDevice")
652 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400653 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400654 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
655 return err
656 }
657 // Remove the logical device Id from the parent device
658 logicalId := ""
659 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
660 return nil
661}
662
khenaidoo19d7b632018-10-30 10:49:50 -0400663func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400664 log.Info("deleteLogicalPort")
665 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400666 // Get the logical port associated with this device
667 var lPortId *voltha.LogicalPortId
668 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400669 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400670 return err
671 }
672 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
673 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400674 return err
675 }
khenaidoo92e62c52018-10-03 14:02:54 -0400676 return nil
677}
678
679func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
680 // Sanity check
681 if childDevice.Root {
682 // childDevice is the parent device
683 return childDevice
684 }
khenaidoo19d7b632018-10-30 10:49:50 -0400685 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400686 return parentDevice
687}
688
khenaidoo4d4802d2018-10-04 21:59:49 -0400689/*
690All the functions below are callback functions where they are invoked with the latest and previous data. We can
691therefore use the data as is without trying to get the latest from the model.
692*/
693
694//disableAllChildDevices is invoked as a callback when the parent device is disabled
695func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400696 log.Debug("disableAllChildDevices")
697 var childDeviceIds []string
698 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400699 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
700 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400701 }
702 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400703 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400704 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400705 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400706 for _, childDeviceId := range childDeviceIds {
707 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
708 if err = agent.disableDevice(nil); err != nil {
709 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400710 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400711 }
712 }
713 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400714 if !allChildDisable {
715 return err
716 }
khenaidoo92e62c52018-10-03 14:02:54 -0400717 return nil
718}
719
khenaidoo4d4802d2018-10-04 21:59:49 -0400720//deleteAllChildDevices is invoked as a callback when the parent device is deleted
721func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
722 log.Debug("deleteAllChildDevices")
723 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400724 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400725 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
726 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400727 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400728 if len(childDeviceIds) == 0 {
729 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
730 }
731 allChildDeleted := true
732 for _, childDeviceId := range childDeviceIds {
733 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
734 if err = agent.deleteDevice(nil); err != nil {
735 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
736 allChildDeleted = false
737 } else {
738 agent.stop(nil)
739 dMgr.deleteDeviceAgentToMap(agent)
740 }
741 }
742 }
743 if !allChildDeleted {
744 return err
745 }
746 return nil
747}
748
749//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
750func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
751 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400752 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400753 if parentDevice != nil {
754 for _, port := range parentDevice.Ports {
755 for _, peer := range port.Peers {
756 childDeviceIds = append(childDeviceIds, peer.DeviceId)
757 }
khenaidoo92e62c52018-10-03 14:02:54 -0400758 }
759 }
Matt Jeanneret4e241952019-02-28 11:16:04 -0500760 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -0400761 return childDeviceIds, nil
762}
763
khenaidoo297cd252019-02-07 22:10:23 -0500764//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
765func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
766 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
767 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
768 childDevices := make([]*voltha.Device, 0)
769 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
770 for _, deviceId := range childDeviceIds {
771 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
772 childDevices = append(childDevices, d)
773 }
774 }
775 }
776 return &voltha.Devices{Items: childDevices}, nil
777 }
778 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
779}
780
khenaidoo92e62c52018-10-03 14:02:54 -0400781func (dMgr *DeviceManager) addUNILogicalPort(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400782 log.Info("addUNILogicalPort")
khenaidoo4d4802d2018-10-04 21:59:49 -0400783 if err := dMgr.logicalDeviceMgr.addUNILogicalPort(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400784 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
785 return err
786 }
787 return nil
788}
789
khenaidoof5a5bfa2019-01-23 22:20:29 -0500790func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
791 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
792 var res interface{}
793 var err error
794 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
795 if res, err = agent.downloadImage(ctx, img); err != nil {
796 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
797 res = err
798 }
799 } else {
800 res = status.Errorf(codes.NotFound, "%s", img.Id)
801 }
802 sendResponse(ctx, ch, res)
803}
804
805func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
806 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
807 var res interface{}
808 var err error
809 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
810 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
811 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
812 res = err
813 }
814 } else {
815 res = status.Errorf(codes.NotFound, "%s", img.Id)
816 }
817 sendResponse(ctx, ch, res)
818}
819
820func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
821 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
822 var res interface{}
823 var err error
824 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
825 if res, err = agent.activateImage(ctx, img); err != nil {
826 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
827 res = err
828 }
829 } else {
830 res = status.Errorf(codes.NotFound, "%s", img.Id)
831 }
832 sendResponse(ctx, ch, res)
833}
834
835func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
836 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
837 var res interface{}
838 var err error
839 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
840 if res, err = agent.revertImage(ctx, img); err != nil {
841 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
842 res = err
843 }
844 } else {
845 res = status.Errorf(codes.NotFound, "%s", img.Id)
846 }
847 sendResponse(ctx, ch, res)
848}
849
850func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
851 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
852 var res interface{}
853 var err error
854 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
855 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
856 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
857 res = err
858 }
859 } else {
860 res = status.Errorf(codes.NotFound, "%s", img.Id)
861 }
862 sendResponse(ctx, ch, res)
863}
864
khenaidoof5a5bfa2019-01-23 22:20:29 -0500865func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
866 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
867 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
868 if err := agent.updateImageDownload(img); err != nil {
869 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
870 return err
871 }
872 } else {
873 return status.Errorf(codes.NotFound, "%s", img.Id)
874 }
875 return nil
876}
877
878func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
879 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
880 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
881 return agent.getImageDownload(ctx, img)
882 }
883 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
884}
885
886func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
887 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
888 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
889 return agent.listImageDownloads(ctx, deviceId)
890 }
891 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
892}
893
khenaidoo92e62c52018-10-03 14:02:54 -0400894func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400895 log.Info("activateDevice")
896 return nil
897}
898
khenaidoo92e62c52018-10-03 14:02:54 -0400899func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
900 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400901 return nil
902}
903
khenaidoo92e62c52018-10-03 14:02:54 -0400904func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400905 log.Info("abandonDevice")
906 return nil
907}
908
khenaidoo92e62c52018-10-03 14:02:54 -0400909func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400910 log.Info("reEnableDevice")
911 return nil
912}
913
khenaidoo92e62c52018-10-03 14:02:54 -0400914func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400915 log.Info("noOp")
916 return nil
917}
918
khenaidoo92e62c52018-10-03 14:02:54 -0400919func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400920 log.Info("notAllowed")
921 return errors.New("Transition-not-allowed")
922}
923
924func funcName(f interface{}) string {
925 p := reflect.ValueOf(f).Pointer()
926 rf := runtime.FuncForPC(p)
927 return rf.Name()
928}
929
930func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
931 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
932 agent.updateDeviceAttribute(attribute, value)
933 }
934}
935
936func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -0400937 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400938 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -0400939 return &device.ParentId
940 }
941 return nil
942}