blob: b3c11afa06b6529f30c9b8a206b7ab5585d0edb5 [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 Baker807addd2019-10-24 15:16:21 -070022 "github.com/opencord/voltha-lib-go/v2/pkg/db/model"
23 "github.com/opencord/voltha-lib-go/v2/pkg/kafka"
24 "github.com/opencord/voltha-lib-go/v2/pkg/log"
25 "github.com/opencord/voltha-lib-go/v2/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{}) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530150 if dMgr.isParentDeviceExist(device) {
151 log.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
152 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
153 return
154 }
khenaidoo92e62c52018-10-03 14:02:54 -0400155 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400156
khenaidoo5e677ae2019-02-28 17:26:29 -0500157 // Ensure this device is set as root
158 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400159 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400160 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400161 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500162 agent.start(ctx, false)
khenaidoob9203542018-09-17 22:56:37 -0400163
khenaidoo92e62c52018-10-03 14:02:54 -0400164 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400165}
166
167func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400168 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400169 var res interface{}
170 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
171 res = agent.enableDevice(ctx)
172 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400173 }
174
175 sendResponse(ctx, ch, res)
176}
177
khenaidoo92e62c52018-10-03 14:02:54 -0400178func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
179 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400180 var res interface{}
181 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
182 res = agent.disableDevice(ctx)
183 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400184 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400185 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400186 }
khenaidoo92e62c52018-10-03 14:02:54 -0400187
188 sendResponse(ctx, ch, res)
189}
190
khenaidoo4d4802d2018-10-04 21:59:49 -0400191func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
192 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
193 var res interface{}
194 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
195 res = agent.rebootDevice(ctx)
196 log.Debugw("rebootDevice-result", log.Fields{"result": res})
197 } else {
198 res = status.Errorf(codes.NotFound, "%s", id.Id)
199 }
200 sendResponse(ctx, ch, res)
201}
202
203func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
204 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
205 var res interface{}
206 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
207 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400208 log.Debugw("deleteDevice-result", log.Fields{"result": res})
209 } else {
210 res = status.Errorf(codes.NotFound, "%s", id.Id)
211 }
212 sendResponse(ctx, ch, res)
213}
214
khenaidoo6d62c002019-05-15 21:57:03 -0400215// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
216// This function is called only in the Core that does not own this device. In the Core that owns this device then a
217// deletion deletion also includes removal of any reference of this device.
218func (dMgr *DeviceManager) stopManagingDevice(id string) {
219 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
220 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
221 if root, _ := dMgr.IsRootDevice(id); root == true {
222 // stop managing the logical device
223 ldeviceId := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceId(id)
224 if ldeviceId != "" { // Can happen if logical device agent was already stopped
225 dMgr.core.deviceOwnership.AbandonDevice(ldeviceId)
226 }
227 // stop managing the child devices
228 childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentId(id)
229 for _, cId := range childDeviceIds {
230 dMgr.stopManagingDevice(cId)
231 }
232 }
233 if agent := dMgr.getDeviceAgent(id); agent != nil {
234 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -0400235 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400236 // Abandon the device ownership
237 dMgr.core.deviceOwnership.AbandonDevice(id)
238 }
239 }
240}
241
khenaidoo0a822f92019-05-08 15:15:57 -0400242func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
243 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400244 dMgr.stopManagingDevice(cDevice.Id)
245 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400246}
247
khenaidoo297cd252019-02-07 22:10:23 -0500248// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400249func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
250 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400251 if agent := dMgr.getDeviceAgent(id); agent != nil {
252 return agent.getDevice()
253 }
254 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400255}
256
Matt Jeanneret4e241952019-02-28 11:16:04 -0500257func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
Matt Jeanneret0c5088c2019-04-22 16:16:19 -0400258 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber,
259 "parentPortNo": parentPortNo, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500260
261 var parentDevice *voltha.Device
262 var err error
263 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
264 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
265 }
266 var childDeviceIds []string
267 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
268 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
269 }
270 if len(childDeviceIds) == 0 {
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700271 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500272 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
273 }
274
275 var foundChildDevice *voltha.Device
276 for _, childDeviceId := range childDeviceIds {
277 found := false
278 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
279
280 foundOnuId := false
281 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
282 if searchDevice.ParentPortNo == uint32(parentPortNo) {
283 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
284 foundOnuId = true
285 }
286 }
287
288 foundSerialNumber := false
289 if searchDevice.SerialNumber == serialNumber {
290 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
291 foundSerialNumber = true
292 }
293
294 // if both onuId and serialNumber are provided both must be true for the device to be found
295 // otherwise whichever one found a match is good enough
296 if onuId > 0 && serialNumber != "" {
297 found = foundOnuId && foundSerialNumber
298 } else {
299 found = foundOnuId || foundSerialNumber
300 }
301
302 if found == true {
303 foundChildDevice = searchDevice
304 break
305 }
306 }
307 }
308
309 if foundChildDevice != nil {
310 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
311 return foundChildDevice, nil
312 }
313
314 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
315 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
316 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
317}
318
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500319func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
320 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
321
322 var parentDevice *voltha.Device
323 var err error
324 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
325 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
326 }
327 var childDeviceIds []string
328 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
329 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
330 }
331 if len(childDeviceIds) == 0 {
332 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
333 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
334 }
335
336 var foundChildDevice *voltha.Device
337 for _, childDeviceId := range childDeviceIds {
338 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
339 if searchDevice.ProxyAddress == proxyAddress {
340 foundChildDevice = searchDevice
341 break
342 }
343 }
344 }
345
346 if foundChildDevice != nil {
347 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
348 return foundChildDevice, nil
349 }
350
351 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
352 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
353}
354
khenaidoo297cd252019-02-07 22:10:23 -0500355func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400356 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500357 return exist
358}
359
khenaidoo19d7b632018-10-30 10:49:50 -0400360func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400361 dMgr.lockRootDeviceMap.RLock()
362 defer dMgr.lockRootDeviceMap.RUnlock()
363 if exist := dMgr.rootDevices[id]; exist {
364 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400365 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400366 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400367}
368
Stephane Barbarieaa467942019-02-06 14:09:44 -0500369// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400370func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400371 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400372 result := &voltha.Devices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400373 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500374 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500375 // If device is not in memory then set it up
376 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400377 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400378 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500379 if err := agent.start(nil, true); err != nil {
380 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
381 agent.stop(nil)
382 } else {
383 dMgr.addDeviceAgentToMap(agent)
384 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500385 }
386 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400387 }
388 }
khenaidoo6d62c002019-05-15 21:57:03 -0400389 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400390 return result, nil
391}
392
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530393//isParentDeviceExist checks whether device is already preprovisioned.
394func (dMgr *DeviceManager) isParentDeviceExist(newDevice *voltha.Device) bool {
395 hostPort := newDevice.GetHostAndPort()
396 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
397 for _, device := range devices.([]interface{}) {
398 if !device.(*voltha.Device).Root {
399 continue
400 }
401 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() {
402 return true
403 }
404 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress {
405 return true
406 }
407 }
408 }
409 return false
410}
411
khenaidoo6d62c002019-05-15 21:57:03 -0400412//getDeviceFromModelretrieves the device data from the model.
413func (dMgr *DeviceManager) getDeviceFromModel(deviceId string) (*voltha.Device, error) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400414 if device := dMgr.clusterDataProxy.Get(context.Background(), "/devices/"+deviceId, 0, false, ""); device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400415 if d, ok := device.(*voltha.Device); ok {
416 return d, nil
417 }
418 }
419 return nil, status.Error(codes.NotFound, deviceId)
420}
421
khenaidoo297cd252019-02-07 22:10:23 -0500422// loadDevice loads the deviceId in memory, if not present
423func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
khenaidoo297cd252019-02-07 22:10:23 -0500424 if deviceId == "" {
425 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
426 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400427 var err error
428 var device *voltha.Device
429 dMgr.devicesLoadingLock.Lock()
430 if _, exist := dMgr.deviceLoadingInProgress[deviceId]; !exist {
431 if !dMgr.IsDeviceInCache(deviceId) {
432 dMgr.deviceLoadingInProgress[deviceId] = []chan int{make(chan int, 1)}
433 dMgr.devicesLoadingLock.Unlock()
434 // Proceed with the loading only if the device exist in the Model (could have been deleted)
435 if device, err = dMgr.getDeviceFromModel(deviceId); err == nil {
436 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
437 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
438 if err = agent.start(nil, true); err != nil {
439 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceId, "error": err})
440 agent.stop(nil)
441 } else {
442 dMgr.addDeviceAgentToMap(agent)
443 }
444 } else {
445 log.Debugw("Device not in model", log.Fields{"deviceId": deviceId})
khenaidoo6d62c002019-05-15 21:57:03 -0400446 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400447 // announce completion of task to any number of waiting channels
448 dMgr.devicesLoadingLock.Lock()
449 if v, ok := dMgr.deviceLoadingInProgress[deviceId]; ok {
450 for _, ch := range v {
451 close(ch)
452 }
453 delete(dMgr.deviceLoadingInProgress, deviceId)
454 }
455 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400456 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400457 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500458 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400459 } else {
460 ch := make(chan int, 1)
461 dMgr.deviceLoadingInProgress[deviceId] = append(dMgr.deviceLoadingInProgress[deviceId], ch)
462 dMgr.devicesLoadingLock.Unlock()
463 // Wait for the channel to be closed, implying the process loading this device is done.
464 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500465 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400466 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
467 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500468 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400469 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceId)
khenaidoo297cd252019-02-07 22:10:23 -0500470}
471
472// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
473func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
474 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
475 if device.Root {
476 // Scenario A
477 if device.ParentId != "" {
478 // Load logical device if needed.
479 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
480 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
481 }
482 } else {
483 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
484 }
485 // Load all child devices, if needed
486 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
487 for _, childDeviceId := range childDeviceIds {
488 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400489 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500490 return err
491 }
492 }
493 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
494 } else {
495 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
496 }
497 }
498 return nil
499}
500
501// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
502// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
503// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
504// and the proceed with the request.
505func (dMgr *DeviceManager) load(deviceId string) error {
506 log.Debug("load...")
507 // First load the device - this may fail in case the device was deleted intentionally by the other core
508 var dAgent *DeviceAgent
509 var err error
510 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500511 return err
512 }
513 // Get the loaded device details
514 var device *voltha.Device
515 if device, err = dAgent.getDevice(); err != nil {
516 return err
517 }
518
519 // If the device is in Pre-provisioning or deleted state stop here
520 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
521 return nil
522 }
523
524 // Now we face two scenarios
525 if device.Root {
526 // Load all children as well as the parent of this device (logical_device)
527 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
528 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
529 return err
530 }
531 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
532 } else {
533 // Scenario B - use the parentId of that device (root device) to trigger the loading
534 if device.ParentId != "" {
535 return dMgr.load(device.ParentId)
536 }
537 }
538 return nil
539}
540
khenaidoo7ccedd52018-12-14 16:48:54 -0500541// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
542func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
543 log.Debug("ListDeviceIDs")
544 // Report only device IDs that are in the device agent map
545 return dMgr.listDeviceIdsFromMap(), nil
546}
547
khenaidoo4c9e5592019-09-09 16:20:41 -0400548//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
549//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500550func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400551 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500552 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400553 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500554 toReconcile := len(ids.Items)
555 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400556 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500557 for _, id := range ids.Items {
khenaidoo4c9e5592019-09-09 16:20:41 -0400558 if err = dMgr.load(id.Id); err != nil {
559 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
560 } else {
561 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500562 }
563 }
564 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400565 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500566 }
567 } else {
568 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
569 }
570 sendResponse(ctx, ch, res)
571}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500572
khenaidooba6b6c42019-08-02 09:11:56 -0400573// isOkToReconcile validates whether a device is in the correct status to be reconciled
574func isOkToReconcile(device *voltha.Device) bool {
575 if device == nil {
576 return false
577 }
578 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
579}
580
581// adapterRestarted is invoked whenever an adapter is restarted
582func (dMgr *DeviceManager) adapterRestarted(adapter *voltha.Adapter) error {
583 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
584
585 // Let's reconcile the device managed by this Core only
586 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
587 if len(rootDeviceIds) == 0 {
588 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
589 return nil
590 }
591
592 chnlsList := make([]chan interface{}, 0)
593 for _, rootDeviceId := range rootDeviceIds {
594 if rootDevice, _ := dMgr.getDeviceFromModel(rootDeviceId); rootDevice != nil {
595 if rootDevice.Adapter == adapter.Id {
596 if isOkToReconcile(rootDevice) {
597 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
598 chnlsList = dMgr.sendReconcileDeviceRequest(rootDevice, chnlsList)
599 } else {
600 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
601 }
602 } else { // Should we be reconciling the root's children instead?
603 childManagedByAdapter:
604 for _, port := range rootDevice.Ports {
605 for _, peer := range port.Peers {
606 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
607 if childDevice.Adapter == adapter.Id {
608 if isOkToReconcile(childDevice) {
609 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
610 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
611 } else {
612 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
613 }
614 } else {
615 // All child devices under a parent device are typically managed by the same adapter type.
616 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
617 break childManagedByAdapter
618 }
619 }
620 }
621 }
622 }
623 }
624 }
625 if len(chnlsList) > 0 {
626 // Wait for completion
627 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
628 return status.Errorf(codes.Aborted, "errors-%s", res)
629 }
630 } else {
631 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
632 }
633 return nil
634}
635
636func (dMgr *DeviceManager) sendReconcileDeviceRequest(device *voltha.Device, chnlsList []chan interface{}) []chan interface{} {
637 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
638 // point of creating a device agent (if the device is not being managed by this Core) before sending the request
639 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to teh adapter via
640 // the adapter_proxy.
641 ch := make(chan interface{})
642 chnlsList = append(chnlsList, ch)
643 go func(device *voltha.Device) {
644 if err := dMgr.adapterProxy.ReconcileDevice(context.Background(), device); err != nil {
645 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
646 ch <- status.Errorf(codes.Internal, "device: %s", device.Id)
647 }
648 ch <- nil
649 }(device)
650
651 return chnlsList
652}
653
654func (dMgr *DeviceManager) reconcileChildDevices(parentDeviceId string) error {
655 if parentDevice, _ := dMgr.getDeviceFromModel(parentDeviceId); parentDevice != nil {
656 chnlsList := make([]chan interface{}, 0)
657 for _, port := range parentDevice.Ports {
658 for _, peer := range port.Peers {
659 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
660 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
661 }
662 }
663 }
664 // Wait for completion
665 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
666 return status.Errorf(codes.Aborted, "errors-%s", res)
667 }
668 }
669 return nil
670}
671
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700672func (dMgr *DeviceManager) updateDeviceUsingAdapterData(device *voltha.Device) error {
673 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400674 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700675 return agent.updateDeviceUsingAdapterData(device)
khenaidoob9203542018-09-17 22:56:37 -0400676 }
677 return status.Errorf(codes.NotFound, "%s", device.Id)
678}
679
680func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
681 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400682 if err := agent.addPort(port); err != nil {
683 return err
684 }
685 // Setup peer ports
686 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
687 for _, peerPort := range port.Peers {
688 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
689 if err := agent.addPeerPort(meAsPeer); err != nil {
690 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
691 return err
692 }
693 }
694 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400695 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
696 // then a logical port will be added to the logical device and the device graph generated. If the port is a
697 // PON port then only the device graph will be generated.
698 if device, err := dMgr.GetDevice(deviceId); err == nil {
699 go dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
700 } else {
701 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
702 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400703 }
khenaidoo92e62c52018-10-03 14:02:54 -0400704 return nil
705 } else {
706 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400707 }
khenaidoob9203542018-09-17 22:56:37 -0400708}
709
khenaidoo0a822f92019-05-08 15:15:57 -0400710func (dMgr *DeviceManager) deletePeerPorts(fromDeviceId string, deviceId string) error {
711 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceId, "deviceid": deviceId})
712 if agent := dMgr.getDeviceAgent(fromDeviceId); agent != nil {
713 return agent.deletePeerPorts(deviceId)
714 }
715 return status.Errorf(codes.NotFound, "%s", deviceId)
716}
717
Manikkaraj kb1a10922019-07-29 12:10:34 -0400718func (dMgr *DeviceManager) addFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
719 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceId, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -0400720 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400721 return agent.addFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400722 }
723 return status.Errorf(codes.NotFound, "%s", deviceId)
724}
725
Manikkaraj kb1a10922019-07-29 12:10:34 -0400726func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400727 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceId})
728 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400729 return agent.deleteFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400730 }
731 return status.Errorf(codes.NotFound, "%s", deviceId)
732}
733
Manikkaraj kb1a10922019-07-29 12:10:34 -0400734func (dMgr *DeviceManager) updateFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400735 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceId})
736 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400737 return agent.updateFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400738 }
739 return status.Errorf(codes.NotFound, "%s", deviceId)
740}
741
khenaidoob3127472019-07-24 21:04:55 -0400742// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
743// following a user action
744func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
745 var res interface{}
746 if pmConfigs.Id == "" {
747 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
748 } else if agent := dMgr.getDeviceAgent(pmConfigs.Id); agent != nil {
749 res = agent.updatePmConfigs(ctx, pmConfigs)
750 } else {
751 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
752 }
753 sendResponse(ctx, ch, res)
754}
755
756// initPmConfigs initialize the pm configs as defined by the adapter.
757func (dMgr *DeviceManager) initPmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
758 if pmConfigs.Id == "" {
759 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
760 }
khenaidoob9203542018-09-17 22:56:37 -0400761 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400762 return agent.initPmConfigs(pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400763 }
764 return status.Errorf(codes.NotFound, "%s", deviceId)
765}
766
khenaidoob3127472019-07-24 21:04:55 -0400767func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceId string) (*voltha.PmConfigs, error) {
768 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
769 return agent.listPmConfigs(ctx)
770 }
771 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
772}
773
khenaidoo79232702018-12-04 11:00:41 -0500774func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400775 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400776 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
777 return agent.getSwitchCapability(ctx)
778 }
779 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
780}
781
khenaidoo92e62c52018-10-03 14:02:54 -0400782func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
783 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400784 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400785 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400786 }
787 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
788}
789
khenaidoo79232702018-12-04 11:00:41 -0500790func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400791 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400792 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
793 return agent.getPortCapability(ctx, portNo)
794 }
795 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
796}
797
khenaidoo92e62c52018-10-03 14:02:54 -0400798func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
799 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400800 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400801 return agent.updateDeviceStatus(operStatus, connStatus)
802 }
803 return status.Errorf(codes.NotFound, "%s", deviceId)
804}
805
khenaidoo4d4802d2018-10-04 21:59:49 -0400806func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
807 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
808 var parentDevice *voltha.Device
809 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400810 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400811 return status.Errorf(codes.Aborted, "%s", err.Error())
812 }
813 var childDeviceIds []string
814 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
815 return status.Errorf(codes.Aborted, "%s", err.Error())
816 }
817 if len(childDeviceIds) == 0 {
818 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
819 }
820 for _, childDeviceId := range childDeviceIds {
821 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
822 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
823 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
824 }
825 }
826 }
827 return nil
828}
829
khenaidoo92e62c52018-10-03 14:02:54 -0400830func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
831 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
832 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
833 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400834 }
835 return status.Errorf(codes.NotFound, "%s", deviceId)
836}
837
khenaidoo0a822f92019-05-08 15:15:57 -0400838func (dMgr *DeviceManager) deleteAllPorts(deviceId string) error {
839 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceId})
840 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
841 if err := agent.deleteAllPorts(); err != nil {
842 return err
843 }
844 // Notify the logical device manager to remove all logical ports, if needed.
845 // At this stage the device itself may gave been deleted already at a deleteAllPorts
846 // typically is part of a device deletion phase.
847 if device, err := dMgr.GetDevice(deviceId); err == nil {
848 go dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
849 } else {
850 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
851 return err
852 }
853 return nil
854 }
855 return status.Errorf(codes.NotFound, "%s", deviceId)
856}
857
khenaidoo3ab34882019-05-02 21:33:30 -0400858//updatePortsState updates all ports on the device
859func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
860 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
861
862 var adminState voltha.AdminState_AdminState
863 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
864 switch state {
865 case voltha.OperStatus_ACTIVE:
866 adminState = voltha.AdminState_ENABLED
867 if err := agent.enablePorts(); err != nil {
868 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
869 return err
870 }
871 case voltha.OperStatus_UNKNOWN:
872 adminState = voltha.AdminState_DISABLED
873 if err := agent.disablePorts(); err != nil {
874 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
875 return err
876 }
877 default:
878 return status.Error(codes.Unimplemented, "state-change-not-implemented")
879 }
880 // Notify the logical device about the state change
881 if device, err := dMgr.GetDevice(deviceId); err != nil {
882 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
883 return err
884 } else {
885 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
886 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
887 return err
888 }
889 return nil
890 }
891 }
892 return status.Errorf(codes.NotFound, "%s", deviceId)
893}
894
Matt Jeanneret4e241952019-02-28 11:16:04 -0500895func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700896 channelId int64, vendorId string, serialNumber string, onuId int64) (*voltha.Device, error) {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700897 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId, "parentPortNo": parentPortNo, "deviceType": deviceType, "channelId": channelId, "vendorId": vendorId, "serialNumber": serialNumber, "onuId": onuId})
898
899 if deviceType == "" && vendorId != "" {
900 log.Debug("device-type-is-nil-fetching-device-type")
901 if deviceTypesIf := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, ""); deviceTypesIf != nil {
902 OLoop:
903 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
904 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
905 for _, v := range dType.VendorIds {
906 if v == vendorId {
907 deviceType = dType.Adapter
908 break OLoop
909 }
910 }
911 }
912 }
913 }
914 }
915 //if no match found for the vendorid,report adapter with the custom error message
916 if deviceType == "" {
917 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorId})
918 return nil, status.Errorf(codes.NotFound, "%s", vendorId)
919 }
khenaidoob9203542018-09-17 22:56:37 -0400920
921 // Create the ONU device
922 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400923 childDevice.Type = deviceType
924 childDevice.ParentId = parentDeviceId
925 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500926 childDevice.VendorId = vendorId
927 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400928 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400929
930 //Get parent device type
931 parent, err := dMgr.GetDevice(parentDeviceId)
932 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500933 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700934 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400935 }
936
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700937 if device, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500938 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700939 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500940 }
941
942 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400943
944 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400945 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400946 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500947 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400948
khenaidoo09771ef2019-10-11 14:25:02 -0400949 // Since this Core has handled this request then it therefore owns this child device. Set the
950 // ownership of this device to this Core
951 dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: agent.deviceId})
952
khenaidoob9203542018-09-17 22:56:37 -0400953 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400954 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500955 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400956 }
957
khenaidoo79232702018-12-04 11:00:41 -0500958 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500959 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500960
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700961 return agent.lastData, nil
khenaidoob9203542018-09-17 22:56:37 -0400962}
963
964func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
965 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400966 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
967 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500968 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400969 return nil
khenaidoob9203542018-09-17 22:56:37 -0400970 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400971 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -0400972 for _, handler := range handlers {
973 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
974 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400975 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400976 return err
977 }
978 }
khenaidoob9203542018-09-17 22:56:37 -0400979 return nil
980}
981
khenaidoofdbad6e2018-11-06 22:26:38 -0500982func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
983 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
984 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
985 return agent.packetOut(outPort, packet)
986 }
987 return status.Errorf(codes.NotFound, "%s", deviceId)
988}
989
khenaidoo297cd252019-02-07 22:10:23 -0500990func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500991 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
992 // Get the logical device Id based on the deviceId
993 var device *voltha.Device
994 var err error
995 if device, err = dMgr.GetDevice(deviceId); err != nil {
996 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
997 return err
998 }
khenaidoo43c82122018-11-22 18:38:28 -0500999 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -05001000 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
1001 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
1002 }
1003
khenaidoo297cd252019-02-07 22:10:23 -05001004 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001005 return err
1006 }
1007 return nil
1008}
1009
khenaidoo0a822f92019-05-08 15:15:57 -04001010func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
1011 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001012 // Verify whether the logical device has already been created
1013 if cDevice.ParentId != "" {
1014 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1015 return nil
1016 }
khenaidoob9203542018-09-17 22:56:37 -04001017 var logicalId *string
1018 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001019 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001020 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1021 return err
1022 }
1023 // Update the parent device with the logical id
1024 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
1025 return nil
1026}
1027
khenaidoo0a822f92019-05-08 15:15:57 -04001028func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
1029 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001030 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001031 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001032 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1033 return err
1034 }
1035 // Remove the logical device Id from the parent device
1036 logicalId := ""
1037 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
1038 return nil
1039}
1040
khenaidoo0a822f92019-05-08 15:15:57 -04001041func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001042 log.Info("deleteLogicalPort")
1043 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001044 // Get the logical port associated with this device
1045 var lPortId *voltha.LogicalPortId
1046 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001047 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001048 return err
1049 }
1050 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
1051 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001052 return err
1053 }
khenaidoo92e62c52018-10-03 14:02:54 -04001054 return nil
1055}
1056
khenaidoo0a822f92019-05-08 15:15:57 -04001057func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1058 log.Info("deleteLogicalPorts")
1059 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1060 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1061 return err
1062 }
1063 return nil
1064}
1065
khenaidoo59ef7be2019-06-21 12:40:28 -04001066func (dMgr *DeviceManager) MarkChildDevicesAsUnReachable(device *voltha.Device) error {
1067 log.Info("MarkChildDevicesAsUnReachable")
1068 // Set the connection status to unreachable
1069 connStatus := voltha.ConnectStatus_UNREACHABLE
1070 // Do not set the operational status. Setting it to -1 will do the trick
1071 operStatus := voltha.OperStatus_OperStatus(-1)
1072 if err := dMgr.updateChildrenStatus(device.Id, operStatus, connStatus); err != nil {
1073 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1074 return err
1075 }
1076 return nil
1077}
1078
khenaidoo92e62c52018-10-03 14:02:54 -04001079func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1080 // Sanity check
1081 if childDevice.Root {
1082 // childDevice is the parent device
1083 return childDevice
1084 }
khenaidoo19d7b632018-10-30 10:49:50 -04001085 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001086 return parentDevice
1087}
1088
khenaidoo0a822f92019-05-08 15:15:57 -04001089//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1090//cannot manage the child devices. This will trigger the Core to disable all the child devices.
1091func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
1092 log.Debug("childDevicesLost")
1093 var err error
1094 var parentDevice *voltha.Device
1095 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1096 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1097 return err
1098 }
1099 return dMgr.DisableAllChildDevices(parentDevice)
1100}
1101
1102//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1103// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
1104func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
1105 log.Debug("childDevicesDetected")
1106 var err error
1107 var parentDevice *voltha.Device
1108 var childDeviceIds []string
1109
1110 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1111 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1112 return err
1113 }
1114
1115 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1116 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1117 }
1118 if len(childDeviceIds) == 0 {
1119 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1120 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001121 allChildEnableRequestSent := true
khenaidoo0a822f92019-05-08 15:15:57 -04001122 for _, childDeviceId := range childDeviceIds {
1123 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001124 // Run the children re-registration in its own routine
1125 go agent.enableDevice(nil)
1126 } else {
1127 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceId)
1128 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceId})
1129 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001130 }
1131 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001132 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001133 return err
1134 }
1135 return nil
1136}
1137
khenaidoo4d4802d2018-10-04 21:59:49 -04001138/*
1139All the functions below are callback functions where they are invoked with the latest and previous data. We can
1140therefore use the data as is without trying to get the latest from the model.
1141*/
1142
khenaidoo0a822f92019-05-08 15:15:57 -04001143//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1144func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1145 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001146 var childDeviceIds []string
1147 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001148 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1149 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001150 }
1151 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001152 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001153 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001154 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -04001155 for _, childDeviceId := range childDeviceIds {
1156 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1157 if err = agent.disableDevice(nil); err != nil {
1158 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001159 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001160 }
1161 }
1162 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001163 if !allChildDisable {
1164 return err
1165 }
khenaidoo92e62c52018-10-03 14:02:54 -04001166 return nil
1167}
1168
khenaidoo0a822f92019-05-08 15:15:57 -04001169//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1170func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1171 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001172 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001173 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001174 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1175 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001176 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001177 if len(childDeviceIds) == 0 {
1178 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1179 }
1180 allChildDeleted := true
1181 for _, childDeviceId := range childDeviceIds {
1182 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1183 if err = agent.deleteDevice(nil); err != nil {
1184 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
1185 allChildDeleted = false
1186 } else {
1187 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -04001188 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo4d4802d2018-10-04 21:59:49 -04001189 }
1190 }
1191 }
1192 if !allChildDeleted {
1193 return err
1194 }
1195 return nil
1196}
1197
khenaidoo6d62c002019-05-15 21:57:03 -04001198//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1199// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1200// device during a delete device operation.
1201func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentId(id string) []string {
1202 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1203 deviceIds := make([]string, 0)
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001204 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
1205 agent := value.(*DeviceAgent)
khenaidoo6d62c002019-05-15 21:57:03 -04001206 if agent.parentId == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001207 deviceIds = append(deviceIds, key.(string))
khenaidoo6d62c002019-05-15 21:57:03 -04001208 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001209 return true
1210 })
khenaidoo6d62c002019-05-15 21:57:03 -04001211 return deviceIds
1212}
1213
khenaidoo4d4802d2018-10-04 21:59:49 -04001214//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1215func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1216 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001217 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001218 if parentDevice != nil {
1219 for _, port := range parentDevice.Ports {
1220 for _, peer := range port.Peers {
1221 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1222 }
khenaidoo92e62c52018-10-03 14:02:54 -04001223 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001224 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001225 }
1226 return childDeviceIds, nil
1227}
1228
khenaidoo297cd252019-02-07 22:10:23 -05001229//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1230func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
1231 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
1232 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
1233 childDevices := make([]*voltha.Device, 0)
1234 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
1235 for _, deviceId := range childDeviceIds {
1236 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
1237 childDevices = append(childDevices, d)
1238 }
1239 }
1240 }
1241 return &voltha.Devices{Items: childDevices}, nil
1242 }
1243 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
1244}
1245
khenaidoo0a822f92019-05-08 15:15:57 -04001246func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001247 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -04001248 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001249 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1250 return err
1251 }
1252 return nil
1253}
1254
khenaidoof5a5bfa2019-01-23 22:20:29 -05001255func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1256 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1257 var res interface{}
1258 var err error
1259 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1260 if res, err = agent.downloadImage(ctx, img); err != nil {
1261 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1262 res = err
1263 }
1264 } else {
1265 res = status.Errorf(codes.NotFound, "%s", img.Id)
1266 }
1267 sendResponse(ctx, ch, res)
1268}
1269
1270func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1271 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1272 var res interface{}
1273 var err error
1274 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1275 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1276 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1277 res = err
1278 }
1279 } else {
1280 res = status.Errorf(codes.NotFound, "%s", img.Id)
1281 }
1282 sendResponse(ctx, ch, res)
1283}
1284
1285func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1286 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1287 var res interface{}
1288 var err error
1289 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1290 if res, err = agent.activateImage(ctx, img); err != nil {
1291 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1292 res = err
1293 }
1294 } else {
1295 res = status.Errorf(codes.NotFound, "%s", img.Id)
1296 }
1297 sendResponse(ctx, ch, res)
1298}
1299
1300func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1301 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1302 var res interface{}
1303 var err error
1304 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1305 if res, err = agent.revertImage(ctx, img); err != nil {
1306 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1307 res = err
1308 }
1309 } else {
1310 res = status.Errorf(codes.NotFound, "%s", img.Id)
1311 }
1312 sendResponse(ctx, ch, res)
1313}
1314
1315func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1316 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1317 var res interface{}
1318 var err error
1319 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1320 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1321 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1322 res = err
1323 }
1324 } else {
1325 res = status.Errorf(codes.NotFound, "%s", img.Id)
1326 }
1327 sendResponse(ctx, ch, res)
1328}
1329
khenaidoof5a5bfa2019-01-23 22:20:29 -05001330func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1331 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1332 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1333 if err := agent.updateImageDownload(img); err != nil {
1334 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1335 return err
1336 }
1337 } else {
1338 return status.Errorf(codes.NotFound, "%s", img.Id)
1339 }
1340 return nil
1341}
1342
1343func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1344 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1345 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1346 return agent.getImageDownload(ctx, img)
1347 }
1348 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1349}
1350
1351func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1352 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1353 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1354 return agent.listImageDownloads(ctx, deviceId)
1355 }
1356 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1357}
1358
khenaidoo0a822f92019-05-08 15:15:57 -04001359func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1360 log.Info("SetAdminStateToEnable")
1361 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1362 return agent.updateAdminState(voltha.AdminState_ENABLED)
1363 }
1364 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1365}
1366
khenaidoo92e62c52018-10-03 14:02:54 -04001367func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001368 log.Info("activateDevice")
1369 return nil
1370}
1371
khenaidoo92e62c52018-10-03 14:02:54 -04001372func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1373 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001374 return nil
1375}
1376
khenaidoo92e62c52018-10-03 14:02:54 -04001377func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001378 log.Info("abandonDevice")
1379 return nil
1380}
1381
khenaidoo92e62c52018-10-03 14:02:54 -04001382func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001383 log.Info("reEnableDevice")
1384 return nil
1385}
1386
khenaidoo92e62c52018-10-03 14:02:54 -04001387func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001388 log.Info("noOp")
1389 return nil
1390}
1391
khenaidoo92e62c52018-10-03 14:02:54 -04001392func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001393 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001394 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001395}
1396
khenaidoo0a822f92019-05-08 15:15:57 -04001397func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001398 log.Errorw("NotifyInvalidTransition", log.Fields{
1399 "device": pcDevice.Id,
1400 "adminState": pcDevice.AdminState,
1401 "operState": pcDevice.OperStatus,
1402 "connState": pcDevice.ConnectStatus,
1403 })
khenaidoo0a822f92019-05-08 15:15:57 -04001404 //TODO: notify over kafka?
1405 return nil
1406}
1407
khenaidoob9203542018-09-17 22:56:37 -04001408func funcName(f interface{}) string {
1409 p := reflect.ValueOf(f).Pointer()
1410 rf := runtime.FuncForPC(p)
1411 return rf.Name()
1412}
1413
1414func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001415 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
1416 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001417 }
1418}
1419
khenaidoo4c9e5592019-09-09 16:20:41 -04001420func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) string {
khenaidoo19d7b632018-10-30 10:49:50 -04001421 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001422 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001423 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001424 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001425 return ""
khenaidoob9203542018-09-17 22:56:37 -04001426}
serkant.uluderya334479d2019-04-10 08:26:15 -07001427
1428func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1429 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1430 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1431 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1432 var res interface{}
1433 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1434 res = agent.simulateAlarm(ctx, simulatereq)
1435 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1436 }
1437 //TODO CLI always get successful response
1438 sendResponse(ctx, ch, res)
1439}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001440
1441func (dMgr *DeviceManager) updateDeviceReason(deviceId string, reason string) error {
1442 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceId, "reason": reason})
1443 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1444 return agent.updateDeviceReason(reason)
1445 }
1446 return status.Errorf(codes.NotFound, "%s", deviceId)
1447}