blob: d053ac4ec3561c00076b7399b2eb129845f2506b [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"
khenaidoo3d3b8c22019-05-22 18:10:39 -040024 "github.com/opencord/voltha-go/rw_core/utils"
William Kurkiandaa6bb22019-03-07 12:26:28 -050025 ic "github.com/opencord/voltha-protos/go/inter_container"
26 ofp "github.com/opencord/voltha-protos/go/openflow_13"
27 "github.com/opencord/voltha-protos/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040028 "google.golang.org/grpc/codes"
29 "google.golang.org/grpc/status"
30 "reflect"
31 "runtime"
32 "sync"
33)
34
35type DeviceManager struct {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040036 deviceAgents sync.Map
37 rootDevices map[string]bool
38 lockRootDeviceMap sync.RWMutex
39 core *Core
40 adapterProxy *AdapterProxy
41 adapterMgr *AdapterManager
42 logicalDeviceMgr *LogicalDeviceManager
43 kafkaICProxy *kafka.InterContainerProxy
44 stateTransitions *TransitionMap
45 clusterDataProxy *model.Proxy
46 coreInstanceId string
47 exitChannel chan int
48 defaultTimeout int64
khenaidoob9203542018-09-17 22:56:37 -040049}
50
Richard Jankowski199fd862019-03-18 14:49:51 -040051func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040052 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040053 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040054 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040055 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040056 deviceMgr.kafkaICProxy = core.kmp
Kent Hagermana6d0c362019-07-30 12:50:21 -040057 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic)
Richard Jankowski199fd862019-03-18 14:49:51 -040058 deviceMgr.coreInstanceId = core.instanceId
59 deviceMgr.clusterDataProxy = core.clusterDataProxy
60 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040061 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
62 deviceMgr.defaultTimeout = core.config.DefaultCoreTimeout
khenaidoob9203542018-09-17 22:56:37 -040063 return &deviceMgr
64}
65
khenaidoo4d4802d2018-10-04 21:59:49 -040066func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040067 log.Info("starting-device-manager")
68 dMgr.logicalDeviceMgr = logicalDeviceMgr
69 dMgr.stateTransitions = NewTransitionMap(dMgr)
70 log.Info("device-manager-started")
71}
72
khenaidoo4d4802d2018-10-04 21:59:49 -040073func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040074 log.Info("stopping-device-manager")
75 dMgr.exitChannel <- 1
76 log.Info("device-manager-stopped")
77}
78
79func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
80 if ctx.Err() == nil {
81 // Returned response only of the ctx has not been cancelled/timeout/etc
82 // Channel is automatically closed when a context is Done
83 ch <- result
84 log.Debugw("sendResponse", log.Fields{"result": result})
85 } else {
86 // Should the transaction be reverted back?
87 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
88 }
89}
90
91func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040092 if _, exist := dMgr.deviceAgents.Load(agent.deviceId); !exist {
93 dMgr.deviceAgents.Store(agent.deviceId, agent)
khenaidoob9203542018-09-17 22:56:37 -040094 }
khenaidoo2c6a0992019-04-29 13:46:56 -040095 dMgr.lockRootDeviceMap.Lock()
96 defer dMgr.lockRootDeviceMap.Unlock()
97 dMgr.rootDevices[agent.deviceId] = agent.isRootdevice
98
khenaidoob9203542018-09-17 22:56:37 -040099}
100
khenaidoo4d4802d2018-10-04 21:59:49 -0400101func (dMgr *DeviceManager) deleteDeviceAgentToMap(agent *DeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400102 dMgr.deviceAgents.Delete(agent.deviceId)
khenaidoo2c6a0992019-04-29 13:46:56 -0400103 dMgr.lockRootDeviceMap.Lock()
104 defer dMgr.lockRootDeviceMap.Unlock()
105 delete(dMgr.rootDevices, agent.deviceId)
khenaidoo4d4802d2018-10-04 21:59:49 -0400106}
107
khenaidoo297cd252019-02-07 22:10:23 -0500108// 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 -0400109func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400110 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
111 return agent.(*DeviceAgent)
khenaidoo297cd252019-02-07 22:10:23 -0500112 } else {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400113 // Try to load into memory - loading will also create the device agent and set the device ownership
khenaidoo297cd252019-02-07 22:10:23 -0500114 if err := dMgr.load(deviceId); err == nil {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400115 if agent, ok = dMgr.deviceAgents.Load(deviceId); !ok {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400116 return nil
117 } else {
118 // Register this device for ownership tracking
119 go dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: deviceId})
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400120 return agent.(*DeviceAgent)
khenaidoo297cd252019-02-07 22:10:23 -0500121 }
khenaidoo3d3b8c22019-05-22 18:10:39 -0400122 } else {
123 //TODO: Change the return params to return an error as well
124 log.Errorw("loading-device-failed", log.Fields{"deviceId": deviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500125 }
khenaidoob9203542018-09-17 22:56:37 -0400126 }
127 return nil
128}
129
khenaidoo297cd252019-02-07 22:10:23 -0500130// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500131func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500132 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400133
134 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
135 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
136 return true
137 })
138
khenaidoo7ccedd52018-12-14 16:48:54 -0500139 return result
140}
141
khenaidoob9203542018-09-17 22:56:37 -0400142func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400143 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400144
khenaidoo5e677ae2019-02-28 17:26:29 -0500145 // Ensure this device is set as root
146 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400147 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400148 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400149 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500150 agent.start(ctx, false)
khenaidoob9203542018-09-17 22:56:37 -0400151
khenaidoo92e62c52018-10-03 14:02:54 -0400152 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400153}
154
155func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400156 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400157 var res interface{}
158 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
159 res = agent.enableDevice(ctx)
160 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400161 }
162
163 sendResponse(ctx, ch, res)
164}
165
khenaidoo92e62c52018-10-03 14:02:54 -0400166func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
167 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400168 var res interface{}
169 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
170 res = agent.disableDevice(ctx)
171 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400172 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400173 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400174 }
khenaidoo92e62c52018-10-03 14:02:54 -0400175
176 sendResponse(ctx, ch, res)
177}
178
khenaidoo4d4802d2018-10-04 21:59:49 -0400179func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
180 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
181 var res interface{}
182 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
183 res = agent.rebootDevice(ctx)
184 log.Debugw("rebootDevice-result", log.Fields{"result": res})
185 } else {
186 res = status.Errorf(codes.NotFound, "%s", id.Id)
187 }
188 sendResponse(ctx, ch, res)
189}
190
191func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
192 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
193 var res interface{}
194 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
195 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400196 log.Debugw("deleteDevice-result", log.Fields{"result": res})
197 } else {
198 res = status.Errorf(codes.NotFound, "%s", id.Id)
199 }
200 sendResponse(ctx, ch, res)
201}
202
khenaidoo6d62c002019-05-15 21:57:03 -0400203// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
204// This function is called only in the Core that does not own this device. In the Core that owns this device then a
205// deletion deletion also includes removal of any reference of this device.
206func (dMgr *DeviceManager) stopManagingDevice(id string) {
207 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
208 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
209 if root, _ := dMgr.IsRootDevice(id); root == true {
210 // stop managing the logical device
211 ldeviceId := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceId(id)
212 if ldeviceId != "" { // Can happen if logical device agent was already stopped
213 dMgr.core.deviceOwnership.AbandonDevice(ldeviceId)
214 }
215 // stop managing the child devices
216 childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentId(id)
217 for _, cId := range childDeviceIds {
218 dMgr.stopManagingDevice(cId)
219 }
220 }
221 if agent := dMgr.getDeviceAgent(id); agent != nil {
222 agent.stop(nil)
223 dMgr.deleteDeviceAgentToMap(agent)
224 // Abandon the device ownership
225 dMgr.core.deviceOwnership.AbandonDevice(id)
226 }
227 }
228}
229
khenaidoo0a822f92019-05-08 15:15:57 -0400230func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
231 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400232 dMgr.stopManagingDevice(cDevice.Id)
233 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400234}
235
khenaidoo297cd252019-02-07 22:10:23 -0500236// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400237func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
238 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400239 if agent := dMgr.getDeviceAgent(id); agent != nil {
240 return agent.getDevice()
241 }
242 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400243}
244
Matt Jeanneret4e241952019-02-28 11:16:04 -0500245func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
Matt Jeanneret0c5088c2019-04-22 16:16:19 -0400246 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber,
247 "parentPortNo": parentPortNo, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500248
249 var parentDevice *voltha.Device
250 var err error
251 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
252 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
253 }
254 var childDeviceIds []string
255 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
256 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
257 }
258 if len(childDeviceIds) == 0 {
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700259 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500260 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
261 }
262
263 var foundChildDevice *voltha.Device
264 for _, childDeviceId := range childDeviceIds {
265 found := false
266 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
267
268 foundOnuId := false
269 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
270 if searchDevice.ParentPortNo == uint32(parentPortNo) {
271 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
272 foundOnuId = true
273 }
274 }
275
276 foundSerialNumber := false
277 if searchDevice.SerialNumber == serialNumber {
278 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
279 foundSerialNumber = true
280 }
281
282 // if both onuId and serialNumber are provided both must be true for the device to be found
283 // otherwise whichever one found a match is good enough
284 if onuId > 0 && serialNumber != "" {
285 found = foundOnuId && foundSerialNumber
286 } else {
287 found = foundOnuId || foundSerialNumber
288 }
289
290 if found == true {
291 foundChildDevice = searchDevice
292 break
293 }
294 }
295 }
296
297 if foundChildDevice != nil {
298 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
299 return foundChildDevice, nil
300 }
301
302 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
303 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
304 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
305}
306
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500307func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
308 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
309
310 var parentDevice *voltha.Device
311 var err error
312 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
313 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
314 }
315 var childDeviceIds []string
316 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
317 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
318 }
319 if len(childDeviceIds) == 0 {
320 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
321 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
322 }
323
324 var foundChildDevice *voltha.Device
325 for _, childDeviceId := range childDeviceIds {
326 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
327 if searchDevice.ProxyAddress == proxyAddress {
328 foundChildDevice = searchDevice
329 break
330 }
331 }
332 }
333
334 if foundChildDevice != nil {
335 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
336 return foundChildDevice, nil
337 }
338
339 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
340 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
341}
342
khenaidoo297cd252019-02-07 22:10:23 -0500343func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400344 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500345 return exist
346}
347
khenaidoo19d7b632018-10-30 10:49:50 -0400348func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400349 dMgr.lockRootDeviceMap.RLock()
350 defer dMgr.lockRootDeviceMap.RUnlock()
351 if exist := dMgr.rootDevices[id]; exist {
352 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400353 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400354 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400355}
356
Stephane Barbarieaa467942019-02-06 14:09:44 -0500357// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400358func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400359 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400360 result := &voltha.Devices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400361 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500362 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500363 // If device is not in memory then set it up
364 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400365 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400366 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500367 if err := agent.start(nil, true); err != nil {
368 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
369 agent.stop(nil)
370 } else {
371 dMgr.addDeviceAgentToMap(agent)
372 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500373 }
374 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400375 }
376 }
khenaidoo6d62c002019-05-15 21:57:03 -0400377 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400378 return result, nil
379}
380
khenaidoo6d62c002019-05-15 21:57:03 -0400381//getDeviceFromModelretrieves the device data from the model.
382func (dMgr *DeviceManager) getDeviceFromModel(deviceId string) (*voltha.Device, error) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400383 if device := dMgr.clusterDataProxy.Get(context.Background(), "/devices/"+deviceId, 0, false, ""); device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400384 if d, ok := device.(*voltha.Device); ok {
385 return d, nil
386 }
387 }
388 return nil, status.Error(codes.NotFound, deviceId)
389}
390
khenaidoo297cd252019-02-07 22:10:23 -0500391// loadDevice loads the deviceId in memory, if not present
392func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
393 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
394 // Sanity check
395 if deviceId == "" {
396 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
397 }
398 if !dMgr.IsDeviceInCache(deviceId) {
khenaidoo6d62c002019-05-15 21:57:03 -0400399 // Proceed with the loading only if the device exist in the Model (could have been deleted)
400 if device, err := dMgr.getDeviceFromModel(deviceId); err == nil {
401 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
402 if err := agent.start(nil, true); err != nil {
403 agent.stop(nil)
404 return nil, err
405 }
406 dMgr.addDeviceAgentToMap(agent)
407 } else {
408 return nil, status.Error(codes.NotFound, deviceId)
khenaidoo297cd252019-02-07 22:10:23 -0500409 }
khenaidoo297cd252019-02-07 22:10:23 -0500410 }
411 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
412 return agent, nil
413 }
Matt Jeanneret4e241952019-02-28 11:16:04 -0500414 return nil, status.Error(codes.NotFound, deviceId) // This should not happen
khenaidoo297cd252019-02-07 22:10:23 -0500415}
416
417// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
418func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
419 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
420 if device.Root {
421 // Scenario A
422 if device.ParentId != "" {
423 // Load logical device if needed.
424 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
425 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
426 }
427 } else {
428 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
429 }
430 // Load all child devices, if needed
431 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
432 for _, childDeviceId := range childDeviceIds {
433 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
434 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId})
435 return err
436 }
437 }
438 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
439 } else {
440 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
441 }
442 }
443 return nil
444}
445
446// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
447// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
448// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
449// and the proceed with the request.
450func (dMgr *DeviceManager) load(deviceId string) error {
451 log.Debug("load...")
452 // First load the device - this may fail in case the device was deleted intentionally by the other core
453 var dAgent *DeviceAgent
454 var err error
455 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500456 return err
457 }
458 // Get the loaded device details
459 var device *voltha.Device
460 if device, err = dAgent.getDevice(); err != nil {
461 return err
462 }
463
464 // If the device is in Pre-provisioning or deleted state stop here
465 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
466 return nil
467 }
468
469 // Now we face two scenarios
470 if device.Root {
471 // Load all children as well as the parent of this device (logical_device)
472 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
473 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
474 return err
475 }
476 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
477 } else {
478 // Scenario B - use the parentId of that device (root device) to trigger the loading
479 if device.ParentId != "" {
480 return dMgr.load(device.ParentId)
481 }
482 }
483 return nil
484}
485
khenaidoo7ccedd52018-12-14 16:48:54 -0500486// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
487func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
488 log.Debug("ListDeviceIDs")
489 // Report only device IDs that are in the device agent map
490 return dMgr.listDeviceIdsFromMap(), nil
491}
492
493//ReconcileDevices is a request to a voltha core to managed a list of devices based on their IDs
494func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
495 log.Debug("ReconcileDevices")
496 var res interface{}
497 if ids != nil {
498 toReconcile := len(ids.Items)
499 reconciled := 0
500 for _, id := range ids.Items {
501 // Act on the device only if its not present in the agent map
khenaidoo297cd252019-02-07 22:10:23 -0500502 if !dMgr.IsDeviceInCache(id.Id) {
khenaidoo7ccedd52018-12-14 16:48:54 -0500503 // Device Id not in memory
504 log.Debugw("reconciling-device", log.Fields{"id": id.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400505 // Proceed with the loading only if the device exist in the Model (could have been deleted)
506 if device, err := dMgr.getDeviceFromModel(id.Id); err == nil {
507 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
508 if err := agent.start(nil, true); err != nil {
509 log.Warnw("failure-loading-device", log.Fields{"deviceId": id.Id})
510 agent.stop(nil)
511 } else {
512 dMgr.addDeviceAgentToMap(agent)
513 reconciled += 1
514 }
khenaidoo7ccedd52018-12-14 16:48:54 -0500515 } else {
khenaidoo297cd252019-02-07 22:10:23 -0500516 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500517 }
khenaidoo7ccedd52018-12-14 16:48:54 -0500518 }
519 }
520 if toReconcile != reconciled {
521 res = status.Errorf(codes.DataLoss, "less-device-reconciled:%d/%d", reconciled, toReconcile)
522 }
523 } else {
524 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
525 }
526 sendResponse(ctx, ch, res)
527}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500528
khenaidooba6b6c42019-08-02 09:11:56 -0400529// isOkToReconcile validates whether a device is in the correct status to be reconciled
530func isOkToReconcile(device *voltha.Device) bool {
531 if device == nil {
532 return false
533 }
534 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
535}
536
537// adapterRestarted is invoked whenever an adapter is restarted
538func (dMgr *DeviceManager) adapterRestarted(adapter *voltha.Adapter) error {
539 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
540
541 // Let's reconcile the device managed by this Core only
542 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
543 if len(rootDeviceIds) == 0 {
544 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
545 return nil
546 }
547
548 chnlsList := make([]chan interface{}, 0)
549 for _, rootDeviceId := range rootDeviceIds {
550 if rootDevice, _ := dMgr.getDeviceFromModel(rootDeviceId); rootDevice != nil {
551 if rootDevice.Adapter == adapter.Id {
552 if isOkToReconcile(rootDevice) {
553 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
554 chnlsList = dMgr.sendReconcileDeviceRequest(rootDevice, chnlsList)
555 } else {
556 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
557 }
558 } else { // Should we be reconciling the root's children instead?
559 childManagedByAdapter:
560 for _, port := range rootDevice.Ports {
561 for _, peer := range port.Peers {
562 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
563 if childDevice.Adapter == adapter.Id {
564 if isOkToReconcile(childDevice) {
565 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
566 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
567 } else {
568 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
569 }
570 } else {
571 // All child devices under a parent device are typically managed by the same adapter type.
572 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
573 break childManagedByAdapter
574 }
575 }
576 }
577 }
578 }
579 }
580 }
581 if len(chnlsList) > 0 {
582 // Wait for completion
583 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
584 return status.Errorf(codes.Aborted, "errors-%s", res)
585 }
586 } else {
587 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
588 }
589 return nil
590}
591
592func (dMgr *DeviceManager) sendReconcileDeviceRequest(device *voltha.Device, chnlsList []chan interface{}) []chan interface{} {
593 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
594 // point of creating a device agent (if the device is not being managed by this Core) before sending the request
595 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to teh adapter via
596 // the adapter_proxy.
597 ch := make(chan interface{})
598 chnlsList = append(chnlsList, ch)
599 go func(device *voltha.Device) {
600 if err := dMgr.adapterProxy.ReconcileDevice(context.Background(), device); err != nil {
601 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
602 ch <- status.Errorf(codes.Internal, "device: %s", device.Id)
603 }
604 ch <- nil
605 }(device)
606
607 return chnlsList
608}
609
610func (dMgr *DeviceManager) reconcileChildDevices(parentDeviceId string) error {
611 if parentDevice, _ := dMgr.getDeviceFromModel(parentDeviceId); parentDevice != nil {
612 chnlsList := make([]chan interface{}, 0)
613 for _, port := range parentDevice.Ports {
614 for _, peer := range port.Peers {
615 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
616 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
617 }
618 }
619 }
620 // Wait for completion
621 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
622 return status.Errorf(codes.Aborted, "errors-%s", res)
623 }
624 }
625 return nil
626}
627
khenaidoob9203542018-09-17 22:56:37 -0400628func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400629 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400630 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
631 return agent.updateDevice(device)
632 }
633 return status.Errorf(codes.NotFound, "%s", device.Id)
634}
635
636func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
637 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400638 if err := agent.addPort(port); err != nil {
639 return err
640 }
641 // Setup peer ports
642 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
643 for _, peerPort := range port.Peers {
644 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
645 if err := agent.addPeerPort(meAsPeer); err != nil {
646 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
647 return err
648 }
649 }
650 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400651 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
652 // then a logical port will be added to the logical device and the device graph generated. If the port is a
653 // PON port then only the device graph will be generated.
654 if device, err := dMgr.GetDevice(deviceId); err == nil {
655 go dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
656 } else {
657 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
658 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400659 }
khenaidoo92e62c52018-10-03 14:02:54 -0400660 return nil
661 } else {
662 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400663 }
khenaidoob9203542018-09-17 22:56:37 -0400664}
665
khenaidoo0a822f92019-05-08 15:15:57 -0400666func (dMgr *DeviceManager) deletePeerPorts(fromDeviceId string, deviceId string) error {
667 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceId, "deviceid": deviceId})
668 if agent := dMgr.getDeviceAgent(fromDeviceId); agent != nil {
669 return agent.deletePeerPorts(deviceId)
670 }
671 return status.Errorf(codes.NotFound, "%s", deviceId)
672}
673
khenaidoo2c6a0992019-04-29 13:46:56 -0400674func (dMgr *DeviceManager) addFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) error {
675 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400676 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400677 return agent.addFlowsAndGroups(flows, groups)
khenaidoo0458db62019-06-20 08:50:36 -0400678 }
679 return status.Errorf(codes.NotFound, "%s", deviceId)
680}
681
682func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) error {
683 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceId})
684 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
685 return agent.deleteFlowsAndGroups(flows, groups)
686 }
687 return status.Errorf(codes.NotFound, "%s", deviceId)
688}
689
690func (dMgr *DeviceManager) updateFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) error {
691 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceId})
692 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
693 return agent.updateFlowsAndGroups(flows, groups)
khenaidoo19d7b632018-10-30 10:49:50 -0400694 }
695 return status.Errorf(codes.NotFound, "%s", deviceId)
696}
697
khenaidoob3127472019-07-24 21:04:55 -0400698// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
699// following a user action
700func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
701 var res interface{}
702 if pmConfigs.Id == "" {
703 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
704 } else if agent := dMgr.getDeviceAgent(pmConfigs.Id); agent != nil {
705 res = agent.updatePmConfigs(ctx, pmConfigs)
706 } else {
707 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
708 }
709 sendResponse(ctx, ch, res)
710}
711
712// initPmConfigs initialize the pm configs as defined by the adapter.
713func (dMgr *DeviceManager) initPmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
714 if pmConfigs.Id == "" {
715 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
716 }
khenaidoob9203542018-09-17 22:56:37 -0400717 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400718 return agent.initPmConfigs(pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400719 }
720 return status.Errorf(codes.NotFound, "%s", deviceId)
721}
722
khenaidoob3127472019-07-24 21:04:55 -0400723func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceId string) (*voltha.PmConfigs, error) {
724 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
725 return agent.listPmConfigs(ctx)
726 }
727 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
728}
729
khenaidoo79232702018-12-04 11:00:41 -0500730func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400731 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400732 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
733 return agent.getSwitchCapability(ctx)
734 }
735 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
736}
737
khenaidoo92e62c52018-10-03 14:02:54 -0400738func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
739 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400740 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400741 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400742 }
743 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
744}
745
khenaidoo79232702018-12-04 11:00:41 -0500746func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400747 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400748 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
749 return agent.getPortCapability(ctx, portNo)
750 }
751 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
752}
753
khenaidoo92e62c52018-10-03 14:02:54 -0400754func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
755 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400756 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400757 return agent.updateDeviceStatus(operStatus, connStatus)
758 }
759 return status.Errorf(codes.NotFound, "%s", deviceId)
760}
761
khenaidoo4d4802d2018-10-04 21:59:49 -0400762func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
763 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
764 var parentDevice *voltha.Device
765 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400766 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400767 return status.Errorf(codes.Aborted, "%s", err.Error())
768 }
769 var childDeviceIds []string
770 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
771 return status.Errorf(codes.Aborted, "%s", err.Error())
772 }
773 if len(childDeviceIds) == 0 {
774 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
775 }
776 for _, childDeviceId := range childDeviceIds {
777 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
778 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
779 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
780 }
781 }
782 }
783 return nil
784}
785
khenaidoo92e62c52018-10-03 14:02:54 -0400786func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
787 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
788 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
789 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400790 }
791 return status.Errorf(codes.NotFound, "%s", deviceId)
792}
793
khenaidoo0a822f92019-05-08 15:15:57 -0400794func (dMgr *DeviceManager) deleteAllPorts(deviceId string) error {
795 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceId})
796 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
797 if err := agent.deleteAllPorts(); err != nil {
798 return err
799 }
800 // Notify the logical device manager to remove all logical ports, if needed.
801 // At this stage the device itself may gave been deleted already at a deleteAllPorts
802 // typically is part of a device deletion phase.
803 if device, err := dMgr.GetDevice(deviceId); err == nil {
804 go dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
805 } else {
806 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
807 return err
808 }
809 return nil
810 }
811 return status.Errorf(codes.NotFound, "%s", deviceId)
812}
813
khenaidoo3ab34882019-05-02 21:33:30 -0400814//updatePortsState updates all ports on the device
815func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
816 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
817
818 var adminState voltha.AdminState_AdminState
819 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
820 switch state {
821 case voltha.OperStatus_ACTIVE:
822 adminState = voltha.AdminState_ENABLED
823 if err := agent.enablePorts(); err != nil {
824 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
825 return err
826 }
827 case voltha.OperStatus_UNKNOWN:
828 adminState = voltha.AdminState_DISABLED
829 if err := agent.disablePorts(); err != nil {
830 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
831 return err
832 }
833 default:
834 return status.Error(codes.Unimplemented, "state-change-not-implemented")
835 }
836 // Notify the logical device about the state change
837 if device, err := dMgr.GetDevice(deviceId); err != nil {
838 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
839 return err
840 } else {
841 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
842 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
843 return err
844 }
845 return nil
846 }
847 }
848 return status.Errorf(codes.NotFound, "%s", deviceId)
849}
850
Matt Jeanneret4e241952019-02-28 11:16:04 -0500851func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700852 channelId int64, vendorId string, serialNumber string, onuId int64) (*voltha.Device, error) {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700853 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId, "parentPortNo": parentPortNo, "deviceType": deviceType, "channelId": channelId, "vendorId": vendorId, "serialNumber": serialNumber, "onuId": onuId})
854
855 if deviceType == "" && vendorId != "" {
856 log.Debug("device-type-is-nil-fetching-device-type")
857 if deviceTypesIf := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, ""); deviceTypesIf != nil {
858 OLoop:
859 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
860 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
861 for _, v := range dType.VendorIds {
862 if v == vendorId {
863 deviceType = dType.Adapter
864 break OLoop
865 }
866 }
867 }
868 }
869 }
870 }
871 //if no match found for the vendorid,report adapter with the custom error message
872 if deviceType == "" {
873 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorId})
874 return nil, status.Errorf(codes.NotFound, "%s", vendorId)
875 }
khenaidoob9203542018-09-17 22:56:37 -0400876
877 // Create the ONU device
878 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400879 childDevice.Type = deviceType
880 childDevice.ParentId = parentDeviceId
881 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500882 childDevice.VendorId = vendorId
883 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400884 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400885
886 //Get parent device type
887 parent, err := dMgr.GetDevice(parentDeviceId)
888 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500889 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700890 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400891 }
892
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700893 if device, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500894 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700895 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500896 }
897
898 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400899
900 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400901 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400902 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500903 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400904
905 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400906 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500907 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400908 }
909
khenaidoo79232702018-12-04 11:00:41 -0500910 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500911 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500912
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700913 return agent.lastData, nil
khenaidoob9203542018-09-17 22:56:37 -0400914}
915
916func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
917 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400918 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
919 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500920 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400921 return nil
khenaidoob9203542018-09-17 22:56:37 -0400922 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400923 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -0400924 for _, handler := range handlers {
925 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
926 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400927 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400928 return err
929 }
930 }
khenaidoob9203542018-09-17 22:56:37 -0400931 return nil
932}
933
khenaidoofdbad6e2018-11-06 22:26:38 -0500934func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
935 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
936 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
937 return agent.packetOut(outPort, packet)
938 }
939 return status.Errorf(codes.NotFound, "%s", deviceId)
940}
941
khenaidoo297cd252019-02-07 22:10:23 -0500942func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500943 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
944 // Get the logical device Id based on the deviceId
945 var device *voltha.Device
946 var err error
947 if device, err = dMgr.GetDevice(deviceId); err != nil {
948 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
949 return err
950 }
khenaidoo43c82122018-11-22 18:38:28 -0500951 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500952 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
953 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
954 }
955
khenaidoo297cd252019-02-07 22:10:23 -0500956 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500957 return err
958 }
959 return nil
960}
961
khenaidoo0a822f92019-05-08 15:15:57 -0400962func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
963 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -0400964 // Verify whether the logical device has already been created
965 if cDevice.ParentId != "" {
966 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
967 return nil
968 }
khenaidoob9203542018-09-17 22:56:37 -0400969 var logicalId *string
970 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400971 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400972 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
973 return err
974 }
975 // Update the parent device with the logical id
976 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
977 return nil
978}
979
khenaidoo0a822f92019-05-08 15:15:57 -0400980func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
981 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -0400982 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400983 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400984 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
985 return err
986 }
987 // Remove the logical device Id from the parent device
988 logicalId := ""
989 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
990 return nil
991}
992
khenaidoo0a822f92019-05-08 15:15:57 -0400993func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400994 log.Info("deleteLogicalPort")
995 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400996 // Get the logical port associated with this device
997 var lPortId *voltha.LogicalPortId
998 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400999 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001000 return err
1001 }
1002 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
1003 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001004 return err
1005 }
khenaidoo92e62c52018-10-03 14:02:54 -04001006 return nil
1007}
1008
khenaidoo0a822f92019-05-08 15:15:57 -04001009func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1010 log.Info("deleteLogicalPorts")
1011 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1012 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1013 return err
1014 }
1015 return nil
1016}
1017
khenaidoo59ef7be2019-06-21 12:40:28 -04001018func (dMgr *DeviceManager) MarkChildDevicesAsUnReachable(device *voltha.Device) error {
1019 log.Info("MarkChildDevicesAsUnReachable")
1020 // Set the connection status to unreachable
1021 connStatus := voltha.ConnectStatus_UNREACHABLE
1022 // Do not set the operational status. Setting it to -1 will do the trick
1023 operStatus := voltha.OperStatus_OperStatus(-1)
1024 if err := dMgr.updateChildrenStatus(device.Id, operStatus, connStatus); err != nil {
1025 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1026 return err
1027 }
1028 return nil
1029}
1030
khenaidoo92e62c52018-10-03 14:02:54 -04001031func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1032 // Sanity check
1033 if childDevice.Root {
1034 // childDevice is the parent device
1035 return childDevice
1036 }
khenaidoo19d7b632018-10-30 10:49:50 -04001037 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001038 return parentDevice
1039}
1040
khenaidoo0a822f92019-05-08 15:15:57 -04001041//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1042//cannot manage the child devices. This will trigger the Core to disable all the child devices.
1043func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
1044 log.Debug("childDevicesLost")
1045 var err error
1046 var parentDevice *voltha.Device
1047 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1048 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1049 return err
1050 }
1051 return dMgr.DisableAllChildDevices(parentDevice)
1052}
1053
1054//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1055// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
1056func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
1057 log.Debug("childDevicesDetected")
1058 var err error
1059 var parentDevice *voltha.Device
1060 var childDeviceIds []string
1061
1062 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1063 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1064 return err
1065 }
1066
1067 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1068 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1069 }
1070 if len(childDeviceIds) == 0 {
1071 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1072 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001073 allChildEnableRequestSent := true
khenaidoo0a822f92019-05-08 15:15:57 -04001074 for _, childDeviceId := range childDeviceIds {
1075 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001076 // Run the children re-registration in its own routine
1077 go agent.enableDevice(nil)
1078 } else {
1079 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceId)
1080 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceId})
1081 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001082 }
1083 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001084 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001085 return err
1086 }
1087 return nil
1088}
1089
khenaidoo4d4802d2018-10-04 21:59:49 -04001090/*
1091All the functions below are callback functions where they are invoked with the latest and previous data. We can
1092therefore use the data as is without trying to get the latest from the model.
1093*/
1094
khenaidoo0a822f92019-05-08 15:15:57 -04001095//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1096func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1097 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001098 var childDeviceIds []string
1099 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001100 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1101 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001102 }
1103 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001104 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001105 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001106 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -04001107 for _, childDeviceId := range childDeviceIds {
1108 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1109 if err = agent.disableDevice(nil); err != nil {
1110 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001111 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001112 }
1113 }
1114 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001115 if !allChildDisable {
1116 return err
1117 }
khenaidoo92e62c52018-10-03 14:02:54 -04001118 return nil
1119}
1120
khenaidoo0a822f92019-05-08 15:15:57 -04001121//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1122func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1123 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001124 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001125 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001126 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1127 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001128 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001129 if len(childDeviceIds) == 0 {
1130 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1131 }
1132 allChildDeleted := true
1133 for _, childDeviceId := range childDeviceIds {
1134 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1135 if err = agent.deleteDevice(nil); err != nil {
1136 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
1137 allChildDeleted = false
1138 } else {
1139 agent.stop(nil)
1140 dMgr.deleteDeviceAgentToMap(agent)
1141 }
1142 }
1143 }
1144 if !allChildDeleted {
1145 return err
1146 }
1147 return nil
1148}
1149
khenaidoo6d62c002019-05-15 21:57:03 -04001150//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1151// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1152// device during a delete device operation.
1153func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentId(id string) []string {
1154 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1155 deviceIds := make([]string, 0)
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001156 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
1157 agent := value.(*DeviceAgent)
khenaidoo6d62c002019-05-15 21:57:03 -04001158 if agent.parentId == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001159 deviceIds = append(deviceIds, key.(string))
khenaidoo6d62c002019-05-15 21:57:03 -04001160 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001161 return true
1162 })
khenaidoo6d62c002019-05-15 21:57:03 -04001163 return deviceIds
1164}
1165
khenaidoo4d4802d2018-10-04 21:59:49 -04001166//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1167func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1168 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001169 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001170 if parentDevice != nil {
1171 for _, port := range parentDevice.Ports {
1172 for _, peer := range port.Peers {
1173 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1174 }
khenaidoo92e62c52018-10-03 14:02:54 -04001175 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001176 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001177 }
1178 return childDeviceIds, nil
1179}
1180
khenaidoo297cd252019-02-07 22:10:23 -05001181//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1182func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
1183 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
1184 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
1185 childDevices := make([]*voltha.Device, 0)
1186 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
1187 for _, deviceId := range childDeviceIds {
1188 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
1189 childDevices = append(childDevices, d)
1190 }
1191 }
1192 }
1193 return &voltha.Devices{Items: childDevices}, nil
1194 }
1195 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
1196}
1197
khenaidoo0a822f92019-05-08 15:15:57 -04001198func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001199 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -04001200 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001201 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1202 return err
1203 }
1204 return nil
1205}
1206
khenaidoof5a5bfa2019-01-23 22:20:29 -05001207func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1208 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1209 var res interface{}
1210 var err error
1211 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1212 if res, err = agent.downloadImage(ctx, img); err != nil {
1213 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1214 res = err
1215 }
1216 } else {
1217 res = status.Errorf(codes.NotFound, "%s", img.Id)
1218 }
1219 sendResponse(ctx, ch, res)
1220}
1221
1222func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1223 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1224 var res interface{}
1225 var err error
1226 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1227 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1228 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1229 res = err
1230 }
1231 } else {
1232 res = status.Errorf(codes.NotFound, "%s", img.Id)
1233 }
1234 sendResponse(ctx, ch, res)
1235}
1236
1237func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1238 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1239 var res interface{}
1240 var err error
1241 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1242 if res, err = agent.activateImage(ctx, img); err != nil {
1243 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1244 res = err
1245 }
1246 } else {
1247 res = status.Errorf(codes.NotFound, "%s", img.Id)
1248 }
1249 sendResponse(ctx, ch, res)
1250}
1251
1252func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1253 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1254 var res interface{}
1255 var err error
1256 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1257 if res, err = agent.revertImage(ctx, img); err != nil {
1258 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1259 res = err
1260 }
1261 } else {
1262 res = status.Errorf(codes.NotFound, "%s", img.Id)
1263 }
1264 sendResponse(ctx, ch, res)
1265}
1266
1267func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1268 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1269 var res interface{}
1270 var err error
1271 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1272 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1273 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1274 res = err
1275 }
1276 } else {
1277 res = status.Errorf(codes.NotFound, "%s", img.Id)
1278 }
1279 sendResponse(ctx, ch, res)
1280}
1281
khenaidoof5a5bfa2019-01-23 22:20:29 -05001282func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1283 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1284 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1285 if err := agent.updateImageDownload(img); err != nil {
1286 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1287 return err
1288 }
1289 } else {
1290 return status.Errorf(codes.NotFound, "%s", img.Id)
1291 }
1292 return nil
1293}
1294
1295func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1296 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1297 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1298 return agent.getImageDownload(ctx, img)
1299 }
1300 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1301}
1302
1303func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1304 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1305 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1306 return agent.listImageDownloads(ctx, deviceId)
1307 }
1308 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1309}
1310
khenaidoo0a822f92019-05-08 15:15:57 -04001311func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1312 log.Info("SetAdminStateToEnable")
1313 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1314 return agent.updateAdminState(voltha.AdminState_ENABLED)
1315 }
1316 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1317}
1318
khenaidoo92e62c52018-10-03 14:02:54 -04001319func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001320 log.Info("activateDevice")
1321 return nil
1322}
1323
khenaidoo92e62c52018-10-03 14:02:54 -04001324func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1325 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001326 return nil
1327}
1328
khenaidoo92e62c52018-10-03 14:02:54 -04001329func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001330 log.Info("abandonDevice")
1331 return nil
1332}
1333
khenaidoo92e62c52018-10-03 14:02:54 -04001334func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001335 log.Info("reEnableDevice")
1336 return nil
1337}
1338
khenaidoo92e62c52018-10-03 14:02:54 -04001339func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001340 log.Info("noOp")
1341 return nil
1342}
1343
khenaidoo92e62c52018-10-03 14:02:54 -04001344func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001345 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001346 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001347}
1348
khenaidoo0a822f92019-05-08 15:15:57 -04001349func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001350 log.Errorw("NotifyInvalidTransition", log.Fields{
1351 "device": pcDevice.Id,
1352 "adminState": pcDevice.AdminState,
1353 "operState": pcDevice.OperStatus,
1354 "connState": pcDevice.ConnectStatus,
1355 })
khenaidoo0a822f92019-05-08 15:15:57 -04001356 //TODO: notify over kafka?
1357 return nil
1358}
1359
khenaidoob9203542018-09-17 22:56:37 -04001360func funcName(f interface{}) string {
1361 p := reflect.ValueOf(f).Pointer()
1362 rf := runtime.FuncForPC(p)
1363 return rf.Name()
1364}
1365
1366func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001367 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
1368 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001369 }
1370}
1371
1372func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -04001373 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001374 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -04001375 return &device.ParentId
1376 }
1377 return nil
1378}
serkant.uluderya334479d2019-04-10 08:26:15 -07001379
1380func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1381 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1382 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1383 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1384 var res interface{}
1385 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1386 res = agent.simulateAlarm(ctx, simulatereq)
1387 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1388 }
1389 //TODO CLI always get successful response
1390 sendResponse(ctx, ch, res)
1391}