blob: 2a03dd446b3a60910936a55fe5f59e7d75c4d361 [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)
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 {
khenaidoo171b98e2019-10-31 11:48:15 -0400833 if err := agent.updatePortState(portType, portNo, operStatus); err != nil {
834 log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceId, "portNo": portNo, "error": err})
835 return err
836 }
837 // Notify the logical device manager to change the port state
838 go dMgr.logicalDeviceMgr.updatePortState(deviceId, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400839 }
840 return status.Errorf(codes.NotFound, "%s", deviceId)
841}
842
khenaidoo0a822f92019-05-08 15:15:57 -0400843func (dMgr *DeviceManager) deleteAllPorts(deviceId string) error {
844 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceId})
845 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
846 if err := agent.deleteAllPorts(); err != nil {
847 return err
848 }
849 // Notify the logical device manager to remove all logical ports, if needed.
850 // At this stage the device itself may gave been deleted already at a deleteAllPorts
851 // typically is part of a device deletion phase.
852 if device, err := dMgr.GetDevice(deviceId); err == nil {
853 go dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
854 } else {
855 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
856 return err
857 }
858 return nil
859 }
860 return status.Errorf(codes.NotFound, "%s", deviceId)
861}
862
khenaidoo3ab34882019-05-02 21:33:30 -0400863//updatePortsState updates all ports on the device
864func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
865 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
866
867 var adminState voltha.AdminState_AdminState
868 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
869 switch state {
870 case voltha.OperStatus_ACTIVE:
871 adminState = voltha.AdminState_ENABLED
872 if err := agent.enablePorts(); err != nil {
873 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
874 return err
875 }
876 case voltha.OperStatus_UNKNOWN:
877 adminState = voltha.AdminState_DISABLED
878 if err := agent.disablePorts(); err != nil {
879 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
880 return err
881 }
882 default:
883 return status.Error(codes.Unimplemented, "state-change-not-implemented")
884 }
885 // Notify the logical device about the state change
886 if device, err := dMgr.GetDevice(deviceId); err != nil {
887 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
888 return err
889 } else {
890 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
891 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
892 return err
893 }
894 return nil
895 }
896 }
897 return status.Errorf(codes.NotFound, "%s", deviceId)
898}
899
Matt Jeanneret4e241952019-02-28 11:16:04 -0500900func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700901 channelId int64, vendorId string, serialNumber string, onuId int64) (*voltha.Device, error) {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700902 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId, "parentPortNo": parentPortNo, "deviceType": deviceType, "channelId": channelId, "vendorId": vendorId, "serialNumber": serialNumber, "onuId": onuId})
903
904 if deviceType == "" && vendorId != "" {
905 log.Debug("device-type-is-nil-fetching-device-type")
906 if deviceTypesIf := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, ""); deviceTypesIf != nil {
907 OLoop:
908 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
909 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
910 for _, v := range dType.VendorIds {
911 if v == vendorId {
912 deviceType = dType.Adapter
913 break OLoop
914 }
915 }
916 }
917 }
918 }
919 }
920 //if no match found for the vendorid,report adapter with the custom error message
921 if deviceType == "" {
922 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorId})
923 return nil, status.Errorf(codes.NotFound, "%s", vendorId)
924 }
khenaidoob9203542018-09-17 22:56:37 -0400925
926 // Create the ONU device
927 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400928 childDevice.Type = deviceType
929 childDevice.ParentId = parentDeviceId
930 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500931 childDevice.VendorId = vendorId
932 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400933 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400934
935 //Get parent device type
936 parent, err := dMgr.GetDevice(parentDeviceId)
937 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500938 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700939 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400940 }
941
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700942 if device, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500943 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700944 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500945 }
946
947 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400948
949 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400950 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400951 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500952 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400953
khenaidoo09771ef2019-10-11 14:25:02 -0400954 // Since this Core has handled this request then it therefore owns this child device. Set the
955 // ownership of this device to this Core
956 dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: agent.deviceId})
957
khenaidoob9203542018-09-17 22:56:37 -0400958 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400959 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500960 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400961 }
962
khenaidoo79232702018-12-04 11:00:41 -0500963 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500964 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500965
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700966 return agent.lastData, nil
khenaidoob9203542018-09-17 22:56:37 -0400967}
968
969func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
970 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400971 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
972 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500973 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400974 return nil
khenaidoob9203542018-09-17 22:56:37 -0400975 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400976 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -0400977 for _, handler := range handlers {
978 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
979 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400980 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400981 return err
982 }
983 }
khenaidoob9203542018-09-17 22:56:37 -0400984 return nil
985}
986
khenaidoofdbad6e2018-11-06 22:26:38 -0500987func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
988 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
989 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
990 return agent.packetOut(outPort, packet)
991 }
992 return status.Errorf(codes.NotFound, "%s", deviceId)
993}
994
khenaidoo297cd252019-02-07 22:10:23 -0500995func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500996 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
997 // Get the logical device Id based on the deviceId
998 var device *voltha.Device
999 var err error
1000 if device, err = dMgr.GetDevice(deviceId); err != nil {
1001 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
1002 return err
1003 }
khenaidoo43c82122018-11-22 18:38:28 -05001004 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -05001005 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
1006 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
1007 }
1008
khenaidoo297cd252019-02-07 22:10:23 -05001009 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001010 return err
1011 }
1012 return nil
1013}
1014
khenaidooad06fd72019-10-28 12:26:05 -04001015func (dMgr *DeviceManager) setParentId(device *voltha.Device, parentId string) error {
1016 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentId})
1017 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
1018 return agent.setParentId(device, parentId)
1019 }
1020 return status.Errorf(codes.NotFound, "%s", device.Id)
1021}
1022
khenaidoo0a822f92019-05-08 15:15:57 -04001023func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
1024 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001025 // Verify whether the logical device has already been created
1026 if cDevice.ParentId != "" {
1027 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1028 return nil
1029 }
khenaidoob9203542018-09-17 22:56:37 -04001030 var err error
khenaidooad06fd72019-10-28 12:26:05 -04001031 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001032 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1033 return err
1034 }
khenaidoob9203542018-09-17 22:56:37 -04001035 return nil
1036}
1037
khenaidoo0a822f92019-05-08 15:15:57 -04001038func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
1039 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001040 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001041 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001042 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1043 return err
1044 }
1045 // Remove the logical device Id from the parent device
1046 logicalId := ""
1047 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
1048 return nil
1049}
1050
khenaidoo0a822f92019-05-08 15:15:57 -04001051func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001052 log.Info("deleteLogicalPort")
1053 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001054 // Get the logical port associated with this device
1055 var lPortId *voltha.LogicalPortId
1056 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001057 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001058 return err
1059 }
1060 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
1061 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001062 return err
1063 }
khenaidoo92e62c52018-10-03 14:02:54 -04001064 return nil
1065}
1066
khenaidoo0a822f92019-05-08 15:15:57 -04001067func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1068 log.Info("deleteLogicalPorts")
1069 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1070 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1071 return err
1072 }
1073 return nil
1074}
1075
khenaidoo92e62c52018-10-03 14:02:54 -04001076func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1077 // Sanity check
1078 if childDevice.Root {
1079 // childDevice is the parent device
1080 return childDevice
1081 }
khenaidoo19d7b632018-10-30 10:49:50 -04001082 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001083 return parentDevice
1084}
1085
khenaidoo0a822f92019-05-08 15:15:57 -04001086//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1087//cannot manage the child devices. This will trigger the Core to disable all the child devices.
1088func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
1089 log.Debug("childDevicesLost")
1090 var err error
1091 var parentDevice *voltha.Device
1092 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1093 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1094 return err
1095 }
1096 return dMgr.DisableAllChildDevices(parentDevice)
1097}
1098
1099//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1100// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
1101func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
1102 log.Debug("childDevicesDetected")
1103 var err error
1104 var parentDevice *voltha.Device
1105 var childDeviceIds []string
1106
1107 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1108 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1109 return err
1110 }
1111
1112 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1113 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1114 }
1115 if len(childDeviceIds) == 0 {
1116 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1117 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001118 allChildEnableRequestSent := true
khenaidoo0a822f92019-05-08 15:15:57 -04001119 for _, childDeviceId := range childDeviceIds {
1120 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001121 // Run the children re-registration in its own routine
1122 go agent.enableDevice(nil)
1123 } else {
1124 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceId)
1125 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceId})
1126 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001127 }
1128 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001129 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001130 return err
1131 }
1132 return nil
1133}
1134
khenaidoo4d4802d2018-10-04 21:59:49 -04001135/*
1136All the functions below are callback functions where they are invoked with the latest and previous data. We can
1137therefore use the data as is without trying to get the latest from the model.
1138*/
1139
khenaidoo0a822f92019-05-08 15:15:57 -04001140//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1141func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1142 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001143 var childDeviceIds []string
1144 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001145 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1146 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001147 }
1148 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001149 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001150 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001151 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -04001152 for _, childDeviceId := range childDeviceIds {
1153 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1154 if err = agent.disableDevice(nil); err != nil {
1155 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001156 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001157 }
1158 }
1159 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001160 if !allChildDisable {
1161 return err
1162 }
khenaidoo92e62c52018-10-03 14:02:54 -04001163 return nil
1164}
1165
khenaidoo0a822f92019-05-08 15:15:57 -04001166//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1167func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1168 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001169 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001170 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001171 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1172 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001173 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001174 if len(childDeviceIds) == 0 {
1175 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1176 }
1177 allChildDeleted := true
1178 for _, childDeviceId := range childDeviceIds {
1179 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1180 if err = agent.deleteDevice(nil); err != nil {
1181 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
1182 allChildDeleted = false
1183 } else {
1184 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -04001185 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo4d4802d2018-10-04 21:59:49 -04001186 }
1187 }
1188 }
1189 if !allChildDeleted {
1190 return err
1191 }
1192 return nil
1193}
1194
khenaidoo6d62c002019-05-15 21:57:03 -04001195//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1196// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1197// device during a delete device operation.
1198func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentId(id string) []string {
1199 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1200 deviceIds := make([]string, 0)
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001201 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
1202 agent := value.(*DeviceAgent)
khenaidoo6d62c002019-05-15 21:57:03 -04001203 if agent.parentId == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001204 deviceIds = append(deviceIds, key.(string))
khenaidoo6d62c002019-05-15 21:57:03 -04001205 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001206 return true
1207 })
khenaidoo6d62c002019-05-15 21:57:03 -04001208 return deviceIds
1209}
1210
khenaidoo4d4802d2018-10-04 21:59:49 -04001211//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1212func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1213 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001214 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001215 if parentDevice != nil {
1216 for _, port := range parentDevice.Ports {
1217 for _, peer := range port.Peers {
1218 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1219 }
khenaidoo92e62c52018-10-03 14:02:54 -04001220 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001221 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001222 }
1223 return childDeviceIds, nil
1224}
1225
khenaidoo297cd252019-02-07 22:10:23 -05001226//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1227func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
1228 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
1229 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
1230 childDevices := make([]*voltha.Device, 0)
1231 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
1232 for _, deviceId := range childDeviceIds {
1233 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
1234 childDevices = append(childDevices, d)
1235 }
1236 }
1237 }
1238 return &voltha.Devices{Items: childDevices}, nil
1239 }
1240 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
1241}
1242
khenaidoo0a822f92019-05-08 15:15:57 -04001243func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001244 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -04001245 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001246 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1247 return err
1248 }
1249 return nil
1250}
1251
khenaidoof5a5bfa2019-01-23 22:20:29 -05001252func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1253 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1254 var res interface{}
1255 var err error
1256 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1257 if res, err = agent.downloadImage(ctx, img); err != nil {
1258 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1259 res = err
1260 }
1261 } else {
1262 res = status.Errorf(codes.NotFound, "%s", img.Id)
1263 }
1264 sendResponse(ctx, ch, res)
1265}
1266
1267func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1268 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1269 var res interface{}
1270 var err error
1271 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1272 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1273 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1274 res = err
1275 }
1276 } else {
1277 res = status.Errorf(codes.NotFound, "%s", img.Id)
1278 }
1279 sendResponse(ctx, ch, res)
1280}
1281
1282func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1283 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1284 var res interface{}
1285 var err error
1286 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1287 if res, err = agent.activateImage(ctx, img); err != nil {
1288 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1289 res = err
1290 }
1291 } else {
1292 res = status.Errorf(codes.NotFound, "%s", img.Id)
1293 }
1294 sendResponse(ctx, ch, res)
1295}
1296
1297func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1298 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1299 var res interface{}
1300 var err error
1301 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1302 if res, err = agent.revertImage(ctx, img); err != nil {
1303 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1304 res = err
1305 }
1306 } else {
1307 res = status.Errorf(codes.NotFound, "%s", img.Id)
1308 }
1309 sendResponse(ctx, ch, res)
1310}
1311
1312func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1313 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1314 var res interface{}
1315 var err error
1316 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1317 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1318 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1319 res = err
1320 }
1321 } else {
1322 res = status.Errorf(codes.NotFound, "%s", img.Id)
1323 }
1324 sendResponse(ctx, ch, res)
1325}
1326
khenaidoof5a5bfa2019-01-23 22:20:29 -05001327func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1328 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1329 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1330 if err := agent.updateImageDownload(img); err != nil {
1331 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1332 return err
1333 }
1334 } else {
1335 return status.Errorf(codes.NotFound, "%s", img.Id)
1336 }
1337 return nil
1338}
1339
1340func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1341 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1342 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1343 return agent.getImageDownload(ctx, img)
1344 }
1345 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1346}
1347
1348func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1349 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1350 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1351 return agent.listImageDownloads(ctx, deviceId)
1352 }
1353 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1354}
1355
khenaidoo0a822f92019-05-08 15:15:57 -04001356func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1357 log.Info("SetAdminStateToEnable")
1358 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1359 return agent.updateAdminState(voltha.AdminState_ENABLED)
1360 }
1361 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1362}
1363
khenaidoo92e62c52018-10-03 14:02:54 -04001364func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001365 log.Info("activateDevice")
1366 return nil
1367}
1368
khenaidoo92e62c52018-10-03 14:02:54 -04001369func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1370 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001371 return nil
1372}
1373
khenaidoo92e62c52018-10-03 14:02:54 -04001374func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001375 log.Info("abandonDevice")
1376 return nil
1377}
1378
khenaidoo92e62c52018-10-03 14:02:54 -04001379func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001380 log.Info("reEnableDevice")
1381 return nil
1382}
1383
khenaidoo92e62c52018-10-03 14:02:54 -04001384func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001385 log.Info("noOp")
1386 return nil
1387}
1388
khenaidoo92e62c52018-10-03 14:02:54 -04001389func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001390 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001391 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001392}
1393
khenaidoo0a822f92019-05-08 15:15:57 -04001394func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001395 log.Errorw("NotifyInvalidTransition", log.Fields{
1396 "device": pcDevice.Id,
1397 "adminState": pcDevice.AdminState,
1398 "operState": pcDevice.OperStatus,
1399 "connState": pcDevice.ConnectStatus,
1400 })
khenaidoo0a822f92019-05-08 15:15:57 -04001401 //TODO: notify over kafka?
1402 return nil
1403}
1404
khenaidoob9203542018-09-17 22:56:37 -04001405func funcName(f interface{}) string {
1406 p := reflect.ValueOf(f).Pointer()
1407 rf := runtime.FuncForPC(p)
1408 return rf.Name()
1409}
1410
1411func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001412 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
1413 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001414 }
1415}
1416
khenaidoo4c9e5592019-09-09 16:20:41 -04001417func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) string {
khenaidoo19d7b632018-10-30 10:49:50 -04001418 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001419 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001420 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001421 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001422 return ""
khenaidoob9203542018-09-17 22:56:37 -04001423}
serkant.uluderya334479d2019-04-10 08:26:15 -07001424
1425func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1426 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1427 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1428 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1429 var res interface{}
1430 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1431 res = agent.simulateAlarm(ctx, simulatereq)
1432 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1433 }
1434 //TODO CLI always get successful response
1435 sendResponse(ctx, ch, res)
1436}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001437
1438func (dMgr *DeviceManager) updateDeviceReason(deviceId string, reason string) error {
1439 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceId, "reason": reason})
1440 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1441 return agent.updateDeviceReason(reason)
1442 }
1443 return status.Errorf(codes.NotFound, "%s", deviceId)
1444}