blob: 9434dcf8264f39af20cae620870445e5b81782c4 [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"
khenaidoo3d3b8c22019-05-22 18:10:39 -040021 "github.com/opencord/voltha-go/rw_core/utils"
Scott Bakercb7c88a2019-10-16 18:32:48 -070022 "github.com/opencord/voltha-lib-go/pkg/db/model"
23 "github.com/opencord/voltha-lib-go/pkg/kafka"
24 "github.com/opencord/voltha-lib-go/pkg/log"
25 "github.com/opencord/voltha-lib-go/pkg/probe"
William Kurkiandaa6bb22019-03-07 12:26:28 -050026 ic "github.com/opencord/voltha-protos/go/inter_container"
27 ofp "github.com/opencord/voltha-protos/go/openflow_13"
28 "github.com/opencord/voltha-protos/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040029 "google.golang.org/grpc/codes"
30 "google.golang.org/grpc/status"
31 "reflect"
32 "runtime"
33 "sync"
34)
35
36type DeviceManager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040037 deviceAgents sync.Map
38 rootDevices map[string]bool
39 lockRootDeviceMap sync.RWMutex
40 core *Core
41 adapterProxy *AdapterProxy
42 adapterMgr *AdapterManager
43 logicalDeviceMgr *LogicalDeviceManager
44 kafkaICProxy *kafka.InterContainerProxy
45 stateTransitions *TransitionMap
46 clusterDataProxy *model.Proxy
47 coreInstanceId string
48 exitChannel chan int
49 defaultTimeout int64
50 devicesLoadingLock sync.RWMutex
51 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040052}
53
Richard Jankowski199fd862019-03-18 14:49:51 -040054func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040055 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040056 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040057 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040058 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040059 deviceMgr.kafkaICProxy = core.kmp
Kent Hagermana6d0c362019-07-30 12:50:21 -040060 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic)
Richard Jankowski199fd862019-03-18 14:49:51 -040061 deviceMgr.coreInstanceId = core.instanceId
62 deviceMgr.clusterDataProxy = core.clusterDataProxy
63 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040064 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
65 deviceMgr.defaultTimeout = core.config.DefaultCoreTimeout
khenaidoo4c9e5592019-09-09 16:20:41 -040066 deviceMgr.devicesLoadingLock = sync.RWMutex{}
67 deviceMgr.deviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040068 return &deviceMgr
69}
70
khenaidoo4d4802d2018-10-04 21:59:49 -040071func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040072 log.Info("starting-device-manager")
73 dMgr.logicalDeviceMgr = logicalDeviceMgr
74 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070075 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
khenaidoob9203542018-09-17 22:56:37 -040076 log.Info("device-manager-started")
77}
78
khenaidoo4d4802d2018-10-04 21:59:49 -040079func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040080 log.Info("stopping-device-manager")
81 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070082 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
khenaidoob9203542018-09-17 22:56:37 -040083 log.Info("device-manager-stopped")
84}
85
86func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
87 if ctx.Err() == nil {
88 // Returned response only of the ctx has not been cancelled/timeout/etc
89 // Channel is automatically closed when a context is Done
90 ch <- result
91 log.Debugw("sendResponse", log.Fields{"result": result})
92 } else {
93 // Should the transaction be reverted back?
94 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
95 }
96}
97
98func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040099 if _, exist := dMgr.deviceAgents.Load(agent.deviceId); !exist {
100 dMgr.deviceAgents.Store(agent.deviceId, agent)
khenaidoob9203542018-09-17 22:56:37 -0400101 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400102 dMgr.lockRootDeviceMap.Lock()
103 defer dMgr.lockRootDeviceMap.Unlock()
104 dMgr.rootDevices[agent.deviceId] = agent.isRootdevice
105
khenaidoob9203542018-09-17 22:56:37 -0400106}
107
khenaidoo4c9e5592019-09-09 16:20:41 -0400108func (dMgr *DeviceManager) deleteDeviceAgentFromMap(agent *DeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400109 dMgr.deviceAgents.Delete(agent.deviceId)
khenaidoo2c6a0992019-04-29 13:46:56 -0400110 dMgr.lockRootDeviceMap.Lock()
111 defer dMgr.lockRootDeviceMap.Unlock()
112 delete(dMgr.rootDevices, agent.deviceId)
khenaidoo4d4802d2018-10-04 21:59:49 -0400113}
114
khenaidoo297cd252019-02-07 22:10:23 -0500115// 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 -0400116func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400117 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
118 return agent.(*DeviceAgent)
khenaidoo297cd252019-02-07 22:10:23 -0500119 } else {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400120 // Try to load into memory - loading will also create the device agent and set the device ownership
khenaidoo297cd252019-02-07 22:10:23 -0500121 if err := dMgr.load(deviceId); err == nil {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400122 if agent, ok = dMgr.deviceAgents.Load(deviceId); !ok {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400123 return nil
124 } else {
125 // Register this device for ownership tracking
126 go dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: deviceId})
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400127 return agent.(*DeviceAgent)
khenaidoo297cd252019-02-07 22:10:23 -0500128 }
khenaidoo3d3b8c22019-05-22 18:10:39 -0400129 } else {
130 //TODO: Change the return params to return an error as well
131 log.Errorw("loading-device-failed", log.Fields{"deviceId": deviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500132 }
khenaidoob9203542018-09-17 22:56:37 -0400133 }
134 return nil
135}
136
khenaidoo297cd252019-02-07 22:10:23 -0500137// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500138func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500139 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400140
141 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
142 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
143 return true
144 })
145
khenaidoo7ccedd52018-12-14 16:48:54 -0500146 return result
147}
148
khenaidoob9203542018-09-17 22:56:37 -0400149func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400150 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400151
khenaidoo5e677ae2019-02-28 17:26:29 -0500152 // Ensure this device is set as root
153 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400154 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400155 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400156 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500157 agent.start(ctx, false)
khenaidoob9203542018-09-17 22:56:37 -0400158
khenaidoo92e62c52018-10-03 14:02:54 -0400159 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400160}
161
162func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400163 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400164 var res interface{}
165 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
166 res = agent.enableDevice(ctx)
167 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400168 }
169
170 sendResponse(ctx, ch, res)
171}
172
khenaidoo92e62c52018-10-03 14:02:54 -0400173func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
174 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400175 var res interface{}
176 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
177 res = agent.disableDevice(ctx)
178 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400179 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400180 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400181 }
khenaidoo92e62c52018-10-03 14:02:54 -0400182
183 sendResponse(ctx, ch, res)
184}
185
khenaidoo4d4802d2018-10-04 21:59:49 -0400186func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
187 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
188 var res interface{}
189 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
190 res = agent.rebootDevice(ctx)
191 log.Debugw("rebootDevice-result", log.Fields{"result": res})
192 } else {
193 res = status.Errorf(codes.NotFound, "%s", id.Id)
194 }
195 sendResponse(ctx, ch, res)
196}
197
198func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
199 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
200 var res interface{}
201 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
202 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400203 log.Debugw("deleteDevice-result", log.Fields{"result": res})
204 } else {
205 res = status.Errorf(codes.NotFound, "%s", id.Id)
206 }
207 sendResponse(ctx, ch, res)
208}
209
khenaidoo6d62c002019-05-15 21:57:03 -0400210// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
211// This function is called only in the Core that does not own this device. In the Core that owns this device then a
212// deletion deletion also includes removal of any reference of this device.
213func (dMgr *DeviceManager) stopManagingDevice(id string) {
214 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
215 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
216 if root, _ := dMgr.IsRootDevice(id); root == true {
217 // stop managing the logical device
218 ldeviceId := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceId(id)
219 if ldeviceId != "" { // Can happen if logical device agent was already stopped
220 dMgr.core.deviceOwnership.AbandonDevice(ldeviceId)
221 }
222 // stop managing the child devices
223 childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentId(id)
224 for _, cId := range childDeviceIds {
225 dMgr.stopManagingDevice(cId)
226 }
227 }
228 if agent := dMgr.getDeviceAgent(id); agent != nil {
229 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -0400230 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400231 // Abandon the device ownership
232 dMgr.core.deviceOwnership.AbandonDevice(id)
233 }
234 }
235}
236
khenaidoo0a822f92019-05-08 15:15:57 -0400237func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
238 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400239 dMgr.stopManagingDevice(cDevice.Id)
240 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400241}
242
khenaidoo297cd252019-02-07 22:10:23 -0500243// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400244func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
245 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400246 if agent := dMgr.getDeviceAgent(id); agent != nil {
247 return agent.getDevice()
248 }
249 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400250}
251
Matt Jeanneret4e241952019-02-28 11:16:04 -0500252func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
Matt Jeanneret0c5088c2019-04-22 16:16:19 -0400253 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber,
254 "parentPortNo": parentPortNo, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500255
256 var parentDevice *voltha.Device
257 var err error
258 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
259 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
260 }
261 var childDeviceIds []string
262 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
263 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
264 }
265 if len(childDeviceIds) == 0 {
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700266 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500267 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
268 }
269
270 var foundChildDevice *voltha.Device
271 for _, childDeviceId := range childDeviceIds {
272 found := false
273 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
274
275 foundOnuId := false
276 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
277 if searchDevice.ParentPortNo == uint32(parentPortNo) {
278 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
279 foundOnuId = true
280 }
281 }
282
283 foundSerialNumber := false
284 if searchDevice.SerialNumber == serialNumber {
285 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
286 foundSerialNumber = true
287 }
288
289 // if both onuId and serialNumber are provided both must be true for the device to be found
290 // otherwise whichever one found a match is good enough
291 if onuId > 0 && serialNumber != "" {
292 found = foundOnuId && foundSerialNumber
293 } else {
294 found = foundOnuId || foundSerialNumber
295 }
296
297 if found == true {
298 foundChildDevice = searchDevice
299 break
300 }
301 }
302 }
303
304 if foundChildDevice != nil {
305 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
306 return foundChildDevice, nil
307 }
308
309 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
310 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
311 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
312}
313
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500314func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
315 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
316
317 var parentDevice *voltha.Device
318 var err error
319 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
320 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
321 }
322 var childDeviceIds []string
323 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
324 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
325 }
326 if len(childDeviceIds) == 0 {
327 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
328 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
329 }
330
331 var foundChildDevice *voltha.Device
332 for _, childDeviceId := range childDeviceIds {
333 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
334 if searchDevice.ProxyAddress == proxyAddress {
335 foundChildDevice = searchDevice
336 break
337 }
338 }
339 }
340
341 if foundChildDevice != nil {
342 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
343 return foundChildDevice, nil
344 }
345
346 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
347 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
348}
349
khenaidoo297cd252019-02-07 22:10:23 -0500350func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400351 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500352 return exist
353}
354
khenaidoo19d7b632018-10-30 10:49:50 -0400355func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400356 dMgr.lockRootDeviceMap.RLock()
357 defer dMgr.lockRootDeviceMap.RUnlock()
358 if exist := dMgr.rootDevices[id]; exist {
359 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400360 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400361 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400362}
363
Stephane Barbarieaa467942019-02-06 14:09:44 -0500364// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400365func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400366 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400367 result := &voltha.Devices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400368 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500369 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500370 // If device is not in memory then set it up
371 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400372 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400373 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500374 if err := agent.start(nil, true); err != nil {
375 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
376 agent.stop(nil)
377 } else {
378 dMgr.addDeviceAgentToMap(agent)
379 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500380 }
381 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400382 }
383 }
khenaidoo6d62c002019-05-15 21:57:03 -0400384 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400385 return result, nil
386}
387
khenaidoo6d62c002019-05-15 21:57:03 -0400388//getDeviceFromModelretrieves the device data from the model.
389func (dMgr *DeviceManager) getDeviceFromModel(deviceId string) (*voltha.Device, error) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400390 if device := dMgr.clusterDataProxy.Get(context.Background(), "/devices/"+deviceId, 0, false, ""); device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400391 if d, ok := device.(*voltha.Device); ok {
392 return d, nil
393 }
394 }
395 return nil, status.Error(codes.NotFound, deviceId)
396}
397
khenaidoo297cd252019-02-07 22:10:23 -0500398// loadDevice loads the deviceId in memory, if not present
399func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
khenaidoo297cd252019-02-07 22:10:23 -0500400 if deviceId == "" {
401 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
402 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400403 var err error
404 var device *voltha.Device
405 dMgr.devicesLoadingLock.Lock()
406 if _, exist := dMgr.deviceLoadingInProgress[deviceId]; !exist {
407 if !dMgr.IsDeviceInCache(deviceId) {
408 dMgr.deviceLoadingInProgress[deviceId] = []chan int{make(chan int, 1)}
409 dMgr.devicesLoadingLock.Unlock()
410 // Proceed with the loading only if the device exist in the Model (could have been deleted)
411 if device, err = dMgr.getDeviceFromModel(deviceId); err == nil {
412 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
413 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
414 if err = agent.start(nil, true); err != nil {
415 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceId, "error": err})
416 agent.stop(nil)
417 } else {
418 dMgr.addDeviceAgentToMap(agent)
419 }
420 } else {
421 log.Debugw("Device not in model", log.Fields{"deviceId": deviceId})
khenaidoo6d62c002019-05-15 21:57:03 -0400422 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400423 // announce completion of task to any number of waiting channels
424 dMgr.devicesLoadingLock.Lock()
425 if v, ok := dMgr.deviceLoadingInProgress[deviceId]; ok {
426 for _, ch := range v {
427 close(ch)
428 }
429 delete(dMgr.deviceLoadingInProgress, deviceId)
430 }
431 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400432 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400433 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500434 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400435 } else {
436 ch := make(chan int, 1)
437 dMgr.deviceLoadingInProgress[deviceId] = append(dMgr.deviceLoadingInProgress[deviceId], ch)
438 dMgr.devicesLoadingLock.Unlock()
439 // Wait for the channel to be closed, implying the process loading this device is done.
440 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500441 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400442 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
443 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500444 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400445 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceId)
khenaidoo297cd252019-02-07 22:10:23 -0500446}
447
448// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
449func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
450 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
451 if device.Root {
452 // Scenario A
453 if device.ParentId != "" {
454 // Load logical device if needed.
455 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
456 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
457 }
458 } else {
459 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
460 }
461 // Load all child devices, if needed
462 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
463 for _, childDeviceId := range childDeviceIds {
464 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400465 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500466 return err
467 }
468 }
469 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
470 } else {
471 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
472 }
473 }
474 return nil
475}
476
477// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
478// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
479// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
480// and the proceed with the request.
481func (dMgr *DeviceManager) load(deviceId string) error {
482 log.Debug("load...")
483 // First load the device - this may fail in case the device was deleted intentionally by the other core
484 var dAgent *DeviceAgent
485 var err error
486 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500487 return err
488 }
489 // Get the loaded device details
490 var device *voltha.Device
491 if device, err = dAgent.getDevice(); err != nil {
492 return err
493 }
494
495 // If the device is in Pre-provisioning or deleted state stop here
496 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
497 return nil
498 }
499
500 // Now we face two scenarios
501 if device.Root {
502 // Load all children as well as the parent of this device (logical_device)
503 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
504 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
505 return err
506 }
507 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
508 } else {
509 // Scenario B - use the parentId of that device (root device) to trigger the loading
510 if device.ParentId != "" {
511 return dMgr.load(device.ParentId)
512 }
513 }
514 return nil
515}
516
khenaidoo7ccedd52018-12-14 16:48:54 -0500517// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
518func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
519 log.Debug("ListDeviceIDs")
520 // Report only device IDs that are in the device agent map
521 return dMgr.listDeviceIdsFromMap(), nil
522}
523
khenaidoo4c9e5592019-09-09 16:20:41 -0400524//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
525//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500526func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400527 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500528 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400529 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500530 toReconcile := len(ids.Items)
531 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400532 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500533 for _, id := range ids.Items {
khenaidoo4c9e5592019-09-09 16:20:41 -0400534 if err = dMgr.load(id.Id); err != nil {
535 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
536 } else {
537 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500538 }
539 }
540 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400541 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500542 }
543 } else {
544 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
545 }
546 sendResponse(ctx, ch, res)
547}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500548
khenaidooba6b6c42019-08-02 09:11:56 -0400549// isOkToReconcile validates whether a device is in the correct status to be reconciled
550func isOkToReconcile(device *voltha.Device) bool {
551 if device == nil {
552 return false
553 }
554 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
555}
556
557// adapterRestarted is invoked whenever an adapter is restarted
558func (dMgr *DeviceManager) adapterRestarted(adapter *voltha.Adapter) error {
559 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
560
561 // Let's reconcile the device managed by this Core only
562 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
563 if len(rootDeviceIds) == 0 {
564 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
565 return nil
566 }
567
568 chnlsList := make([]chan interface{}, 0)
569 for _, rootDeviceId := range rootDeviceIds {
570 if rootDevice, _ := dMgr.getDeviceFromModel(rootDeviceId); rootDevice != nil {
571 if rootDevice.Adapter == adapter.Id {
572 if isOkToReconcile(rootDevice) {
573 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
574 chnlsList = dMgr.sendReconcileDeviceRequest(rootDevice, chnlsList)
575 } else {
576 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
577 }
578 } else { // Should we be reconciling the root's children instead?
579 childManagedByAdapter:
580 for _, port := range rootDevice.Ports {
581 for _, peer := range port.Peers {
582 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
583 if childDevice.Adapter == adapter.Id {
584 if isOkToReconcile(childDevice) {
585 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
586 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
587 } else {
588 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
589 }
590 } else {
591 // All child devices under a parent device are typically managed by the same adapter type.
592 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
593 break childManagedByAdapter
594 }
595 }
596 }
597 }
598 }
599 }
600 }
601 if len(chnlsList) > 0 {
602 // Wait for completion
603 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
604 return status.Errorf(codes.Aborted, "errors-%s", res)
605 }
606 } else {
607 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
608 }
609 return nil
610}
611
612func (dMgr *DeviceManager) sendReconcileDeviceRequest(device *voltha.Device, chnlsList []chan interface{}) []chan interface{} {
613 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
614 // point of creating a device agent (if the device is not being managed by this Core) before sending the request
615 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to teh adapter via
616 // the adapter_proxy.
617 ch := make(chan interface{})
618 chnlsList = append(chnlsList, ch)
619 go func(device *voltha.Device) {
620 if err := dMgr.adapterProxy.ReconcileDevice(context.Background(), device); err != nil {
621 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
622 ch <- status.Errorf(codes.Internal, "device: %s", device.Id)
623 }
624 ch <- nil
625 }(device)
626
627 return chnlsList
628}
629
630func (dMgr *DeviceManager) reconcileChildDevices(parentDeviceId string) error {
631 if parentDevice, _ := dMgr.getDeviceFromModel(parentDeviceId); parentDevice != nil {
632 chnlsList := make([]chan interface{}, 0)
633 for _, port := range parentDevice.Ports {
634 for _, peer := range port.Peers {
635 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
636 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
637 }
638 }
639 }
640 // Wait for completion
641 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
642 return status.Errorf(codes.Aborted, "errors-%s", res)
643 }
644 }
645 return nil
646}
647
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700648func (dMgr *DeviceManager) updateDeviceUsingAdapterData(device *voltha.Device) error {
649 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400650 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700651 return agent.updateDeviceUsingAdapterData(device)
khenaidoob9203542018-09-17 22:56:37 -0400652 }
653 return status.Errorf(codes.NotFound, "%s", device.Id)
654}
655
656func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
657 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400658 if err := agent.addPort(port); err != nil {
659 return err
660 }
661 // Setup peer ports
662 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
663 for _, peerPort := range port.Peers {
664 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
665 if err := agent.addPeerPort(meAsPeer); err != nil {
666 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
667 return err
668 }
669 }
670 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400671 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
672 // then a logical port will be added to the logical device and the device graph generated. If the port is a
673 // PON port then only the device graph will be generated.
674 if device, err := dMgr.GetDevice(deviceId); err == nil {
675 go dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
676 } else {
677 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
678 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400679 }
khenaidoo92e62c52018-10-03 14:02:54 -0400680 return nil
681 } else {
682 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400683 }
khenaidoob9203542018-09-17 22:56:37 -0400684}
685
khenaidoo0a822f92019-05-08 15:15:57 -0400686func (dMgr *DeviceManager) deletePeerPorts(fromDeviceId string, deviceId string) error {
687 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceId, "deviceid": deviceId})
688 if agent := dMgr.getDeviceAgent(fromDeviceId); agent != nil {
689 return agent.deletePeerPorts(deviceId)
690 }
691 return status.Errorf(codes.NotFound, "%s", deviceId)
692}
693
Manikkaraj kb1a10922019-07-29 12:10:34 -0400694func (dMgr *DeviceManager) addFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
695 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceId, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -0400696 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400697 return agent.addFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400698 }
699 return status.Errorf(codes.NotFound, "%s", deviceId)
700}
701
Manikkaraj kb1a10922019-07-29 12:10:34 -0400702func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400703 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceId})
704 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400705 return agent.deleteFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400706 }
707 return status.Errorf(codes.NotFound, "%s", deviceId)
708}
709
Manikkaraj kb1a10922019-07-29 12:10:34 -0400710func (dMgr *DeviceManager) updateFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400711 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceId})
712 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400713 return agent.updateFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400714 }
715 return status.Errorf(codes.NotFound, "%s", deviceId)
716}
717
khenaidoob3127472019-07-24 21:04:55 -0400718// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
719// following a user action
720func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
721 var res interface{}
722 if pmConfigs.Id == "" {
723 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
724 } else if agent := dMgr.getDeviceAgent(pmConfigs.Id); agent != nil {
725 res = agent.updatePmConfigs(ctx, pmConfigs)
726 } else {
727 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
728 }
729 sendResponse(ctx, ch, res)
730}
731
732// initPmConfigs initialize the pm configs as defined by the adapter.
733func (dMgr *DeviceManager) initPmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
734 if pmConfigs.Id == "" {
735 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
736 }
khenaidoob9203542018-09-17 22:56:37 -0400737 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400738 return agent.initPmConfigs(pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400739 }
740 return status.Errorf(codes.NotFound, "%s", deviceId)
741}
742
khenaidoob3127472019-07-24 21:04:55 -0400743func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceId string) (*voltha.PmConfigs, error) {
744 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
745 return agent.listPmConfigs(ctx)
746 }
747 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
748}
749
khenaidoo79232702018-12-04 11:00:41 -0500750func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400751 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400752 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
753 return agent.getSwitchCapability(ctx)
754 }
755 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
756}
757
khenaidoo92e62c52018-10-03 14:02:54 -0400758func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
759 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400760 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400761 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400762 }
763 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
764}
765
khenaidoo79232702018-12-04 11:00:41 -0500766func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400767 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400768 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
769 return agent.getPortCapability(ctx, portNo)
770 }
771 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
772}
773
khenaidoo92e62c52018-10-03 14:02:54 -0400774func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
775 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400776 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400777 return agent.updateDeviceStatus(operStatus, connStatus)
778 }
779 return status.Errorf(codes.NotFound, "%s", deviceId)
780}
781
khenaidoo4d4802d2018-10-04 21:59:49 -0400782func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
783 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
784 var parentDevice *voltha.Device
785 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400786 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400787 return status.Errorf(codes.Aborted, "%s", err.Error())
788 }
789 var childDeviceIds []string
790 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
791 return status.Errorf(codes.Aborted, "%s", err.Error())
792 }
793 if len(childDeviceIds) == 0 {
794 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
795 }
796 for _, childDeviceId := range childDeviceIds {
797 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
798 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
799 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
800 }
801 }
802 }
803 return nil
804}
805
khenaidoo92e62c52018-10-03 14:02:54 -0400806func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
807 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
808 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
809 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400810 }
811 return status.Errorf(codes.NotFound, "%s", deviceId)
812}
813
khenaidoo0a822f92019-05-08 15:15:57 -0400814func (dMgr *DeviceManager) deleteAllPorts(deviceId string) error {
815 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceId})
816 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
817 if err := agent.deleteAllPorts(); err != nil {
818 return err
819 }
820 // Notify the logical device manager to remove all logical ports, if needed.
821 // At this stage the device itself may gave been deleted already at a deleteAllPorts
822 // typically is part of a device deletion phase.
823 if device, err := dMgr.GetDevice(deviceId); err == nil {
824 go dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
825 } else {
826 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
827 return err
828 }
829 return nil
830 }
831 return status.Errorf(codes.NotFound, "%s", deviceId)
832}
833
khenaidoo3ab34882019-05-02 21:33:30 -0400834//updatePortsState updates all ports on the device
835func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
836 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
837
838 var adminState voltha.AdminState_AdminState
839 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
840 switch state {
841 case voltha.OperStatus_ACTIVE:
842 adminState = voltha.AdminState_ENABLED
843 if err := agent.enablePorts(); err != nil {
844 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
845 return err
846 }
847 case voltha.OperStatus_UNKNOWN:
848 adminState = voltha.AdminState_DISABLED
849 if err := agent.disablePorts(); err != nil {
850 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
851 return err
852 }
853 default:
854 return status.Error(codes.Unimplemented, "state-change-not-implemented")
855 }
856 // Notify the logical device about the state change
857 if device, err := dMgr.GetDevice(deviceId); err != nil {
858 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
859 return err
860 } else {
861 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
862 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
863 return err
864 }
865 return nil
866 }
867 }
868 return status.Errorf(codes.NotFound, "%s", deviceId)
869}
870
Matt Jeanneret4e241952019-02-28 11:16:04 -0500871func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700872 channelId int64, vendorId string, serialNumber string, onuId int64) (*voltha.Device, error) {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700873 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId, "parentPortNo": parentPortNo, "deviceType": deviceType, "channelId": channelId, "vendorId": vendorId, "serialNumber": serialNumber, "onuId": onuId})
874
875 if deviceType == "" && vendorId != "" {
876 log.Debug("device-type-is-nil-fetching-device-type")
877 if deviceTypesIf := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, ""); deviceTypesIf != nil {
878 OLoop:
879 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
880 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
881 for _, v := range dType.VendorIds {
882 if v == vendorId {
883 deviceType = dType.Adapter
884 break OLoop
885 }
886 }
887 }
888 }
889 }
890 }
891 //if no match found for the vendorid,report adapter with the custom error message
892 if deviceType == "" {
893 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorId})
894 return nil, status.Errorf(codes.NotFound, "%s", vendorId)
895 }
khenaidoob9203542018-09-17 22:56:37 -0400896
897 // Create the ONU device
898 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400899 childDevice.Type = deviceType
900 childDevice.ParentId = parentDeviceId
901 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500902 childDevice.VendorId = vendorId
903 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400904 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400905
906 //Get parent device type
907 parent, err := dMgr.GetDevice(parentDeviceId)
908 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500909 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700910 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400911 }
912
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700913 if device, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500914 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700915 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500916 }
917
918 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400919
920 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400921 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400922 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500923 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400924
khenaidoo09771ef2019-10-11 14:25:02 -0400925 // Since this Core has handled this request then it therefore owns this child device. Set the
926 // ownership of this device to this Core
927 dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: agent.deviceId})
928
khenaidoob9203542018-09-17 22:56:37 -0400929 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400930 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500931 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400932 }
933
khenaidoo79232702018-12-04 11:00:41 -0500934 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500935 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500936
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700937 return agent.lastData, nil
khenaidoob9203542018-09-17 22:56:37 -0400938}
939
940func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
941 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400942 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
943 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500944 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400945 return nil
khenaidoob9203542018-09-17 22:56:37 -0400946 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400947 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -0400948 for _, handler := range handlers {
949 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
950 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400951 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400952 return err
953 }
954 }
khenaidoob9203542018-09-17 22:56:37 -0400955 return nil
956}
957
khenaidoofdbad6e2018-11-06 22:26:38 -0500958func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
959 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
960 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
961 return agent.packetOut(outPort, packet)
962 }
963 return status.Errorf(codes.NotFound, "%s", deviceId)
964}
965
khenaidoo297cd252019-02-07 22:10:23 -0500966func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500967 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
968 // Get the logical device Id based on the deviceId
969 var device *voltha.Device
970 var err error
971 if device, err = dMgr.GetDevice(deviceId); err != nil {
972 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
973 return err
974 }
khenaidoo43c82122018-11-22 18:38:28 -0500975 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500976 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
977 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
978 }
979
khenaidoo297cd252019-02-07 22:10:23 -0500980 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500981 return err
982 }
983 return nil
984}
985
khenaidoo0a822f92019-05-08 15:15:57 -0400986func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
987 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -0400988 // Verify whether the logical device has already been created
989 if cDevice.ParentId != "" {
990 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
991 return nil
992 }
khenaidoob9203542018-09-17 22:56:37 -0400993 var logicalId *string
994 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400995 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400996 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
997 return err
998 }
999 // Update the parent device with the logical id
1000 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
1001 return nil
1002}
1003
khenaidoo0a822f92019-05-08 15:15:57 -04001004func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
1005 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001006 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001007 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001008 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1009 return err
1010 }
1011 // Remove the logical device Id from the parent device
1012 logicalId := ""
1013 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
1014 return nil
1015}
1016
khenaidoo0a822f92019-05-08 15:15:57 -04001017func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001018 log.Info("deleteLogicalPort")
1019 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001020 // Get the logical port associated with this device
1021 var lPortId *voltha.LogicalPortId
1022 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001023 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001024 return err
1025 }
1026 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
1027 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001028 return err
1029 }
khenaidoo92e62c52018-10-03 14:02:54 -04001030 return nil
1031}
1032
khenaidoo0a822f92019-05-08 15:15:57 -04001033func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1034 log.Info("deleteLogicalPorts")
1035 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1036 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1037 return err
1038 }
1039 return nil
1040}
1041
khenaidoo59ef7be2019-06-21 12:40:28 -04001042func (dMgr *DeviceManager) MarkChildDevicesAsUnReachable(device *voltha.Device) error {
1043 log.Info("MarkChildDevicesAsUnReachable")
1044 // Set the connection status to unreachable
1045 connStatus := voltha.ConnectStatus_UNREACHABLE
1046 // Do not set the operational status. Setting it to -1 will do the trick
1047 operStatus := voltha.OperStatus_OperStatus(-1)
1048 if err := dMgr.updateChildrenStatus(device.Id, operStatus, connStatus); err != nil {
1049 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1050 return err
1051 }
1052 return nil
1053}
1054
khenaidoo92e62c52018-10-03 14:02:54 -04001055func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1056 // Sanity check
1057 if childDevice.Root {
1058 // childDevice is the parent device
1059 return childDevice
1060 }
khenaidoo19d7b632018-10-30 10:49:50 -04001061 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001062 return parentDevice
1063}
1064
khenaidoo0a822f92019-05-08 15:15:57 -04001065//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1066//cannot manage the child devices. This will trigger the Core to disable all the child devices.
1067func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
1068 log.Debug("childDevicesLost")
1069 var err error
1070 var parentDevice *voltha.Device
1071 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1072 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1073 return err
1074 }
1075 return dMgr.DisableAllChildDevices(parentDevice)
1076}
1077
1078//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1079// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
1080func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
1081 log.Debug("childDevicesDetected")
1082 var err error
1083 var parentDevice *voltha.Device
1084 var childDeviceIds []string
1085
1086 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1087 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1088 return err
1089 }
1090
1091 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1092 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1093 }
1094 if len(childDeviceIds) == 0 {
1095 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1096 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001097 allChildEnableRequestSent := true
khenaidoo0a822f92019-05-08 15:15:57 -04001098 for _, childDeviceId := range childDeviceIds {
1099 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001100 // Run the children re-registration in its own routine
1101 go agent.enableDevice(nil)
1102 } else {
1103 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceId)
1104 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceId})
1105 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001106 }
1107 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001108 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001109 return err
1110 }
1111 return nil
1112}
1113
khenaidoo4d4802d2018-10-04 21:59:49 -04001114/*
1115All the functions below are callback functions where they are invoked with the latest and previous data. We can
1116therefore use the data as is without trying to get the latest from the model.
1117*/
1118
khenaidoo0a822f92019-05-08 15:15:57 -04001119//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1120func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1121 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001122 var childDeviceIds []string
1123 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001124 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1125 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001126 }
1127 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001128 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001129 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001130 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -04001131 for _, childDeviceId := range childDeviceIds {
1132 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1133 if err = agent.disableDevice(nil); err != nil {
1134 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001135 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001136 }
1137 }
1138 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001139 if !allChildDisable {
1140 return err
1141 }
khenaidoo92e62c52018-10-03 14:02:54 -04001142 return nil
1143}
1144
khenaidoo0a822f92019-05-08 15:15:57 -04001145//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1146func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1147 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001148 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001149 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001150 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1151 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001152 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001153 if len(childDeviceIds) == 0 {
1154 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1155 }
1156 allChildDeleted := true
1157 for _, childDeviceId := range childDeviceIds {
1158 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1159 if err = agent.deleteDevice(nil); err != nil {
1160 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
1161 allChildDeleted = false
1162 } else {
1163 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -04001164 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo4d4802d2018-10-04 21:59:49 -04001165 }
1166 }
1167 }
1168 if !allChildDeleted {
1169 return err
1170 }
1171 return nil
1172}
1173
khenaidoo6d62c002019-05-15 21:57:03 -04001174//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1175// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1176// device during a delete device operation.
1177func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentId(id string) []string {
1178 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1179 deviceIds := make([]string, 0)
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001180 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
1181 agent := value.(*DeviceAgent)
khenaidoo6d62c002019-05-15 21:57:03 -04001182 if agent.parentId == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001183 deviceIds = append(deviceIds, key.(string))
khenaidoo6d62c002019-05-15 21:57:03 -04001184 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001185 return true
1186 })
khenaidoo6d62c002019-05-15 21:57:03 -04001187 return deviceIds
1188}
1189
khenaidoo4d4802d2018-10-04 21:59:49 -04001190//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1191func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1192 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001193 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001194 if parentDevice != nil {
1195 for _, port := range parentDevice.Ports {
1196 for _, peer := range port.Peers {
1197 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1198 }
khenaidoo92e62c52018-10-03 14:02:54 -04001199 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001200 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001201 }
1202 return childDeviceIds, nil
1203}
1204
khenaidoo297cd252019-02-07 22:10:23 -05001205//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1206func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
1207 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
1208 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
1209 childDevices := make([]*voltha.Device, 0)
1210 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
1211 for _, deviceId := range childDeviceIds {
1212 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
1213 childDevices = append(childDevices, d)
1214 }
1215 }
1216 }
1217 return &voltha.Devices{Items: childDevices}, nil
1218 }
1219 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
1220}
1221
khenaidoo0a822f92019-05-08 15:15:57 -04001222func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001223 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -04001224 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001225 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1226 return err
1227 }
1228 return nil
1229}
1230
khenaidoof5a5bfa2019-01-23 22:20:29 -05001231func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1232 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1233 var res interface{}
1234 var err error
1235 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1236 if res, err = agent.downloadImage(ctx, img); err != nil {
1237 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1238 res = err
1239 }
1240 } else {
1241 res = status.Errorf(codes.NotFound, "%s", img.Id)
1242 }
1243 sendResponse(ctx, ch, res)
1244}
1245
1246func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1247 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1248 var res interface{}
1249 var err error
1250 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1251 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1252 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1253 res = err
1254 }
1255 } else {
1256 res = status.Errorf(codes.NotFound, "%s", img.Id)
1257 }
1258 sendResponse(ctx, ch, res)
1259}
1260
1261func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1262 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1263 var res interface{}
1264 var err error
1265 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1266 if res, err = agent.activateImage(ctx, img); err != nil {
1267 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1268 res = err
1269 }
1270 } else {
1271 res = status.Errorf(codes.NotFound, "%s", img.Id)
1272 }
1273 sendResponse(ctx, ch, res)
1274}
1275
1276func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1277 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1278 var res interface{}
1279 var err error
1280 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1281 if res, err = agent.revertImage(ctx, img); err != nil {
1282 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1283 res = err
1284 }
1285 } else {
1286 res = status.Errorf(codes.NotFound, "%s", img.Id)
1287 }
1288 sendResponse(ctx, ch, res)
1289}
1290
1291func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1292 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1293 var res interface{}
1294 var err error
1295 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1296 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1297 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1298 res = err
1299 }
1300 } else {
1301 res = status.Errorf(codes.NotFound, "%s", img.Id)
1302 }
1303 sendResponse(ctx, ch, res)
1304}
1305
khenaidoof5a5bfa2019-01-23 22:20:29 -05001306func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1307 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1308 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1309 if err := agent.updateImageDownload(img); err != nil {
1310 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1311 return err
1312 }
1313 } else {
1314 return status.Errorf(codes.NotFound, "%s", img.Id)
1315 }
1316 return nil
1317}
1318
1319func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1320 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1321 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1322 return agent.getImageDownload(ctx, img)
1323 }
1324 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1325}
1326
1327func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1328 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1329 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1330 return agent.listImageDownloads(ctx, deviceId)
1331 }
1332 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1333}
1334
khenaidoo0a822f92019-05-08 15:15:57 -04001335func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1336 log.Info("SetAdminStateToEnable")
1337 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1338 return agent.updateAdminState(voltha.AdminState_ENABLED)
1339 }
1340 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1341}
1342
khenaidoo92e62c52018-10-03 14:02:54 -04001343func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001344 log.Info("activateDevice")
1345 return nil
1346}
1347
khenaidoo92e62c52018-10-03 14:02:54 -04001348func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1349 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001350 return nil
1351}
1352
khenaidoo92e62c52018-10-03 14:02:54 -04001353func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001354 log.Info("abandonDevice")
1355 return nil
1356}
1357
khenaidoo92e62c52018-10-03 14:02:54 -04001358func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001359 log.Info("reEnableDevice")
1360 return nil
1361}
1362
khenaidoo92e62c52018-10-03 14:02:54 -04001363func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001364 log.Info("noOp")
1365 return nil
1366}
1367
khenaidoo92e62c52018-10-03 14:02:54 -04001368func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001369 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001370 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001371}
1372
khenaidoo0a822f92019-05-08 15:15:57 -04001373func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001374 log.Errorw("NotifyInvalidTransition", log.Fields{
1375 "device": pcDevice.Id,
1376 "adminState": pcDevice.AdminState,
1377 "operState": pcDevice.OperStatus,
1378 "connState": pcDevice.ConnectStatus,
1379 })
khenaidoo0a822f92019-05-08 15:15:57 -04001380 //TODO: notify over kafka?
1381 return nil
1382}
1383
khenaidoob9203542018-09-17 22:56:37 -04001384func funcName(f interface{}) string {
1385 p := reflect.ValueOf(f).Pointer()
1386 rf := runtime.FuncForPC(p)
1387 return rf.Name()
1388}
1389
1390func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001391 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
1392 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001393 }
1394}
1395
khenaidoo4c9e5592019-09-09 16:20:41 -04001396func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) string {
khenaidoo19d7b632018-10-30 10:49:50 -04001397 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001398 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001399 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001400 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001401 return ""
khenaidoob9203542018-09-17 22:56:37 -04001402}
serkant.uluderya334479d2019-04-10 08:26:15 -07001403
1404func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1405 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1406 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1407 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1408 var res interface{}
1409 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1410 res = agent.simulateAlarm(ctx, simulatereq)
1411 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1412 }
1413 //TODO CLI always get successful response
1414 sendResponse(ctx, ch, res)
1415}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001416
1417func (dMgr *DeviceManager) updateDeviceReason(deviceId string, reason string) error {
1418 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceId, "reason": reason})
1419 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1420 return agent.updateDeviceReason(reason)
1421 }
1422 return status.Errorf(codes.NotFound, "%s", deviceId)
1423}