blob: 09eca3bd78baa8b3e99082f0457ef765a17bdb68 [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
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500265func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
266 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
267
268 var parentDevice *voltha.Device
269 var err error
270 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
271 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
272 }
273 var childDeviceIds []string
274 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
275 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
276 }
277 if len(childDeviceIds) == 0 {
278 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
279 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
280 }
281
282 var foundChildDevice *voltha.Device
283 for _, childDeviceId := range childDeviceIds {
284 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
285 if searchDevice.ProxyAddress == proxyAddress {
286 foundChildDevice = searchDevice
287 break
288 }
289 }
290 }
291
292 if foundChildDevice != nil {
293 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
294 return foundChildDevice, nil
295 }
296
297 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
298 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
299}
300
khenaidoo297cd252019-02-07 22:10:23 -0500301func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
302 dMgr.lockDeviceAgentsMap.Lock()
303 defer dMgr.lockDeviceAgentsMap.Unlock()
304 _, exist := dMgr.deviceAgents[id]
305 return exist
306}
307
khenaidoo19d7b632018-10-30 10:49:50 -0400308func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
309 device, err := dMgr.GetDevice(id)
310 if err != nil {
311 return false, err
312 }
313 return device.Root, nil
314}
315
Stephane Barbarieaa467942019-02-06 14:09:44 -0500316// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400317func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400318 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400319 result := &voltha.Devices{}
Stephane Barbarieaa467942019-02-06 14:09:44 -0500320 if devices := dMgr.clusterDataProxy.List("/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500321 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500322 // If device is not in memory then set it up
323 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
324 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy)
325 if err := agent.start(nil, true); err != nil {
326 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
327 agent.stop(nil)
328 } else {
329 dMgr.addDeviceAgentToMap(agent)
330 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500331 }
332 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400333 }
334 }
335 return result, nil
336}
337
khenaidoo297cd252019-02-07 22:10:23 -0500338// loadDevice loads the deviceId in memory, if not present
339func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
340 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
341 // Sanity check
342 if deviceId == "" {
343 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
344 }
345 if !dMgr.IsDeviceInCache(deviceId) {
346 agent := newDeviceAgent(dMgr.adapterProxy, &voltha.Device{Id: deviceId}, dMgr, dMgr.clusterDataProxy)
347 if err := agent.start(nil, true); err != nil {
348 agent.stop(nil)
349 return nil, err
350 }
351 dMgr.addDeviceAgentToMap(agent)
352 }
353 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
354 return agent, nil
355 }
Matt Jeanneret4e241952019-02-28 11:16:04 -0500356 return nil, status.Error(codes.NotFound, deviceId) // This should not happen
khenaidoo297cd252019-02-07 22:10:23 -0500357}
358
359// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
360func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
361 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
362 if device.Root {
363 // Scenario A
364 if device.ParentId != "" {
365 // Load logical device if needed.
366 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
367 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
368 }
369 } else {
370 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
371 }
372 // Load all child devices, if needed
373 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
374 for _, childDeviceId := range childDeviceIds {
375 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
376 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId})
377 return err
378 }
379 }
380 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
381 } else {
382 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
383 }
384 }
385 return nil
386}
387
388// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
389// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
390// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
391// and the proceed with the request.
392func (dMgr *DeviceManager) load(deviceId string) error {
393 log.Debug("load...")
394 // First load the device - this may fail in case the device was deleted intentionally by the other core
395 var dAgent *DeviceAgent
396 var err error
397 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
398 log.Warnw("failure-loading-device", log.Fields{"deviceId": deviceId})
399 return err
400 }
401 // Get the loaded device details
402 var device *voltha.Device
403 if device, err = dAgent.getDevice(); err != nil {
404 return err
405 }
406
407 // If the device is in Pre-provisioning or deleted state stop here
408 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
409 return nil
410 }
411
412 // Now we face two scenarios
413 if device.Root {
414 // Load all children as well as the parent of this device (logical_device)
415 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
416 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
417 return err
418 }
419 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
420 } else {
421 // Scenario B - use the parentId of that device (root device) to trigger the loading
422 if device.ParentId != "" {
423 return dMgr.load(device.ParentId)
424 }
425 }
426 return nil
427}
428
khenaidoo7ccedd52018-12-14 16:48:54 -0500429// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
430func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
431 log.Debug("ListDeviceIDs")
432 // Report only device IDs that are in the device agent map
433 return dMgr.listDeviceIdsFromMap(), nil
434}
435
436//ReconcileDevices is a request to a voltha core to managed a list of devices based on their IDs
437func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
438 log.Debug("ReconcileDevices")
439 var res interface{}
440 if ids != nil {
441 toReconcile := len(ids.Items)
442 reconciled := 0
443 for _, id := range ids.Items {
444 // Act on the device only if its not present in the agent map
khenaidoo297cd252019-02-07 22:10:23 -0500445 if !dMgr.IsDeviceInCache(id.Id) {
khenaidoo7ccedd52018-12-14 16:48:54 -0500446 // Device Id not in memory
447 log.Debugw("reconciling-device", log.Fields{"id": id.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500448 // Load device from dB
Matt Jeanneret4e241952019-02-28 11:16:04 -0500449 agent := newDeviceAgent(dMgr.adapterProxy, &voltha.Device{Id: id.Id}, dMgr, dMgr.clusterDataProxy)
khenaidoo297cd252019-02-07 22:10:23 -0500450 if err := agent.start(nil, true); err != nil {
451 log.Warnw("failure-loading-device", log.Fields{"deviceId": id.Id})
452 agent.stop(nil)
khenaidoo7ccedd52018-12-14 16:48:54 -0500453 } else {
khenaidoo297cd252019-02-07 22:10:23 -0500454 dMgr.addDeviceAgentToMap(agent)
455 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500456 }
457 } else {
458 reconciled += 1
459 }
460 }
461 if toReconcile != reconciled {
462 res = status.Errorf(codes.DataLoss, "less-device-reconciled:%d/%d", reconciled, toReconcile)
463 }
464 } else {
465 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
466 }
467 sendResponse(ctx, ch, res)
468}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500469
khenaidoob9203542018-09-17 22:56:37 -0400470func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400471 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400472 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
473 return agent.updateDevice(device)
474 }
475 return status.Errorf(codes.NotFound, "%s", device.Id)
476}
477
478func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
479 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400480 if err := agent.addPort(port); err != nil {
481 return err
482 }
483 // Setup peer ports
484 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
485 for _, peerPort := range port.Peers {
486 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
487 if err := agent.addPeerPort(meAsPeer); err != nil {
488 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
489 return err
490 }
491 }
492 }
khenaidoofc1314d2019-03-14 09:34:21 -0400493 // Notify the logical device manager to setup a logical port if needed
494 if port.Type == voltha.Port_ETHERNET_NNI || port.Type == voltha.Port_ETHERNET_UNI {
495 if device , err := dMgr.GetDevice(deviceId); err == nil {
496 go dMgr.logicalDeviceMgr.addLogicalPort(device, port)
497 } else {
498 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
499 return err
500 }
501 }
khenaidoo92e62c52018-10-03 14:02:54 -0400502 return nil
503 } else {
504 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400505 }
khenaidoob9203542018-09-17 22:56:37 -0400506}
507
khenaidoo19d7b632018-10-30 10:49:50 -0400508func (dMgr *DeviceManager) updateFlows(deviceId string, flows []*ofp.OfpFlowStats) error {
509 log.Debugw("updateFlows", log.Fields{"deviceid": deviceId})
510 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
511 return agent.updateFlows(flows)
512 }
513 return status.Errorf(codes.NotFound, "%s", deviceId)
514}
515
516func (dMgr *DeviceManager) updateGroups(deviceId string, groups []*ofp.OfpGroupEntry) error {
517 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
518 return agent.updateGroups(groups)
519 }
520 return status.Errorf(codes.NotFound, "%s", deviceId)
521}
522
khenaidoob9203542018-09-17 22:56:37 -0400523func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
524 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
525 return agent.updatePmConfigs(pmConfigs)
526 }
527 return status.Errorf(codes.NotFound, "%s", deviceId)
528}
529
khenaidoo79232702018-12-04 11:00:41 -0500530func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400531 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400532 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
533 return agent.getSwitchCapability(ctx)
534 }
535 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
536}
537
khenaidoo92e62c52018-10-03 14:02:54 -0400538func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
539 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400540 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400541 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400542 }
543 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400544
khenaidoob9203542018-09-17 22:56:37 -0400545}
546
khenaidoo79232702018-12-04 11:00:41 -0500547func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400548 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400549 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
550 return agent.getPortCapability(ctx, portNo)
551 }
552 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
553}
554
khenaidoo92e62c52018-10-03 14:02:54 -0400555func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
556 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400557 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400558 return agent.updateDeviceStatus(operStatus, connStatus)
559 }
560 return status.Errorf(codes.NotFound, "%s", deviceId)
561}
562
khenaidoo4d4802d2018-10-04 21:59:49 -0400563func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
564 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
565 var parentDevice *voltha.Device
566 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400567 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400568 return status.Errorf(codes.Aborted, "%s", err.Error())
569 }
570 var childDeviceIds []string
571 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
572 return status.Errorf(codes.Aborted, "%s", err.Error())
573 }
574 if len(childDeviceIds) == 0 {
575 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
576 }
577 for _, childDeviceId := range childDeviceIds {
578 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
579 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
580 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
581 }
582 }
583 }
584 return nil
585}
586
khenaidoo92e62c52018-10-03 14:02:54 -0400587func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
588 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
589 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
590 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400591 }
592 return status.Errorf(codes.NotFound, "%s", deviceId)
593}
594
Matt Jeanneret4e241952019-02-28 11:16:04 -0500595func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
596 channelId int64, vendorId string, serialNumber string, onuId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400597 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400598
599 // Create the ONU device
600 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400601 childDevice.Type = deviceType
602 childDevice.ParentId = parentDeviceId
603 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500604 childDevice.VendorId = vendorId
605 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400606 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400607
608 //Get parent device type
609 parent, err := dMgr.GetDevice(parentDeviceId)
610 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500611 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400612 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
613 }
614
Matt Jeanneret4e241952019-02-28 11:16:04 -0500615 if _, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
616 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
617 return status.Errorf(codes.AlreadyExists, "%s", serialNumber)
618 }
619
620 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400621
622 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400623 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400624 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500625 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400626
627 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400628 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500629 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400630 }
631
khenaidoo79232702018-12-04 11:00:41 -0500632 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500633 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500634
khenaidoob9203542018-09-17 22:56:37 -0400635 return nil
636}
637
638func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
639 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400640 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
641 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500642 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400643 return nil
khenaidoob9203542018-09-17 22:56:37 -0400644 }
khenaidoo92e62c52018-10-03 14:02:54 -0400645 for _, handler := range handlers {
646 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
647 if err := handler(current); err != nil {
648 return err
649 }
650 }
khenaidoob9203542018-09-17 22:56:37 -0400651 return nil
652}
653
khenaidoofdbad6e2018-11-06 22:26:38 -0500654func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
655 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
656 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
657 return agent.packetOut(outPort, packet)
658 }
659 return status.Errorf(codes.NotFound, "%s", deviceId)
660}
661
khenaidoo297cd252019-02-07 22:10:23 -0500662func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500663 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
664 // Get the logical device Id based on the deviceId
665 var device *voltha.Device
666 var err error
667 if device, err = dMgr.GetDevice(deviceId); err != nil {
668 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
669 return err
670 }
khenaidoo43c82122018-11-22 18:38:28 -0500671 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500672 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
673 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
674 }
675
khenaidoo297cd252019-02-07 22:10:23 -0500676 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500677 return err
678 }
679 return nil
680}
681
khenaidoo92e62c52018-10-03 14:02:54 -0400682func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400683 log.Info("createLogicalDevice")
684 var logicalId *string
685 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400686 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400687 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
688 return err
689 }
690 // Update the parent device with the logical id
691 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
692 return nil
693}
694
khenaidoo92e62c52018-10-03 14:02:54 -0400695func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
696 log.Info("deleteLogicalDevice")
697 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400698 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400699 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
700 return err
701 }
702 // Remove the logical device Id from the parent device
703 logicalId := ""
704 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
705 return nil
706}
707
khenaidoo19d7b632018-10-30 10:49:50 -0400708func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400709 log.Info("deleteLogicalPort")
710 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400711 // Get the logical port associated with this device
712 var lPortId *voltha.LogicalPortId
713 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400714 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400715 return err
716 }
717 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
718 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400719 return err
720 }
khenaidoo92e62c52018-10-03 14:02:54 -0400721 return nil
722}
723
724func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
725 // Sanity check
726 if childDevice.Root {
727 // childDevice is the parent device
728 return childDevice
729 }
khenaidoo19d7b632018-10-30 10:49:50 -0400730 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400731 return parentDevice
732}
733
khenaidoo4d4802d2018-10-04 21:59:49 -0400734/*
735All the functions below are callback functions where they are invoked with the latest and previous data. We can
736therefore use the data as is without trying to get the latest from the model.
737*/
738
739//disableAllChildDevices is invoked as a callback when the parent device is disabled
740func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400741 log.Debug("disableAllChildDevices")
742 var childDeviceIds []string
743 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400744 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
745 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400746 }
747 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400748 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400749 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400750 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400751 for _, childDeviceId := range childDeviceIds {
752 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
753 if err = agent.disableDevice(nil); err != nil {
754 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400755 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400756 }
757 }
758 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400759 if !allChildDisable {
760 return err
761 }
khenaidoo92e62c52018-10-03 14:02:54 -0400762 return nil
763}
764
khenaidoo4d4802d2018-10-04 21:59:49 -0400765//deleteAllChildDevices is invoked as a callback when the parent device is deleted
766func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
767 log.Debug("deleteAllChildDevices")
768 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400769 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400770 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
771 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400772 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400773 if len(childDeviceIds) == 0 {
774 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
775 }
776 allChildDeleted := true
777 for _, childDeviceId := range childDeviceIds {
778 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
779 if err = agent.deleteDevice(nil); err != nil {
780 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
781 allChildDeleted = false
782 } else {
783 agent.stop(nil)
784 dMgr.deleteDeviceAgentToMap(agent)
785 }
786 }
787 }
788 if !allChildDeleted {
789 return err
790 }
791 return nil
792}
793
794//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
795func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
796 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400797 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400798 if parentDevice != nil {
799 for _, port := range parentDevice.Ports {
800 for _, peer := range port.Peers {
801 childDeviceIds = append(childDeviceIds, peer.DeviceId)
802 }
khenaidoo92e62c52018-10-03 14:02:54 -0400803 }
804 }
Matt Jeanneret4e241952019-02-28 11:16:04 -0500805 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -0400806 return childDeviceIds, nil
807}
808
khenaidoo297cd252019-02-07 22:10:23 -0500809//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
810func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
811 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
812 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
813 childDevices := make([]*voltha.Device, 0)
814 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
815 for _, deviceId := range childDeviceIds {
816 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
817 childDevices = append(childDevices, d)
818 }
819 }
820 }
821 return &voltha.Devices{Items: childDevices}, nil
822 }
823 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
824}
825
khenaidoofc1314d2019-03-14 09:34:21 -0400826func (dMgr *DeviceManager) setupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400827 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -0400828 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400829 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
830 return err
831 }
832 return nil
833}
834
khenaidoof5a5bfa2019-01-23 22:20:29 -0500835func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
836 log.Debugw("downloadImage", 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.downloadImage(ctx, img); err != nil {
841 log.Debugw("downloadImage-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) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
851 log.Debugw("cancelImageDownload", 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.cancelImageDownload(ctx, img); err != nil {
856 log.Debugw("cancelImageDownload-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
865func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
866 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
867 var res interface{}
868 var err error
869 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
870 if res, err = agent.activateImage(ctx, img); err != nil {
871 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
872 res = err
873 }
874 } else {
875 res = status.Errorf(codes.NotFound, "%s", img.Id)
876 }
877 sendResponse(ctx, ch, res)
878}
879
880func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
881 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
882 var res interface{}
883 var err error
884 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
885 if res, err = agent.revertImage(ctx, img); err != nil {
886 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
887 res = err
888 }
889 } else {
890 res = status.Errorf(codes.NotFound, "%s", img.Id)
891 }
892 sendResponse(ctx, ch, res)
893}
894
895func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
896 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
897 var res interface{}
898 var err error
899 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
900 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
901 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
902 res = err
903 }
904 } else {
905 res = status.Errorf(codes.NotFound, "%s", img.Id)
906 }
907 sendResponse(ctx, ch, res)
908}
909
khenaidoof5a5bfa2019-01-23 22:20:29 -0500910func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
911 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
912 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
913 if err := agent.updateImageDownload(img); err != nil {
914 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
915 return err
916 }
917 } else {
918 return status.Errorf(codes.NotFound, "%s", img.Id)
919 }
920 return nil
921}
922
923func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
924 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
925 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
926 return agent.getImageDownload(ctx, img)
927 }
928 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
929}
930
931func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
932 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
933 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
934 return agent.listImageDownloads(ctx, deviceId)
935 }
936 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
937}
938
khenaidoo92e62c52018-10-03 14:02:54 -0400939func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400940 log.Info("activateDevice")
941 return nil
942}
943
khenaidoo92e62c52018-10-03 14:02:54 -0400944func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
945 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400946 return nil
947}
948
khenaidoo92e62c52018-10-03 14:02:54 -0400949func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400950 log.Info("abandonDevice")
951 return nil
952}
953
khenaidoo92e62c52018-10-03 14:02:54 -0400954func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400955 log.Info("reEnableDevice")
956 return nil
957}
958
khenaidoo92e62c52018-10-03 14:02:54 -0400959func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400960 log.Info("noOp")
961 return nil
962}
963
khenaidoo92e62c52018-10-03 14:02:54 -0400964func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400965 log.Info("notAllowed")
966 return errors.New("Transition-not-allowed")
967}
968
969func funcName(f interface{}) string {
970 p := reflect.ValueOf(f).Pointer()
971 rf := runtime.FuncForPC(p)
972 return rf.Name()
973}
974
975func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
976 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
977 agent.updateDeviceAttribute(attribute, value)
978 }
979}
980
981func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -0400982 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400983 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -0400984 return &device.ParentId
985 }
986 return nil
987}