blob: 56db2b1fd7768e736d9986bf1ab912ebea10496e [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"
sbarbari17d7e222019-11-05 10:02:29 -050021 "github.com/opencord/voltha-go/db/model"
khenaidoo3d3b8c22019-05-22 18:10:39 -040022 "github.com/opencord/voltha-go/rw_core/utils"
Scott Baker807addd2019-10-24 15:16:21 -070023 "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"
Scott Baker555307d2019-11-04 08:58:01 -080026 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
27 ofp "github.com/opencord/voltha-protos/v2/go/openflow_13"
28 "github.com/opencord/voltha-protos/v2/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)
Scott Baker80678602019-11-14 16:57:36 -0800162 device, err := agent.start(ctx, device)
163 if err != nil {
164 log.Errorf("Failed to start device")
165 sendResponse(ctx, ch, errors.New("Failed to start device"))
166 return
167 }
khenaidoob9203542018-09-17 22:56:37 -0400168
Scott Baker80678602019-11-14 16:57:36 -0800169 sendResponse(ctx, ch, device)
khenaidoob9203542018-09-17 22:56:37 -0400170}
171
172func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400173 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400174 var res interface{}
175 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
176 res = agent.enableDevice(ctx)
177 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400178 }
179
180 sendResponse(ctx, ch, res)
181}
182
khenaidoo92e62c52018-10-03 14:02:54 -0400183func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
184 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400185 var res interface{}
186 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
187 res = agent.disableDevice(ctx)
188 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400189 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400190 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400191 }
khenaidoo92e62c52018-10-03 14:02:54 -0400192
193 sendResponse(ctx, ch, res)
194}
195
khenaidoo4d4802d2018-10-04 21:59:49 -0400196func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
197 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
198 var res interface{}
199 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
200 res = agent.rebootDevice(ctx)
201 log.Debugw("rebootDevice-result", log.Fields{"result": res})
202 } else {
203 res = status.Errorf(codes.NotFound, "%s", id.Id)
204 }
205 sendResponse(ctx, ch, res)
206}
207
208func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
209 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
210 var res interface{}
211 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
212 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400213 log.Debugw("deleteDevice-result", log.Fields{"result": res})
214 } else {
215 res = status.Errorf(codes.NotFound, "%s", id.Id)
216 }
217 sendResponse(ctx, ch, res)
218}
219
khenaidoo6d62c002019-05-15 21:57:03 -0400220// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
221// This function is called only in the Core that does not own this device. In the Core that owns this device then a
222// deletion deletion also includes removal of any reference of this device.
223func (dMgr *DeviceManager) stopManagingDevice(id string) {
224 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
225 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
226 if root, _ := dMgr.IsRootDevice(id); root == true {
227 // stop managing the logical device
228 ldeviceId := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceId(id)
229 if ldeviceId != "" { // Can happen if logical device agent was already stopped
230 dMgr.core.deviceOwnership.AbandonDevice(ldeviceId)
231 }
232 // stop managing the child devices
233 childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentId(id)
234 for _, cId := range childDeviceIds {
235 dMgr.stopManagingDevice(cId)
236 }
237 }
238 if agent := dMgr.getDeviceAgent(id); agent != nil {
239 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -0400240 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400241 // Abandon the device ownership
242 dMgr.core.deviceOwnership.AbandonDevice(id)
243 }
244 }
245}
246
khenaidoo0a822f92019-05-08 15:15:57 -0400247func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
248 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400249 dMgr.stopManagingDevice(cDevice.Id)
250 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400251}
252
khenaidoo297cd252019-02-07 22:10:23 -0500253// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400254func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
255 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400256 if agent := dMgr.getDeviceAgent(id); agent != nil {
257 return agent.getDevice()
258 }
259 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400260}
261
Matt Jeanneret4e241952019-02-28 11:16:04 -0500262func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
Matt Jeanneret0c5088c2019-04-22 16:16:19 -0400263 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber,
264 "parentPortNo": parentPortNo, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500265
266 var parentDevice *voltha.Device
267 var err error
268 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
269 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
270 }
271 var childDeviceIds []string
272 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
273 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
274 }
275 if len(childDeviceIds) == 0 {
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700276 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500277 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
278 }
279
280 var foundChildDevice *voltha.Device
281 for _, childDeviceId := range childDeviceIds {
282 found := false
283 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
284
285 foundOnuId := false
286 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
287 if searchDevice.ParentPortNo == uint32(parentPortNo) {
288 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
289 foundOnuId = true
290 }
291 }
292
293 foundSerialNumber := false
294 if searchDevice.SerialNumber == serialNumber {
295 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
296 foundSerialNumber = true
297 }
298
299 // if both onuId and serialNumber are provided both must be true for the device to be found
300 // otherwise whichever one found a match is good enough
301 if onuId > 0 && serialNumber != "" {
302 found = foundOnuId && foundSerialNumber
303 } else {
304 found = foundOnuId || foundSerialNumber
305 }
306
307 if found == true {
308 foundChildDevice = searchDevice
309 break
310 }
311 }
312 }
313
314 if foundChildDevice != nil {
315 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
316 return foundChildDevice, nil
317 }
318
319 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
320 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
321 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
322}
323
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500324func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
325 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
326
327 var parentDevice *voltha.Device
328 var err error
329 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
330 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
331 }
332 var childDeviceIds []string
333 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
334 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
335 }
336 if len(childDeviceIds) == 0 {
337 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
338 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
339 }
340
341 var foundChildDevice *voltha.Device
342 for _, childDeviceId := range childDeviceIds {
343 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
344 if searchDevice.ProxyAddress == proxyAddress {
345 foundChildDevice = searchDevice
346 break
347 }
348 }
349 }
350
351 if foundChildDevice != nil {
352 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
353 return foundChildDevice, nil
354 }
355
356 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
357 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
358}
359
khenaidoo297cd252019-02-07 22:10:23 -0500360func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400361 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500362 return exist
363}
364
khenaidoo19d7b632018-10-30 10:49:50 -0400365func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400366 dMgr.lockRootDeviceMap.RLock()
367 defer dMgr.lockRootDeviceMap.RUnlock()
368 if exist := dMgr.rootDevices[id]; exist {
369 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400370 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400371 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400372}
373
Stephane Barbarieaa467942019-02-06 14:09:44 -0500374// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400375func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400376 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400377 result := &voltha.Devices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400378 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500379 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500380 // If device is not in memory then set it up
381 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400382 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400383 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Scott Baker80678602019-11-14 16:57:36 -0800384 if _, err := agent.start(nil, nil); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500385 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
386 agent.stop(nil)
387 } else {
388 dMgr.addDeviceAgentToMap(agent)
389 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500390 }
391 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400392 }
393 }
khenaidoo6d62c002019-05-15 21:57:03 -0400394 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400395 return result, nil
396}
397
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530398//isParentDeviceExist checks whether device is already preprovisioned.
399func (dMgr *DeviceManager) isParentDeviceExist(newDevice *voltha.Device) bool {
400 hostPort := newDevice.GetHostAndPort()
401 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
402 for _, device := range devices.([]interface{}) {
403 if !device.(*voltha.Device).Root {
404 continue
405 }
406 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() {
407 return true
408 }
409 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress {
410 return true
411 }
412 }
413 }
414 return false
415}
416
khenaidoo6d62c002019-05-15 21:57:03 -0400417//getDeviceFromModelretrieves the device data from the model.
418func (dMgr *DeviceManager) getDeviceFromModel(deviceId string) (*voltha.Device, error) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400419 if device := dMgr.clusterDataProxy.Get(context.Background(), "/devices/"+deviceId, 0, false, ""); device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400420 if d, ok := device.(*voltha.Device); ok {
421 return d, nil
422 }
423 }
424 return nil, status.Error(codes.NotFound, deviceId)
425}
426
khenaidoo297cd252019-02-07 22:10:23 -0500427// loadDevice loads the deviceId in memory, if not present
428func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
khenaidoo297cd252019-02-07 22:10:23 -0500429 if deviceId == "" {
430 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
431 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400432 var err error
433 var device *voltha.Device
434 dMgr.devicesLoadingLock.Lock()
435 if _, exist := dMgr.deviceLoadingInProgress[deviceId]; !exist {
436 if !dMgr.IsDeviceInCache(deviceId) {
437 dMgr.deviceLoadingInProgress[deviceId] = []chan int{make(chan int, 1)}
438 dMgr.devicesLoadingLock.Unlock()
439 // Proceed with the loading only if the device exist in the Model (could have been deleted)
440 if device, err = dMgr.getDeviceFromModel(deviceId); err == nil {
441 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
442 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Scott Baker80678602019-11-14 16:57:36 -0800443 if _, err = agent.start(nil, nil); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400444 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceId, "error": err})
445 agent.stop(nil)
446 } else {
447 dMgr.addDeviceAgentToMap(agent)
448 }
449 } else {
450 log.Debugw("Device not in model", log.Fields{"deviceId": deviceId})
khenaidoo6d62c002019-05-15 21:57:03 -0400451 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400452 // announce completion of task to any number of waiting channels
453 dMgr.devicesLoadingLock.Lock()
454 if v, ok := dMgr.deviceLoadingInProgress[deviceId]; ok {
455 for _, ch := range v {
456 close(ch)
457 }
458 delete(dMgr.deviceLoadingInProgress, deviceId)
459 }
460 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400461 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400462 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500463 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400464 } else {
465 ch := make(chan int, 1)
466 dMgr.deviceLoadingInProgress[deviceId] = append(dMgr.deviceLoadingInProgress[deviceId], ch)
467 dMgr.devicesLoadingLock.Unlock()
468 // Wait for the channel to be closed, implying the process loading this device is done.
469 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500470 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400471 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
472 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500473 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400474 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceId)
khenaidoo297cd252019-02-07 22:10:23 -0500475}
476
477// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
478func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
479 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
480 if device.Root {
481 // Scenario A
482 if device.ParentId != "" {
483 // Load logical device if needed.
484 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
485 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
486 }
487 } else {
488 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
489 }
490 // Load all child devices, if needed
491 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
492 for _, childDeviceId := range childDeviceIds {
493 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400494 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500495 return err
496 }
497 }
498 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
499 } else {
500 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
501 }
502 }
503 return nil
504}
505
506// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
507// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
508// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
509// and the proceed with the request.
510func (dMgr *DeviceManager) load(deviceId string) error {
511 log.Debug("load...")
512 // First load the device - this may fail in case the device was deleted intentionally by the other core
513 var dAgent *DeviceAgent
514 var err error
515 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500516 return err
517 }
518 // Get the loaded device details
519 var device *voltha.Device
520 if device, err = dAgent.getDevice(); err != nil {
521 return err
522 }
523
524 // If the device is in Pre-provisioning or deleted state stop here
525 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
526 return nil
527 }
528
529 // Now we face two scenarios
530 if device.Root {
531 // Load all children as well as the parent of this device (logical_device)
532 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
533 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
534 return err
535 }
536 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
537 } else {
538 // Scenario B - use the parentId of that device (root device) to trigger the loading
539 if device.ParentId != "" {
540 return dMgr.load(device.ParentId)
541 }
542 }
543 return nil
544}
545
khenaidoo7ccedd52018-12-14 16:48:54 -0500546// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
547func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
548 log.Debug("ListDeviceIDs")
549 // Report only device IDs that are in the device agent map
550 return dMgr.listDeviceIdsFromMap(), nil
551}
552
khenaidoo4c9e5592019-09-09 16:20:41 -0400553//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
554//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500555func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400556 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500557 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400558 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500559 toReconcile := len(ids.Items)
560 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400561 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500562 for _, id := range ids.Items {
khenaidoo4c9e5592019-09-09 16:20:41 -0400563 if err = dMgr.load(id.Id); err != nil {
564 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
565 } else {
566 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500567 }
568 }
569 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400570 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500571 }
572 } else {
573 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
574 }
575 sendResponse(ctx, ch, res)
576}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500577
khenaidooba6b6c42019-08-02 09:11:56 -0400578// isOkToReconcile validates whether a device is in the correct status to be reconciled
579func isOkToReconcile(device *voltha.Device) bool {
580 if device == nil {
581 return false
582 }
583 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
584}
585
586// adapterRestarted is invoked whenever an adapter is restarted
587func (dMgr *DeviceManager) adapterRestarted(adapter *voltha.Adapter) error {
588 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
589
590 // Let's reconcile the device managed by this Core only
591 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
592 if len(rootDeviceIds) == 0 {
593 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
594 return nil
595 }
596
597 chnlsList := make([]chan interface{}, 0)
598 for _, rootDeviceId := range rootDeviceIds {
599 if rootDevice, _ := dMgr.getDeviceFromModel(rootDeviceId); rootDevice != nil {
600 if rootDevice.Adapter == adapter.Id {
601 if isOkToReconcile(rootDevice) {
602 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
603 chnlsList = dMgr.sendReconcileDeviceRequest(rootDevice, chnlsList)
604 } else {
605 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
606 }
607 } else { // Should we be reconciling the root's children instead?
608 childManagedByAdapter:
609 for _, port := range rootDevice.Ports {
610 for _, peer := range port.Peers {
611 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
612 if childDevice.Adapter == adapter.Id {
613 if isOkToReconcile(childDevice) {
614 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
615 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
616 } else {
617 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
618 }
619 } else {
620 // All child devices under a parent device are typically managed by the same adapter type.
621 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
622 break childManagedByAdapter
623 }
624 }
625 }
626 }
627 }
628 }
629 }
630 if len(chnlsList) > 0 {
631 // Wait for completion
632 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
633 return status.Errorf(codes.Aborted, "errors-%s", res)
634 }
635 } else {
636 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
637 }
638 return nil
639}
640
641func (dMgr *DeviceManager) sendReconcileDeviceRequest(device *voltha.Device, chnlsList []chan interface{}) []chan interface{} {
642 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
643 // point of creating a device agent (if the device is not being managed by this Core) before sending the request
644 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to teh adapter via
645 // the adapter_proxy.
646 ch := make(chan interface{})
647 chnlsList = append(chnlsList, ch)
648 go func(device *voltha.Device) {
649 if err := dMgr.adapterProxy.ReconcileDevice(context.Background(), device); err != nil {
650 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
651 ch <- status.Errorf(codes.Internal, "device: %s", device.Id)
652 }
653 ch <- nil
654 }(device)
655
656 return chnlsList
657}
658
659func (dMgr *DeviceManager) reconcileChildDevices(parentDeviceId string) error {
660 if parentDevice, _ := dMgr.getDeviceFromModel(parentDeviceId); parentDevice != nil {
661 chnlsList := make([]chan interface{}, 0)
662 for _, port := range parentDevice.Ports {
663 for _, peer := range port.Peers {
664 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
665 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
666 }
667 }
668 }
669 // Wait for completion
670 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
671 return status.Errorf(codes.Aborted, "errors-%s", res)
672 }
673 }
674 return nil
675}
676
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700677func (dMgr *DeviceManager) updateDeviceUsingAdapterData(device *voltha.Device) error {
678 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400679 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700680 return agent.updateDeviceUsingAdapterData(device)
khenaidoob9203542018-09-17 22:56:37 -0400681 }
682 return status.Errorf(codes.NotFound, "%s", device.Id)
683}
684
685func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
686 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400687 if err := agent.addPort(port); err != nil {
688 return err
689 }
690 // Setup peer ports
691 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
692 for _, peerPort := range port.Peers {
693 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
694 if err := agent.addPeerPort(meAsPeer); err != nil {
695 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
696 return err
697 }
698 }
699 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400700 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
701 // then a logical port will be added to the logical device and the device graph generated. If the port is a
702 // PON port then only the device graph will be generated.
703 if device, err := dMgr.GetDevice(deviceId); err == nil {
704 go dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
705 } else {
706 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
707 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400708 }
khenaidoo92e62c52018-10-03 14:02:54 -0400709 return nil
710 } else {
711 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400712 }
khenaidoob9203542018-09-17 22:56:37 -0400713}
714
khenaidoo0a822f92019-05-08 15:15:57 -0400715func (dMgr *DeviceManager) deletePeerPorts(fromDeviceId string, deviceId string) error {
716 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceId, "deviceid": deviceId})
717 if agent := dMgr.getDeviceAgent(fromDeviceId); agent != nil {
718 return agent.deletePeerPorts(deviceId)
719 }
720 return status.Errorf(codes.NotFound, "%s", deviceId)
721}
722
Manikkaraj kb1a10922019-07-29 12:10:34 -0400723func (dMgr *DeviceManager) addFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
724 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceId, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -0400725 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400726 return agent.addFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400727 }
728 return status.Errorf(codes.NotFound, "%s", deviceId)
729}
730
Manikkaraj kb1a10922019-07-29 12:10:34 -0400731func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400732 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceId})
733 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400734 return agent.deleteFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400735 }
736 return status.Errorf(codes.NotFound, "%s", deviceId)
737}
738
Manikkaraj kb1a10922019-07-29 12:10:34 -0400739func (dMgr *DeviceManager) updateFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400740 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceId})
741 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400742 return agent.updateFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400743 }
744 return status.Errorf(codes.NotFound, "%s", deviceId)
745}
746
khenaidoob3127472019-07-24 21:04:55 -0400747// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
748// following a user action
749func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
750 var res interface{}
751 if pmConfigs.Id == "" {
752 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
753 } else if agent := dMgr.getDeviceAgent(pmConfigs.Id); agent != nil {
754 res = agent.updatePmConfigs(ctx, pmConfigs)
755 } else {
756 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
757 }
758 sendResponse(ctx, ch, res)
759}
760
761// initPmConfigs initialize the pm configs as defined by the adapter.
762func (dMgr *DeviceManager) initPmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
763 if pmConfigs.Id == "" {
764 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
765 }
khenaidoob9203542018-09-17 22:56:37 -0400766 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400767 return agent.initPmConfigs(pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400768 }
769 return status.Errorf(codes.NotFound, "%s", deviceId)
770}
771
khenaidoob3127472019-07-24 21:04:55 -0400772func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceId string) (*voltha.PmConfigs, error) {
773 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
774 return agent.listPmConfigs(ctx)
775 }
776 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
777}
778
khenaidoo79232702018-12-04 11:00:41 -0500779func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400780 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400781 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
782 return agent.getSwitchCapability(ctx)
783 }
784 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
785}
786
khenaidoo92e62c52018-10-03 14:02:54 -0400787func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
788 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400789 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400790 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400791 }
792 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
793}
794
khenaidoo79232702018-12-04 11:00:41 -0500795func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400796 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400797 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
798 return agent.getPortCapability(ctx, portNo)
799 }
800 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
801}
802
khenaidoo92e62c52018-10-03 14:02:54 -0400803func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
804 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400805 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400806 return agent.updateDeviceStatus(operStatus, connStatus)
807 }
808 return status.Errorf(codes.NotFound, "%s", deviceId)
809}
810
khenaidoo4d4802d2018-10-04 21:59:49 -0400811func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
812 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
813 var parentDevice *voltha.Device
814 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400815 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400816 return status.Errorf(codes.Aborted, "%s", err.Error())
817 }
818 var childDeviceIds []string
819 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
820 return status.Errorf(codes.Aborted, "%s", err.Error())
821 }
822 if len(childDeviceIds) == 0 {
823 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
824 }
825 for _, childDeviceId := range childDeviceIds {
826 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
827 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
828 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
829 }
830 }
831 }
832 return nil
833}
834
khenaidoo92e62c52018-10-03 14:02:54 -0400835func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
836 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
837 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo171b98e2019-10-31 11:48:15 -0400838 if err := agent.updatePortState(portType, portNo, operStatus); err != nil {
839 log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceId, "portNo": portNo, "error": err})
840 return err
841 }
842 // Notify the logical device manager to change the port state
843 go dMgr.logicalDeviceMgr.updatePortState(deviceId, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400844 }
845 return status.Errorf(codes.NotFound, "%s", deviceId)
846}
847
khenaidoo0a822f92019-05-08 15:15:57 -0400848func (dMgr *DeviceManager) deleteAllPorts(deviceId string) error {
849 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceId})
850 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
851 if err := agent.deleteAllPorts(); err != nil {
852 return err
853 }
854 // Notify the logical device manager to remove all logical ports, if needed.
855 // At this stage the device itself may gave been deleted already at a deleteAllPorts
856 // typically is part of a device deletion phase.
857 if device, err := dMgr.GetDevice(deviceId); err == nil {
858 go dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
859 } else {
860 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
861 return err
862 }
863 return nil
864 }
865 return status.Errorf(codes.NotFound, "%s", deviceId)
866}
867
khenaidoo3ab34882019-05-02 21:33:30 -0400868//updatePortsState updates all ports on the device
869func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
870 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
871
872 var adminState voltha.AdminState_AdminState
873 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
874 switch state {
875 case voltha.OperStatus_ACTIVE:
876 adminState = voltha.AdminState_ENABLED
877 if err := agent.enablePorts(); err != nil {
878 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
879 return err
880 }
881 case voltha.OperStatus_UNKNOWN:
882 adminState = voltha.AdminState_DISABLED
883 if err := agent.disablePorts(); err != nil {
884 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
885 return err
886 }
887 default:
888 return status.Error(codes.Unimplemented, "state-change-not-implemented")
889 }
890 // Notify the logical device about the state change
891 if device, err := dMgr.GetDevice(deviceId); err != nil {
892 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
893 return err
894 } else {
895 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
896 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
897 return err
898 }
899 return nil
900 }
901 }
902 return status.Errorf(codes.NotFound, "%s", deviceId)
903}
904
Matt Jeanneret4e241952019-02-28 11:16:04 -0500905func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700906 channelId int64, vendorId string, serialNumber string, onuId int64) (*voltha.Device, error) {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700907 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId, "parentPortNo": parentPortNo, "deviceType": deviceType, "channelId": channelId, "vendorId": vendorId, "serialNumber": serialNumber, "onuId": onuId})
908
909 if deviceType == "" && vendorId != "" {
910 log.Debug("device-type-is-nil-fetching-device-type")
911 if deviceTypesIf := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, ""); deviceTypesIf != nil {
912 OLoop:
913 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
914 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
915 for _, v := range dType.VendorIds {
916 if v == vendorId {
917 deviceType = dType.Adapter
918 break OLoop
919 }
920 }
921 }
922 }
923 }
924 }
925 //if no match found for the vendorid,report adapter with the custom error message
926 if deviceType == "" {
927 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorId})
928 return nil, status.Errorf(codes.NotFound, "%s", vendorId)
929 }
khenaidoob9203542018-09-17 22:56:37 -0400930
931 // Create the ONU device
932 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400933 childDevice.Type = deviceType
934 childDevice.ParentId = parentDeviceId
935 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500936 childDevice.VendorId = vendorId
937 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400938 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400939
940 //Get parent device type
941 parent, err := dMgr.GetDevice(parentDeviceId)
942 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500943 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700944 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400945 }
946
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700947 if device, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500948 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700949 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500950 }
951
952 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400953
954 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400955 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400956 dMgr.addDeviceAgentToMap(agent)
Scott Baker80678602019-11-14 16:57:36 -0800957 childDevice, err = agent.start(nil, childDevice)
958 if err != nil {
959 log.Error("error-starting-child")
960 return nil, err
961 }
khenaidoob9203542018-09-17 22:56:37 -0400962
khenaidoo09771ef2019-10-11 14:25:02 -0400963 // Since this Core has handled this request then it therefore owns this child device. Set the
964 // ownership of this device to this Core
965 dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: agent.deviceId})
966
khenaidoob9203542018-09-17 22:56:37 -0400967 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400968 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500969 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400970 }
971
khenaidoo79232702018-12-04 11:00:41 -0500972 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500973 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500974
Scott Baker80678602019-11-14 16:57:36 -0800975 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -0400976}
977
978func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
979 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400980 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
981 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500982 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400983 return nil
khenaidoob9203542018-09-17 22:56:37 -0400984 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400985 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -0400986 for _, handler := range handlers {
987 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
988 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400989 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400990 return err
991 }
992 }
khenaidoob9203542018-09-17 22:56:37 -0400993 return nil
994}
995
khenaidoofdbad6e2018-11-06 22:26:38 -0500996func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
997 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
998 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
999 return agent.packetOut(outPort, packet)
1000 }
1001 return status.Errorf(codes.NotFound, "%s", deviceId)
1002}
1003
khenaidoo297cd252019-02-07 22:10:23 -05001004func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -05001005 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
1006 // Get the logical device Id based on the deviceId
1007 var device *voltha.Device
1008 var err error
1009 if device, err = dMgr.GetDevice(deviceId); err != nil {
1010 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
1011 return err
1012 }
khenaidoo43c82122018-11-22 18:38:28 -05001013 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -05001014 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
1015 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
1016 }
1017
khenaidoo297cd252019-02-07 22:10:23 -05001018 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001019 return err
1020 }
1021 return nil
1022}
1023
khenaidooad06fd72019-10-28 12:26:05 -04001024func (dMgr *DeviceManager) setParentId(device *voltha.Device, parentId string) error {
1025 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentId})
1026 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
1027 return agent.setParentId(device, parentId)
1028 }
1029 return status.Errorf(codes.NotFound, "%s", device.Id)
1030}
1031
khenaidoo0a822f92019-05-08 15:15:57 -04001032func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
1033 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001034 // Verify whether the logical device has already been created
1035 if cDevice.ParentId != "" {
1036 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1037 return nil
1038 }
khenaidoob9203542018-09-17 22:56:37 -04001039 var err error
khenaidooad06fd72019-10-28 12:26:05 -04001040 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001041 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1042 return err
1043 }
khenaidoob9203542018-09-17 22:56:37 -04001044 return nil
1045}
1046
khenaidoo0a822f92019-05-08 15:15:57 -04001047func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
1048 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001049 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001050 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001051 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1052 return err
1053 }
1054 // Remove the logical device Id from the parent device
1055 logicalId := ""
1056 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
1057 return nil
1058}
1059
khenaidoo0a822f92019-05-08 15:15:57 -04001060func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001061 log.Info("deleteLogicalPort")
1062 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001063 // Get the logical port associated with this device
1064 var lPortId *voltha.LogicalPortId
1065 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001066 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001067 return err
1068 }
1069 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
1070 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001071 return err
1072 }
khenaidoo92e62c52018-10-03 14:02:54 -04001073 return nil
1074}
1075
khenaidoo0a822f92019-05-08 15:15:57 -04001076func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1077 log.Info("deleteLogicalPorts")
1078 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1079 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1080 return err
1081 }
1082 return nil
1083}
1084
khenaidoo92e62c52018-10-03 14:02:54 -04001085func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1086 // Sanity check
1087 if childDevice.Root {
1088 // childDevice is the parent device
1089 return childDevice
1090 }
khenaidoo19d7b632018-10-30 10:49:50 -04001091 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001092 return parentDevice
1093}
1094
khenaidoo0a822f92019-05-08 15:15:57 -04001095//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1096//cannot manage the child devices. This will trigger the Core to disable all the child devices.
1097func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
1098 log.Debug("childDevicesLost")
1099 var err error
1100 var parentDevice *voltha.Device
1101 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1102 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1103 return err
1104 }
1105 return dMgr.DisableAllChildDevices(parentDevice)
1106}
1107
1108//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1109// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
1110func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
1111 log.Debug("childDevicesDetected")
1112 var err error
1113 var parentDevice *voltha.Device
1114 var childDeviceIds []string
1115
1116 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1117 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1118 return err
1119 }
1120
1121 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1122 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1123 }
1124 if len(childDeviceIds) == 0 {
1125 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1126 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001127 allChildEnableRequestSent := true
khenaidoo0a822f92019-05-08 15:15:57 -04001128 for _, childDeviceId := range childDeviceIds {
1129 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001130 // Run the children re-registration in its own routine
1131 go agent.enableDevice(nil)
1132 } else {
1133 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceId)
1134 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceId})
1135 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001136 }
1137 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001138 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001139 return err
1140 }
1141 return nil
1142}
1143
khenaidoo4d4802d2018-10-04 21:59:49 -04001144/*
1145All the functions below are callback functions where they are invoked with the latest and previous data. We can
1146therefore use the data as is without trying to get the latest from the model.
1147*/
1148
khenaidoo0a822f92019-05-08 15:15:57 -04001149//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1150func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1151 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001152 var childDeviceIds []string
1153 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001154 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1155 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001156 }
1157 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001158 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001159 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001160 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -04001161 for _, childDeviceId := range childDeviceIds {
1162 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1163 if err = agent.disableDevice(nil); err != nil {
1164 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001165 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001166 }
1167 }
1168 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001169 if !allChildDisable {
1170 return err
1171 }
khenaidoo92e62c52018-10-03 14:02:54 -04001172 return nil
1173}
1174
khenaidoo0a822f92019-05-08 15:15:57 -04001175//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1176func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1177 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001178 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001179 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001180 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1181 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001182 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001183 if len(childDeviceIds) == 0 {
1184 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1185 }
1186 allChildDeleted := true
1187 for _, childDeviceId := range childDeviceIds {
1188 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1189 if err = agent.deleteDevice(nil); err != nil {
1190 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
1191 allChildDeleted = false
1192 } else {
1193 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -04001194 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo4d4802d2018-10-04 21:59:49 -04001195 }
1196 }
1197 }
1198 if !allChildDeleted {
1199 return err
1200 }
1201 return nil
1202}
1203
khenaidoo6d62c002019-05-15 21:57:03 -04001204//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1205// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1206// device during a delete device operation.
1207func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentId(id string) []string {
1208 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1209 deviceIds := make([]string, 0)
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001210 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
1211 agent := value.(*DeviceAgent)
khenaidoo6d62c002019-05-15 21:57:03 -04001212 if agent.parentId == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001213 deviceIds = append(deviceIds, key.(string))
khenaidoo6d62c002019-05-15 21:57:03 -04001214 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001215 return true
1216 })
khenaidoo6d62c002019-05-15 21:57:03 -04001217 return deviceIds
1218}
1219
khenaidoo4d4802d2018-10-04 21:59:49 -04001220//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1221func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1222 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001223 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001224 if parentDevice != nil {
1225 for _, port := range parentDevice.Ports {
1226 for _, peer := range port.Peers {
1227 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1228 }
khenaidoo92e62c52018-10-03 14:02:54 -04001229 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001230 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001231 }
1232 return childDeviceIds, nil
1233}
1234
khenaidoo297cd252019-02-07 22:10:23 -05001235//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1236func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
1237 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
1238 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
1239 childDevices := make([]*voltha.Device, 0)
1240 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
1241 for _, deviceId := range childDeviceIds {
1242 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
1243 childDevices = append(childDevices, d)
1244 }
1245 }
1246 }
1247 return &voltha.Devices{Items: childDevices}, nil
1248 }
1249 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
1250}
1251
khenaidoo0a822f92019-05-08 15:15:57 -04001252func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001253 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -04001254 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001255 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1256 return err
1257 }
1258 return nil
1259}
1260
khenaidoof5a5bfa2019-01-23 22:20:29 -05001261func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1262 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1263 var res interface{}
1264 var err error
1265 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1266 if res, err = agent.downloadImage(ctx, img); err != nil {
1267 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1268 res = err
1269 }
1270 } else {
1271 res = status.Errorf(codes.NotFound, "%s", img.Id)
1272 }
1273 sendResponse(ctx, ch, res)
1274}
1275
1276func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1277 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1278 var res interface{}
1279 var err error
1280 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1281 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1282 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1283 res = err
1284 }
1285 } else {
1286 res = status.Errorf(codes.NotFound, "%s", img.Id)
1287 }
1288 sendResponse(ctx, ch, res)
1289}
1290
1291func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1292 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1293 var res interface{}
1294 var err error
1295 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1296 if res, err = agent.activateImage(ctx, img); err != nil {
1297 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1298 res = err
1299 }
1300 } else {
1301 res = status.Errorf(codes.NotFound, "%s", img.Id)
1302 }
1303 sendResponse(ctx, ch, res)
1304}
1305
1306func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1307 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1308 var res interface{}
1309 var err error
1310 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1311 if res, err = agent.revertImage(ctx, img); err != nil {
1312 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1313 res = err
1314 }
1315 } else {
1316 res = status.Errorf(codes.NotFound, "%s", img.Id)
1317 }
1318 sendResponse(ctx, ch, res)
1319}
1320
1321func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1322 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1323 var res interface{}
1324 var err error
1325 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1326 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1327 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1328 res = err
1329 }
1330 } else {
1331 res = status.Errorf(codes.NotFound, "%s", img.Id)
1332 }
1333 sendResponse(ctx, ch, res)
1334}
1335
khenaidoof5a5bfa2019-01-23 22:20:29 -05001336func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1337 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1338 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1339 if err := agent.updateImageDownload(img); err != nil {
1340 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1341 return err
1342 }
1343 } else {
1344 return status.Errorf(codes.NotFound, "%s", img.Id)
1345 }
1346 return nil
1347}
1348
1349func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1350 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1351 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1352 return agent.getImageDownload(ctx, img)
1353 }
1354 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1355}
1356
1357func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1358 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1359 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1360 return agent.listImageDownloads(ctx, deviceId)
1361 }
1362 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1363}
1364
khenaidoo0a822f92019-05-08 15:15:57 -04001365func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1366 log.Info("SetAdminStateToEnable")
1367 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1368 return agent.updateAdminState(voltha.AdminState_ENABLED)
1369 }
1370 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1371}
1372
khenaidoo92e62c52018-10-03 14:02:54 -04001373func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001374 log.Info("activateDevice")
1375 return nil
1376}
1377
khenaidoo92e62c52018-10-03 14:02:54 -04001378func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1379 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001380 return nil
1381}
1382
khenaidoo92e62c52018-10-03 14:02:54 -04001383func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001384 log.Info("abandonDevice")
1385 return nil
1386}
1387
khenaidoo92e62c52018-10-03 14:02:54 -04001388func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001389 log.Info("reEnableDevice")
1390 return nil
1391}
1392
khenaidoo92e62c52018-10-03 14:02:54 -04001393func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001394 log.Info("noOp")
1395 return nil
1396}
1397
khenaidoo92e62c52018-10-03 14:02:54 -04001398func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001399 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001400 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001401}
1402
khenaidoo0a822f92019-05-08 15:15:57 -04001403func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001404 log.Errorw("NotifyInvalidTransition", log.Fields{
1405 "device": pcDevice.Id,
1406 "adminState": pcDevice.AdminState,
1407 "operState": pcDevice.OperStatus,
1408 "connState": pcDevice.ConnectStatus,
1409 })
khenaidoo0a822f92019-05-08 15:15:57 -04001410 //TODO: notify over kafka?
1411 return nil
1412}
1413
khenaidoob9203542018-09-17 22:56:37 -04001414func funcName(f interface{}) string {
1415 p := reflect.ValueOf(f).Pointer()
1416 rf := runtime.FuncForPC(p)
1417 return rf.Name()
1418}
1419
1420func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001421 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
1422 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001423 }
1424}
1425
khenaidoo4c9e5592019-09-09 16:20:41 -04001426func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) string {
khenaidoo19d7b632018-10-30 10:49:50 -04001427 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001428 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001429 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001430 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001431 return ""
khenaidoob9203542018-09-17 22:56:37 -04001432}
serkant.uluderya334479d2019-04-10 08:26:15 -07001433
1434func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1435 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1436 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1437 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1438 var res interface{}
1439 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1440 res = agent.simulateAlarm(ctx, simulatereq)
1441 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1442 }
1443 //TODO CLI always get successful response
1444 sendResponse(ctx, ch, res)
1445}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001446
1447func (dMgr *DeviceManager) updateDeviceReason(deviceId string, reason string) error {
1448 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceId, "reason": reason})
1449 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1450 return agent.updateDeviceReason(reason)
1451 }
1452 return status.Errorf(codes.NotFound, "%s", deviceId)
1453}