blob: 91c359a88d354b6ebd0d514b082bf450fc6b8900 [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"
David K. Bainbridgee4572ee2019-09-20 15:12:16 -070022 "github.com/opencord/voltha-go/common/probe"
khenaidoob9203542018-09-17 22:56:37 -040023 "github.com/opencord/voltha-go/db/model"
24 "github.com/opencord/voltha-go/kafka"
khenaidoo3d3b8c22019-05-22 18:10:39 -040025 "github.com/opencord/voltha-go/rw_core/utils"
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 {
khenaidooc3224532019-09-05 21:04:54 -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
khenaidooc3224532019-09-05 21:04:54 -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. Bainbridgee4572ee2019-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. Bainbridgee4572ee2019-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
khenaidooc3224532019-09-05 21:04:54 -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)
khenaidooc3224532019-09-05 21:04:54 -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 }
khenaidooc3224532019-09-05 21:04:54 -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 }
khenaidooc3224532019-09-05 21:04:54 -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 {
khenaidooc3224532019-09-05 21:04:54 -0400433 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500434 }
khenaidooc3224532019-09-05 21:04:54 -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 }
khenaidooc3224532019-09-05 21:04:54 -0400442 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
443 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500444 }
khenaidooc3224532019-09-05 21:04:54 -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 {
khenaidooc3224532019-09-05 21:04:54 -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
khenaidooc3224532019-09-05 21:04:54 -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{}) {
khenaidooc3224532019-09-05 21:04:54 -0400527 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500528 var res interface{}
khenaidooc3224532019-09-05 21:04:54 -0400529 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500530 toReconcile := len(ids.Items)
531 reconciled := 0
khenaidooc3224532019-09-05 21:04:54 -0400532 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500533 for _, id := range ids.Items {
khenaidooc3224532019-09-05 21:04:54 -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 {
khenaidooc3224532019-09-05 21:04:54 -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
925 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400926 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500927 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400928 }
929
khenaidoo79232702018-12-04 11:00:41 -0500930 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500931 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500932
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700933 return agent.lastData, nil
khenaidoob9203542018-09-17 22:56:37 -0400934}
935
936func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
937 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400938 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
939 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500940 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400941 return nil
khenaidoob9203542018-09-17 22:56:37 -0400942 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400943 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -0400944 for _, handler := range handlers {
945 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
946 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400947 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400948 return err
949 }
950 }
khenaidoob9203542018-09-17 22:56:37 -0400951 return nil
952}
953
khenaidoofdbad6e2018-11-06 22:26:38 -0500954func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
955 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
956 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
957 return agent.packetOut(outPort, packet)
958 }
959 return status.Errorf(codes.NotFound, "%s", deviceId)
960}
961
khenaidoo297cd252019-02-07 22:10:23 -0500962func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500963 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
964 // Get the logical device Id based on the deviceId
965 var device *voltha.Device
966 var err error
967 if device, err = dMgr.GetDevice(deviceId); err != nil {
968 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
969 return err
970 }
khenaidoo43c82122018-11-22 18:38:28 -0500971 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500972 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
973 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
974 }
975
khenaidoo297cd252019-02-07 22:10:23 -0500976 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500977 return err
978 }
979 return nil
980}
981
khenaidoo0a822f92019-05-08 15:15:57 -0400982func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
983 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -0400984 // Verify whether the logical device has already been created
985 if cDevice.ParentId != "" {
986 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
987 return nil
988 }
khenaidoob9203542018-09-17 22:56:37 -0400989 var logicalId *string
990 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400991 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400992 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
993 return err
994 }
995 // Update the parent device with the logical id
996 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
997 return nil
998}
999
khenaidoo0a822f92019-05-08 15:15:57 -04001000func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
1001 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001002 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001003 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001004 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1005 return err
1006 }
1007 // Remove the logical device Id from the parent device
1008 logicalId := ""
1009 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
1010 return nil
1011}
1012
khenaidoo0a822f92019-05-08 15:15:57 -04001013func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001014 log.Info("deleteLogicalPort")
1015 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001016 // Get the logical port associated with this device
1017 var lPortId *voltha.LogicalPortId
1018 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001019 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001020 return err
1021 }
1022 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
1023 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001024 return err
1025 }
khenaidoo92e62c52018-10-03 14:02:54 -04001026 return nil
1027}
1028
khenaidoo0a822f92019-05-08 15:15:57 -04001029func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1030 log.Info("deleteLogicalPorts")
1031 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1032 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1033 return err
1034 }
1035 return nil
1036}
1037
khenaidoo59ef7be2019-06-21 12:40:28 -04001038func (dMgr *DeviceManager) MarkChildDevicesAsUnReachable(device *voltha.Device) error {
1039 log.Info("MarkChildDevicesAsUnReachable")
1040 // Set the connection status to unreachable
1041 connStatus := voltha.ConnectStatus_UNREACHABLE
1042 // Do not set the operational status. Setting it to -1 will do the trick
1043 operStatus := voltha.OperStatus_OperStatus(-1)
1044 if err := dMgr.updateChildrenStatus(device.Id, operStatus, connStatus); err != nil {
1045 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1046 return err
1047 }
1048 return nil
1049}
1050
khenaidoo92e62c52018-10-03 14:02:54 -04001051func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1052 // Sanity check
1053 if childDevice.Root {
1054 // childDevice is the parent device
1055 return childDevice
1056 }
khenaidoo19d7b632018-10-30 10:49:50 -04001057 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001058 return parentDevice
1059}
1060
khenaidoo0a822f92019-05-08 15:15:57 -04001061//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1062//cannot manage the child devices. This will trigger the Core to disable all the child devices.
1063func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
1064 log.Debug("childDevicesLost")
1065 var err error
1066 var parentDevice *voltha.Device
1067 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1068 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1069 return err
1070 }
1071 return dMgr.DisableAllChildDevices(parentDevice)
1072}
1073
1074//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1075// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
1076func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
1077 log.Debug("childDevicesDetected")
1078 var err error
1079 var parentDevice *voltha.Device
1080 var childDeviceIds []string
1081
1082 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1083 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1084 return err
1085 }
1086
1087 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1088 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1089 }
1090 if len(childDeviceIds) == 0 {
1091 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1092 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001093 allChildEnableRequestSent := true
khenaidoo0a822f92019-05-08 15:15:57 -04001094 for _, childDeviceId := range childDeviceIds {
1095 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001096 // Run the children re-registration in its own routine
1097 go agent.enableDevice(nil)
1098 } else {
1099 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceId)
1100 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceId})
1101 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001102 }
1103 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001104 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001105 return err
1106 }
1107 return nil
1108}
1109
khenaidoo4d4802d2018-10-04 21:59:49 -04001110/*
1111All the functions below are callback functions where they are invoked with the latest and previous data. We can
1112therefore use the data as is without trying to get the latest from the model.
1113*/
1114
khenaidoo0a822f92019-05-08 15:15:57 -04001115//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1116func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1117 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001118 var childDeviceIds []string
1119 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001120 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1121 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001122 }
1123 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001124 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001125 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001126 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -04001127 for _, childDeviceId := range childDeviceIds {
1128 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1129 if err = agent.disableDevice(nil); err != nil {
1130 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001131 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001132 }
1133 }
1134 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001135 if !allChildDisable {
1136 return err
1137 }
khenaidoo92e62c52018-10-03 14:02:54 -04001138 return nil
1139}
1140
khenaidoo0a822f92019-05-08 15:15:57 -04001141//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1142func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1143 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001144 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001145 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001146 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1147 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001148 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001149 if len(childDeviceIds) == 0 {
1150 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1151 }
1152 allChildDeleted := true
1153 for _, childDeviceId := range childDeviceIds {
1154 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1155 if err = agent.deleteDevice(nil); err != nil {
1156 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
1157 allChildDeleted = false
1158 } else {
1159 agent.stop(nil)
khenaidooc3224532019-09-05 21:04:54 -04001160 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo4d4802d2018-10-04 21:59:49 -04001161 }
1162 }
1163 }
1164 if !allChildDeleted {
1165 return err
1166 }
1167 return nil
1168}
1169
khenaidoo6d62c002019-05-15 21:57:03 -04001170//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1171// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1172// device during a delete device operation.
1173func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentId(id string) []string {
1174 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1175 deviceIds := make([]string, 0)
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001176 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
1177 agent := value.(*DeviceAgent)
khenaidoo6d62c002019-05-15 21:57:03 -04001178 if agent.parentId == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001179 deviceIds = append(deviceIds, key.(string))
khenaidoo6d62c002019-05-15 21:57:03 -04001180 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001181 return true
1182 })
khenaidoo6d62c002019-05-15 21:57:03 -04001183 return deviceIds
1184}
1185
khenaidoo4d4802d2018-10-04 21:59:49 -04001186//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1187func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1188 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001189 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001190 if parentDevice != nil {
1191 for _, port := range parentDevice.Ports {
1192 for _, peer := range port.Peers {
1193 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1194 }
khenaidoo92e62c52018-10-03 14:02:54 -04001195 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001196 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001197 }
1198 return childDeviceIds, nil
1199}
1200
khenaidoo297cd252019-02-07 22:10:23 -05001201//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1202func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
1203 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
1204 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
1205 childDevices := make([]*voltha.Device, 0)
1206 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
1207 for _, deviceId := range childDeviceIds {
1208 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
1209 childDevices = append(childDevices, d)
1210 }
1211 }
1212 }
1213 return &voltha.Devices{Items: childDevices}, nil
1214 }
1215 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
1216}
1217
khenaidoo0a822f92019-05-08 15:15:57 -04001218func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001219 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -04001220 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001221 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1222 return err
1223 }
1224 return nil
1225}
1226
khenaidoof5a5bfa2019-01-23 22:20:29 -05001227func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1228 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1229 var res interface{}
1230 var err error
1231 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1232 if res, err = agent.downloadImage(ctx, img); err != nil {
1233 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1234 res = err
1235 }
1236 } else {
1237 res = status.Errorf(codes.NotFound, "%s", img.Id)
1238 }
1239 sendResponse(ctx, ch, res)
1240}
1241
1242func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1243 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1244 var res interface{}
1245 var err error
1246 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1247 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1248 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1249 res = err
1250 }
1251 } else {
1252 res = status.Errorf(codes.NotFound, "%s", img.Id)
1253 }
1254 sendResponse(ctx, ch, res)
1255}
1256
1257func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1258 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1259 var res interface{}
1260 var err error
1261 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1262 if res, err = agent.activateImage(ctx, img); err != nil {
1263 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1264 res = err
1265 }
1266 } else {
1267 res = status.Errorf(codes.NotFound, "%s", img.Id)
1268 }
1269 sendResponse(ctx, ch, res)
1270}
1271
1272func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1273 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1274 var res interface{}
1275 var err error
1276 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1277 if res, err = agent.revertImage(ctx, img); err != nil {
1278 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1279 res = err
1280 }
1281 } else {
1282 res = status.Errorf(codes.NotFound, "%s", img.Id)
1283 }
1284 sendResponse(ctx, ch, res)
1285}
1286
1287func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1288 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1289 var res interface{}
1290 var err error
1291 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1292 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1293 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1294 res = err
1295 }
1296 } else {
1297 res = status.Errorf(codes.NotFound, "%s", img.Id)
1298 }
1299 sendResponse(ctx, ch, res)
1300}
1301
khenaidoof5a5bfa2019-01-23 22:20:29 -05001302func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1303 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1304 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1305 if err := agent.updateImageDownload(img); err != nil {
1306 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1307 return err
1308 }
1309 } else {
1310 return status.Errorf(codes.NotFound, "%s", img.Id)
1311 }
1312 return nil
1313}
1314
1315func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1316 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1317 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1318 return agent.getImageDownload(ctx, img)
1319 }
1320 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1321}
1322
1323func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1324 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1325 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1326 return agent.listImageDownloads(ctx, deviceId)
1327 }
1328 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1329}
1330
khenaidoo0a822f92019-05-08 15:15:57 -04001331func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1332 log.Info("SetAdminStateToEnable")
1333 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1334 return agent.updateAdminState(voltha.AdminState_ENABLED)
1335 }
1336 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1337}
1338
khenaidoo92e62c52018-10-03 14:02:54 -04001339func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001340 log.Info("activateDevice")
1341 return nil
1342}
1343
khenaidoo92e62c52018-10-03 14:02:54 -04001344func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1345 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001346 return nil
1347}
1348
khenaidoo92e62c52018-10-03 14:02:54 -04001349func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001350 log.Info("abandonDevice")
1351 return nil
1352}
1353
khenaidoo92e62c52018-10-03 14:02:54 -04001354func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001355 log.Info("reEnableDevice")
1356 return nil
1357}
1358
khenaidoo92e62c52018-10-03 14:02:54 -04001359func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001360 log.Info("noOp")
1361 return nil
1362}
1363
khenaidoo92e62c52018-10-03 14:02:54 -04001364func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001365 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001366 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001367}
1368
khenaidoo0a822f92019-05-08 15:15:57 -04001369func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001370 log.Errorw("NotifyInvalidTransition", log.Fields{
1371 "device": pcDevice.Id,
1372 "adminState": pcDevice.AdminState,
1373 "operState": pcDevice.OperStatus,
1374 "connState": pcDevice.ConnectStatus,
1375 })
khenaidoo0a822f92019-05-08 15:15:57 -04001376 //TODO: notify over kafka?
1377 return nil
1378}
1379
khenaidoob9203542018-09-17 22:56:37 -04001380func funcName(f interface{}) string {
1381 p := reflect.ValueOf(f).Pointer()
1382 rf := runtime.FuncForPC(p)
1383 return rf.Name()
1384}
1385
1386func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001387 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
1388 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001389 }
1390}
1391
khenaidooc3224532019-09-05 21:04:54 -04001392func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) string {
khenaidoo19d7b632018-10-30 10:49:50 -04001393 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001394 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidooc3224532019-09-05 21:04:54 -04001395 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001396 }
khenaidooc3224532019-09-05 21:04:54 -04001397 return ""
khenaidoob9203542018-09-17 22:56:37 -04001398}
serkant.uluderya334479d2019-04-10 08:26:15 -07001399
1400func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1401 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1402 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1403 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1404 var res interface{}
1405 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1406 res = agent.simulateAlarm(ctx, simulatereq)
1407 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1408 }
1409 //TODO CLI always get successful response
1410 sendResponse(ctx, ch, res)
1411}