blob: beff7ae56e0d506181a80f2edec7f555880ddb30 [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package core
17
18import (
19 "context"
20 "errors"
khenaidoo3d3b8c22019-05-22 18:10:39 -040021 "github.com/opencord/voltha-go/rw_core/utils"
Scott Baker807addd2019-10-24 15:16:21 -070022 "github.com/opencord/voltha-lib-go/v2/pkg/db/model"
23 "github.com/opencord/voltha-lib-go/v2/pkg/kafka"
24 "github.com/opencord/voltha-lib-go/v2/pkg/log"
25 "github.com/opencord/voltha-lib-go/v2/pkg/probe"
William Kurkiandaa6bb22019-03-07 12:26:28 -050026 ic "github.com/opencord/voltha-protos/go/inter_container"
27 ofp "github.com/opencord/voltha-protos/go/openflow_13"
28 "github.com/opencord/voltha-protos/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040029 "google.golang.org/grpc/codes"
30 "google.golang.org/grpc/status"
31 "reflect"
32 "runtime"
33 "sync"
34)
35
36type DeviceManager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040037 deviceAgents sync.Map
38 rootDevices map[string]bool
39 lockRootDeviceMap sync.RWMutex
40 core *Core
41 adapterProxy *AdapterProxy
42 adapterMgr *AdapterManager
43 logicalDeviceMgr *LogicalDeviceManager
44 kafkaICProxy *kafka.InterContainerProxy
45 stateTransitions *TransitionMap
46 clusterDataProxy *model.Proxy
47 coreInstanceId string
48 exitChannel chan int
49 defaultTimeout int64
50 devicesLoadingLock sync.RWMutex
51 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040052}
53
Richard Jankowski199fd862019-03-18 14:49:51 -040054func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040055 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040056 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040057 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040058 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040059 deviceMgr.kafkaICProxy = core.kmp
Kent Hagermana6d0c362019-07-30 12:50:21 -040060 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic)
Richard Jankowski199fd862019-03-18 14:49:51 -040061 deviceMgr.coreInstanceId = core.instanceId
62 deviceMgr.clusterDataProxy = core.clusterDataProxy
63 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040064 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
65 deviceMgr.defaultTimeout = core.config.DefaultCoreTimeout
khenaidoo4c9e5592019-09-09 16:20:41 -040066 deviceMgr.devicesLoadingLock = sync.RWMutex{}
67 deviceMgr.deviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040068 return &deviceMgr
69}
70
khenaidoo4d4802d2018-10-04 21:59:49 -040071func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040072 log.Info("starting-device-manager")
73 dMgr.logicalDeviceMgr = logicalDeviceMgr
74 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070075 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
khenaidoob9203542018-09-17 22:56:37 -040076 log.Info("device-manager-started")
77}
78
khenaidoo4d4802d2018-10-04 21:59:49 -040079func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040080 log.Info("stopping-device-manager")
81 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070082 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
khenaidoob9203542018-09-17 22:56:37 -040083 log.Info("device-manager-stopped")
84}
85
86func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
87 if ctx.Err() == nil {
88 // Returned response only of the ctx has not been cancelled/timeout/etc
89 // Channel is automatically closed when a context is Done
90 ch <- result
91 log.Debugw("sendResponse", log.Fields{"result": result})
92 } else {
93 // Should the transaction be reverted back?
94 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
95 }
96}
97
98func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040099 if _, exist := dMgr.deviceAgents.Load(agent.deviceId); !exist {
100 dMgr.deviceAgents.Store(agent.deviceId, agent)
khenaidoob9203542018-09-17 22:56:37 -0400101 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400102 dMgr.lockRootDeviceMap.Lock()
103 defer dMgr.lockRootDeviceMap.Unlock()
104 dMgr.rootDevices[agent.deviceId] = agent.isRootdevice
105
khenaidoob9203542018-09-17 22:56:37 -0400106}
107
khenaidoo4c9e5592019-09-09 16:20:41 -0400108func (dMgr *DeviceManager) deleteDeviceAgentFromMap(agent *DeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400109 dMgr.deviceAgents.Delete(agent.deviceId)
khenaidoo2c6a0992019-04-29 13:46:56 -0400110 dMgr.lockRootDeviceMap.Lock()
111 defer dMgr.lockRootDeviceMap.Unlock()
112 delete(dMgr.rootDevices, agent.deviceId)
khenaidoo4d4802d2018-10-04 21:59:49 -0400113}
114
khenaidoo297cd252019-02-07 22:10:23 -0500115// getDeviceAgent returns the agent managing the device. If the device is not in memory, it will loads it, if it exists
khenaidoob9203542018-09-17 22:56:37 -0400116func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400117 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
118 return agent.(*DeviceAgent)
khenaidoo297cd252019-02-07 22:10:23 -0500119 } else {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400120 // Try to load into memory - loading will also create the device agent and set the device ownership
khenaidoo297cd252019-02-07 22:10:23 -0500121 if err := dMgr.load(deviceId); err == nil {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400122 if agent, ok = dMgr.deviceAgents.Load(deviceId); !ok {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400123 return nil
124 } else {
125 // Register this device for ownership tracking
126 go dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: deviceId})
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400127 return agent.(*DeviceAgent)
khenaidoo297cd252019-02-07 22:10:23 -0500128 }
khenaidoo3d3b8c22019-05-22 18:10:39 -0400129 } else {
130 //TODO: Change the return params to return an error as well
131 log.Errorw("loading-device-failed", log.Fields{"deviceId": deviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500132 }
khenaidoob9203542018-09-17 22:56:37 -0400133 }
134 return nil
135}
136
khenaidoo297cd252019-02-07 22:10:23 -0500137// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500138func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500139 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400140
141 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
142 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
143 return true
144 })
145
khenaidoo7ccedd52018-12-14 16:48:54 -0500146 return result
147}
148
khenaidoob9203542018-09-17 22:56:37 -0400149func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530150 if dMgr.isParentDeviceExist(device) {
151 log.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
152 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
153 return
154 }
khenaidoo92e62c52018-10-03 14:02:54 -0400155 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400156
khenaidoo5e677ae2019-02-28 17:26:29 -0500157 // Ensure this device is set as root
158 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400159 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400160 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400161 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500162 agent.start(ctx, false)
khenaidoob9203542018-09-17 22:56:37 -0400163
khenaidoo92e62c52018-10-03 14:02:54 -0400164 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400165}
166
167func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400168 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400169 var res interface{}
170 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
171 res = agent.enableDevice(ctx)
172 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400173 }
174
175 sendResponse(ctx, ch, res)
176}
177
khenaidoo92e62c52018-10-03 14:02:54 -0400178func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
179 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400180 var res interface{}
181 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
182 res = agent.disableDevice(ctx)
183 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400184 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400185 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400186 }
khenaidoo92e62c52018-10-03 14:02:54 -0400187
188 sendResponse(ctx, ch, res)
189}
190
khenaidoo4d4802d2018-10-04 21:59:49 -0400191func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
192 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
193 var res interface{}
194 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
195 res = agent.rebootDevice(ctx)
196 log.Debugw("rebootDevice-result", log.Fields{"result": res})
197 } else {
198 res = status.Errorf(codes.NotFound, "%s", id.Id)
199 }
200 sendResponse(ctx, ch, res)
201}
202
203func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
204 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
205 var res interface{}
206 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
207 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400208 log.Debugw("deleteDevice-result", log.Fields{"result": res})
209 } else {
210 res = status.Errorf(codes.NotFound, "%s", id.Id)
211 }
212 sendResponse(ctx, ch, res)
213}
214
khenaidoo6d62c002019-05-15 21:57:03 -0400215// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
216// This function is called only in the Core that does not own this device. In the Core that owns this device then a
217// deletion deletion also includes removal of any reference of this device.
218func (dMgr *DeviceManager) stopManagingDevice(id string) {
219 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
220 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
221 if root, _ := dMgr.IsRootDevice(id); root == true {
222 // stop managing the logical device
223 ldeviceId := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceId(id)
224 if ldeviceId != "" { // Can happen if logical device agent was already stopped
225 dMgr.core.deviceOwnership.AbandonDevice(ldeviceId)
226 }
227 // stop managing the child devices
228 childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentId(id)
229 for _, cId := range childDeviceIds {
230 dMgr.stopManagingDevice(cId)
231 }
232 }
233 if agent := dMgr.getDeviceAgent(id); agent != nil {
234 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -0400235 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400236 // Abandon the device ownership
237 dMgr.core.deviceOwnership.AbandonDevice(id)
238 }
239 }
240}
241
khenaidoo0a822f92019-05-08 15:15:57 -0400242func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
243 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400244 dMgr.stopManagingDevice(cDevice.Id)
245 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400246}
247
khenaidoo297cd252019-02-07 22:10:23 -0500248// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400249func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
250 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400251 if agent := dMgr.getDeviceAgent(id); agent != nil {
252 return agent.getDevice()
253 }
254 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400255}
256
Matt Jeanneret4e241952019-02-28 11:16:04 -0500257func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
Matt Jeanneret0c5088c2019-04-22 16:16:19 -0400258 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber,
259 "parentPortNo": parentPortNo, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500260
261 var parentDevice *voltha.Device
262 var err error
263 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
264 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
265 }
266 var childDeviceIds []string
267 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
268 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
269 }
270 if len(childDeviceIds) == 0 {
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700271 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500272 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
273 }
274
275 var foundChildDevice *voltha.Device
276 for _, childDeviceId := range childDeviceIds {
277 found := false
278 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
279
280 foundOnuId := false
281 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
282 if searchDevice.ParentPortNo == uint32(parentPortNo) {
283 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
284 foundOnuId = true
285 }
286 }
287
288 foundSerialNumber := false
289 if searchDevice.SerialNumber == serialNumber {
290 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
291 foundSerialNumber = true
292 }
293
294 // if both onuId and serialNumber are provided both must be true for the device to be found
295 // otherwise whichever one found a match is good enough
296 if onuId > 0 && serialNumber != "" {
297 found = foundOnuId && foundSerialNumber
298 } else {
299 found = foundOnuId || foundSerialNumber
300 }
301
302 if found == true {
303 foundChildDevice = searchDevice
304 break
305 }
306 }
307 }
308
309 if foundChildDevice != nil {
310 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
311 return foundChildDevice, nil
312 }
313
314 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
315 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
316 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
317}
318
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500319func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
320 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
321
322 var parentDevice *voltha.Device
323 var err error
324 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
325 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
326 }
327 var childDeviceIds []string
328 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
329 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
330 }
331 if len(childDeviceIds) == 0 {
332 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
333 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
334 }
335
336 var foundChildDevice *voltha.Device
337 for _, childDeviceId := range childDeviceIds {
338 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
339 if searchDevice.ProxyAddress == proxyAddress {
340 foundChildDevice = searchDevice
341 break
342 }
343 }
344 }
345
346 if foundChildDevice != nil {
347 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
348 return foundChildDevice, nil
349 }
350
351 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
352 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
353}
354
khenaidoo297cd252019-02-07 22:10:23 -0500355func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400356 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500357 return exist
358}
359
khenaidoo19d7b632018-10-30 10:49:50 -0400360func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400361 dMgr.lockRootDeviceMap.RLock()
362 defer dMgr.lockRootDeviceMap.RUnlock()
363 if exist := dMgr.rootDevices[id]; exist {
364 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400365 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400366 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400367}
368
Stephane Barbarieaa467942019-02-06 14:09:44 -0500369// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400370func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400371 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400372 result := &voltha.Devices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400373 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500374 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500375 // If device is not in memory then set it up
376 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400377 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400378 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500379 if err := agent.start(nil, true); err != nil {
380 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
381 agent.stop(nil)
382 } else {
383 dMgr.addDeviceAgentToMap(agent)
384 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500385 }
386 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400387 }
388 }
khenaidoo6d62c002019-05-15 21:57:03 -0400389 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400390 return result, nil
391}
392
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530393//isParentDeviceExist checks whether device is already preprovisioned.
394func (dMgr *DeviceManager) isParentDeviceExist(newDevice *voltha.Device) bool {
395 hostPort := newDevice.GetHostAndPort()
396 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
397 for _, device := range devices.([]interface{}) {
398 if !device.(*voltha.Device).Root {
399 continue
400 }
401 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() {
402 return true
403 }
404 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress {
405 return true
406 }
407 }
408 }
409 return false
410}
411
khenaidoo6d62c002019-05-15 21:57:03 -0400412//getDeviceFromModelretrieves the device data from the model.
413func (dMgr *DeviceManager) getDeviceFromModel(deviceId string) (*voltha.Device, error) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400414 if device := dMgr.clusterDataProxy.Get(context.Background(), "/devices/"+deviceId, 0, false, ""); device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400415 if d, ok := device.(*voltha.Device); ok {
416 return d, nil
417 }
418 }
419 return nil, status.Error(codes.NotFound, deviceId)
420}
421
khenaidoo297cd252019-02-07 22:10:23 -0500422// loadDevice loads the deviceId in memory, if not present
423func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
khenaidoo297cd252019-02-07 22:10:23 -0500424 if deviceId == "" {
425 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
426 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400427 var err error
428 var device *voltha.Device
429 dMgr.devicesLoadingLock.Lock()
430 if _, exist := dMgr.deviceLoadingInProgress[deviceId]; !exist {
431 if !dMgr.IsDeviceInCache(deviceId) {
432 dMgr.deviceLoadingInProgress[deviceId] = []chan int{make(chan int, 1)}
433 dMgr.devicesLoadingLock.Unlock()
434 // Proceed with the loading only if the device exist in the Model (could have been deleted)
435 if device, err = dMgr.getDeviceFromModel(deviceId); err == nil {
436 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
437 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
438 if err = agent.start(nil, true); err != nil {
439 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceId, "error": err})
440 agent.stop(nil)
441 } else {
442 dMgr.addDeviceAgentToMap(agent)
443 }
444 } else {
445 log.Debugw("Device not in model", log.Fields{"deviceId": deviceId})
khenaidoo6d62c002019-05-15 21:57:03 -0400446 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400447 // announce completion of task to any number of waiting channels
448 dMgr.devicesLoadingLock.Lock()
449 if v, ok := dMgr.deviceLoadingInProgress[deviceId]; ok {
450 for _, ch := range v {
451 close(ch)
452 }
453 delete(dMgr.deviceLoadingInProgress, deviceId)
454 }
455 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400456 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400457 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500458 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400459 } else {
460 ch := make(chan int, 1)
461 dMgr.deviceLoadingInProgress[deviceId] = append(dMgr.deviceLoadingInProgress[deviceId], ch)
462 dMgr.devicesLoadingLock.Unlock()
463 // Wait for the channel to be closed, implying the process loading this device is done.
464 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500465 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400466 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
467 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500468 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400469 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceId)
khenaidoo297cd252019-02-07 22:10:23 -0500470}
471
472// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
473func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
474 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
475 if device.Root {
476 // Scenario A
477 if device.ParentId != "" {
478 // Load logical device if needed.
479 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
480 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
481 }
482 } else {
483 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
484 }
485 // Load all child devices, if needed
486 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
487 for _, childDeviceId := range childDeviceIds {
488 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400489 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500490 return err
491 }
492 }
493 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
494 } else {
495 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
496 }
497 }
498 return nil
499}
500
501// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
502// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
503// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
504// and the proceed with the request.
505func (dMgr *DeviceManager) load(deviceId string) error {
506 log.Debug("load...")
507 // First load the device - this may fail in case the device was deleted intentionally by the other core
508 var dAgent *DeviceAgent
509 var err error
510 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500511 return err
512 }
513 // Get the loaded device details
514 var device *voltha.Device
515 if device, err = dAgent.getDevice(); err != nil {
516 return err
517 }
518
519 // If the device is in Pre-provisioning or deleted state stop here
520 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
521 return nil
522 }
523
524 // Now we face two scenarios
525 if device.Root {
526 // Load all children as well as the parent of this device (logical_device)
527 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
528 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
529 return err
530 }
531 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
532 } else {
533 // Scenario B - use the parentId of that device (root device) to trigger the loading
534 if device.ParentId != "" {
535 return dMgr.load(device.ParentId)
536 }
537 }
538 return nil
539}
540
khenaidoo7ccedd52018-12-14 16:48:54 -0500541// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
542func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
543 log.Debug("ListDeviceIDs")
544 // Report only device IDs that are in the device agent map
545 return dMgr.listDeviceIdsFromMap(), nil
546}
547
khenaidoo4c9e5592019-09-09 16:20:41 -0400548//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
549//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500550func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400551 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500552 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400553 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500554 toReconcile := len(ids.Items)
555 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400556 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500557 for _, id := range ids.Items {
khenaidoo4c9e5592019-09-09 16:20:41 -0400558 if err = dMgr.load(id.Id); err != nil {
559 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
560 } else {
561 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500562 }
563 }
564 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400565 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500566 }
567 } else {
568 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
569 }
570 sendResponse(ctx, ch, res)
571}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500572
khenaidooba6b6c42019-08-02 09:11:56 -0400573// isOkToReconcile validates whether a device is in the correct status to be reconciled
574func isOkToReconcile(device *voltha.Device) bool {
575 if device == nil {
576 return false
577 }
578 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
579}
580
581// adapterRestarted is invoked whenever an adapter is restarted
582func (dMgr *DeviceManager) adapterRestarted(adapter *voltha.Adapter) error {
583 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
584
585 // Let's reconcile the device managed by this Core only
586 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
587 if len(rootDeviceIds) == 0 {
588 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
589 return nil
590 }
591
592 chnlsList := make([]chan interface{}, 0)
593 for _, rootDeviceId := range rootDeviceIds {
594 if rootDevice, _ := dMgr.getDeviceFromModel(rootDeviceId); rootDevice != nil {
595 if rootDevice.Adapter == adapter.Id {
596 if isOkToReconcile(rootDevice) {
597 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
598 chnlsList = dMgr.sendReconcileDeviceRequest(rootDevice, chnlsList)
599 } else {
600 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
601 }
602 } else { // Should we be reconciling the root's children instead?
603 childManagedByAdapter:
604 for _, port := range rootDevice.Ports {
605 for _, peer := range port.Peers {
606 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
607 if childDevice.Adapter == adapter.Id {
608 if isOkToReconcile(childDevice) {
609 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
610 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
611 } else {
612 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
613 }
614 } else {
615 // All child devices under a parent device are typically managed by the same adapter type.
616 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
617 break childManagedByAdapter
618 }
619 }
620 }
621 }
622 }
623 }
624 }
625 if len(chnlsList) > 0 {
626 // Wait for completion
627 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
628 return status.Errorf(codes.Aborted, "errors-%s", res)
629 }
630 } else {
631 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
632 }
633 return nil
634}
635
636func (dMgr *DeviceManager) sendReconcileDeviceRequest(device *voltha.Device, chnlsList []chan interface{}) []chan interface{} {
637 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
638 // point of creating a device agent (if the device is not being managed by this Core) before sending the request
639 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to teh adapter via
640 // the adapter_proxy.
641 ch := make(chan interface{})
642 chnlsList = append(chnlsList, ch)
643 go func(device *voltha.Device) {
644 if err := dMgr.adapterProxy.ReconcileDevice(context.Background(), device); err != nil {
645 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
646 ch <- status.Errorf(codes.Internal, "device: %s", device.Id)
647 }
648 ch <- nil
649 }(device)
650
651 return chnlsList
652}
653
654func (dMgr *DeviceManager) reconcileChildDevices(parentDeviceId string) error {
655 if parentDevice, _ := dMgr.getDeviceFromModel(parentDeviceId); parentDevice != nil {
656 chnlsList := make([]chan interface{}, 0)
657 for _, port := range parentDevice.Ports {
658 for _, peer := range port.Peers {
659 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
660 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
661 }
662 }
663 }
664 // Wait for completion
665 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
666 return status.Errorf(codes.Aborted, "errors-%s", res)
667 }
668 }
669 return nil
670}
671
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700672func (dMgr *DeviceManager) updateDeviceUsingAdapterData(device *voltha.Device) error {
673 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400674 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700675 return agent.updateDeviceUsingAdapterData(device)
khenaidoob9203542018-09-17 22:56:37 -0400676 }
677 return status.Errorf(codes.NotFound, "%s", device.Id)
678}
679
680func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
681 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400682 if err := agent.addPort(port); err != nil {
683 return err
684 }
685 // Setup peer ports
686 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
687 for _, peerPort := range port.Peers {
688 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
689 if err := agent.addPeerPort(meAsPeer); err != nil {
690 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
691 return err
692 }
693 }
694 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400695 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
696 // then a logical port will be added to the logical device and the device graph generated. If the port is a
697 // PON port then only the device graph will be generated.
698 if device, err := dMgr.GetDevice(deviceId); err == nil {
699 go dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
700 } else {
701 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
702 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400703 }
khenaidoo92e62c52018-10-03 14:02:54 -0400704 return nil
705 } else {
706 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400707 }
khenaidoob9203542018-09-17 22:56:37 -0400708}
709
khenaidoo0a822f92019-05-08 15:15:57 -0400710func (dMgr *DeviceManager) deletePeerPorts(fromDeviceId string, deviceId string) error {
711 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceId, "deviceid": deviceId})
712 if agent := dMgr.getDeviceAgent(fromDeviceId); agent != nil {
713 return agent.deletePeerPorts(deviceId)
714 }
715 return status.Errorf(codes.NotFound, "%s", deviceId)
716}
717
Manikkaraj kb1a10922019-07-29 12:10:34 -0400718func (dMgr *DeviceManager) addFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
719 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceId, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -0400720 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400721 return agent.addFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400722 }
723 return status.Errorf(codes.NotFound, "%s", deviceId)
724}
725
Manikkaraj kb1a10922019-07-29 12:10:34 -0400726func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400727 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceId})
728 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400729 return agent.deleteFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400730 }
731 return status.Errorf(codes.NotFound, "%s", deviceId)
732}
733
Manikkaraj kb1a10922019-07-29 12:10:34 -0400734func (dMgr *DeviceManager) updateFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400735 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceId})
736 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400737 return agent.updateFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400738 }
739 return status.Errorf(codes.NotFound, "%s", deviceId)
740}
741
khenaidoob3127472019-07-24 21:04:55 -0400742// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
743// following a user action
744func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
745 var res interface{}
746 if pmConfigs.Id == "" {
747 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
748 } else if agent := dMgr.getDeviceAgent(pmConfigs.Id); agent != nil {
749 res = agent.updatePmConfigs(ctx, pmConfigs)
750 } else {
751 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
752 }
753 sendResponse(ctx, ch, res)
754}
755
756// initPmConfigs initialize the pm configs as defined by the adapter.
757func (dMgr *DeviceManager) initPmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
758 if pmConfigs.Id == "" {
759 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
760 }
khenaidoob9203542018-09-17 22:56:37 -0400761 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400762 return agent.initPmConfigs(pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400763 }
764 return status.Errorf(codes.NotFound, "%s", deviceId)
765}
766
khenaidoob3127472019-07-24 21:04:55 -0400767func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceId string) (*voltha.PmConfigs, error) {
768 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
769 return agent.listPmConfigs(ctx)
770 }
771 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
772}
773
khenaidoo79232702018-12-04 11:00:41 -0500774func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400775 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400776 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
777 return agent.getSwitchCapability(ctx)
778 }
779 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
780}
781
khenaidoo92e62c52018-10-03 14:02:54 -0400782func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
783 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400784 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400785 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400786 }
787 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
788}
789
khenaidoo79232702018-12-04 11:00:41 -0500790func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400791 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400792 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
793 return agent.getPortCapability(ctx, portNo)
794 }
795 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
796}
797
khenaidoo92e62c52018-10-03 14:02:54 -0400798func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
799 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400800 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400801 return agent.updateDeviceStatus(operStatus, connStatus)
802 }
803 return status.Errorf(codes.NotFound, "%s", deviceId)
804}
805
khenaidoo4d4802d2018-10-04 21:59:49 -0400806func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
807 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
808 var parentDevice *voltha.Device
809 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400810 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400811 return status.Errorf(codes.Aborted, "%s", err.Error())
812 }
813 var childDeviceIds []string
814 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
815 return status.Errorf(codes.Aborted, "%s", err.Error())
816 }
817 if len(childDeviceIds) == 0 {
818 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
819 }
820 for _, childDeviceId := range childDeviceIds {
821 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
822 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
823 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
824 }
825 }
826 }
827 return nil
828}
829
khenaidoo92e62c52018-10-03 14:02:54 -0400830func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
831 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
832 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
833 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400834 }
835 return status.Errorf(codes.NotFound, "%s", deviceId)
836}
837
khenaidoo0a822f92019-05-08 15:15:57 -0400838func (dMgr *DeviceManager) deleteAllPorts(deviceId string) error {
839 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceId})
840 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
841 if err := agent.deleteAllPorts(); err != nil {
842 return err
843 }
844 // Notify the logical device manager to remove all logical ports, if needed.
845 // At this stage the device itself may gave been deleted already at a deleteAllPorts
846 // typically is part of a device deletion phase.
847 if device, err := dMgr.GetDevice(deviceId); err == nil {
848 go dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
849 } else {
850 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
851 return err
852 }
853 return nil
854 }
855 return status.Errorf(codes.NotFound, "%s", deviceId)
856}
857
khenaidoo3ab34882019-05-02 21:33:30 -0400858//updatePortsState updates all ports on the device
859func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
860 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
861
862 var adminState voltha.AdminState_AdminState
863 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
864 switch state {
865 case voltha.OperStatus_ACTIVE:
866 adminState = voltha.AdminState_ENABLED
867 if err := agent.enablePorts(); err != nil {
868 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
869 return err
870 }
871 case voltha.OperStatus_UNKNOWN:
872 adminState = voltha.AdminState_DISABLED
873 if err := agent.disablePorts(); err != nil {
874 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
875 return err
876 }
877 default:
878 return status.Error(codes.Unimplemented, "state-change-not-implemented")
879 }
880 // Notify the logical device about the state change
881 if device, err := dMgr.GetDevice(deviceId); err != nil {
882 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
883 return err
884 } else {
885 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
886 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
887 return err
888 }
889 return nil
890 }
891 }
892 return status.Errorf(codes.NotFound, "%s", deviceId)
893}
894
Matt Jeanneret4e241952019-02-28 11:16:04 -0500895func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700896 channelId int64, vendorId string, serialNumber string, onuId int64) (*voltha.Device, error) {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700897 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId, "parentPortNo": parentPortNo, "deviceType": deviceType, "channelId": channelId, "vendorId": vendorId, "serialNumber": serialNumber, "onuId": onuId})
898
899 if deviceType == "" && vendorId != "" {
900 log.Debug("device-type-is-nil-fetching-device-type")
901 if deviceTypesIf := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, ""); deviceTypesIf != nil {
902 OLoop:
903 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
904 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
905 for _, v := range dType.VendorIds {
906 if v == vendorId {
907 deviceType = dType.Adapter
908 break OLoop
909 }
910 }
911 }
912 }
913 }
914 }
915 //if no match found for the vendorid,report adapter with the custom error message
916 if deviceType == "" {
917 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorId})
918 return nil, status.Errorf(codes.NotFound, "%s", vendorId)
919 }
khenaidoob9203542018-09-17 22:56:37 -0400920
921 // Create the ONU device
922 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400923 childDevice.Type = deviceType
924 childDevice.ParentId = parentDeviceId
925 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500926 childDevice.VendorId = vendorId
927 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400928 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400929
930 //Get parent device type
931 parent, err := dMgr.GetDevice(parentDeviceId)
932 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500933 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700934 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400935 }
936
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700937 if device, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500938 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700939 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500940 }
941
942 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400943
944 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400945 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400946 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500947 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400948
khenaidoo09771ef2019-10-11 14:25:02 -0400949 // Since this Core has handled this request then it therefore owns this child device. Set the
950 // ownership of this device to this Core
951 dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: agent.deviceId})
952
khenaidoob9203542018-09-17 22:56:37 -0400953 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400954 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500955 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400956 }
957
khenaidoo79232702018-12-04 11:00:41 -0500958 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500959 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500960
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700961 return agent.lastData, nil
khenaidoob9203542018-09-17 22:56:37 -0400962}
963
964func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
965 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400966 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
967 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500968 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400969 return nil
khenaidoob9203542018-09-17 22:56:37 -0400970 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400971 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -0400972 for _, handler := range handlers {
973 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
974 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400975 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400976 return err
977 }
978 }
khenaidoob9203542018-09-17 22:56:37 -0400979 return nil
980}
981
khenaidoofdbad6e2018-11-06 22:26:38 -0500982func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
983 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
984 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
985 return agent.packetOut(outPort, packet)
986 }
987 return status.Errorf(codes.NotFound, "%s", deviceId)
988}
989
khenaidoo297cd252019-02-07 22:10:23 -0500990func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500991 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
992 // Get the logical device Id based on the deviceId
993 var device *voltha.Device
994 var err error
995 if device, err = dMgr.GetDevice(deviceId); err != nil {
996 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
997 return err
998 }
khenaidoo43c82122018-11-22 18:38:28 -0500999 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -05001000 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
1001 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
1002 }
1003
khenaidoo297cd252019-02-07 22:10:23 -05001004 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001005 return err
1006 }
1007 return nil
1008}
1009
khenaidooad06fd72019-10-28 12:26:05 -04001010func (dMgr *DeviceManager) setParentId(device *voltha.Device, parentId string) error {
1011 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentId})
1012 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
1013 return agent.setParentId(device, parentId)
1014 }
1015 return status.Errorf(codes.NotFound, "%s", device.Id)
1016}
1017
khenaidoo0a822f92019-05-08 15:15:57 -04001018func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
1019 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001020 // Verify whether the logical device has already been created
1021 if cDevice.ParentId != "" {
1022 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1023 return nil
1024 }
khenaidoob9203542018-09-17 22:56:37 -04001025 var err error
khenaidooad06fd72019-10-28 12:26:05 -04001026 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001027 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1028 return err
1029 }
khenaidoob9203542018-09-17 22:56:37 -04001030 return nil
1031}
1032
khenaidoo0a822f92019-05-08 15:15:57 -04001033func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
1034 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001035 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001036 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001037 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1038 return err
1039 }
1040 // Remove the logical device Id from the parent device
1041 logicalId := ""
1042 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
1043 return nil
1044}
1045
khenaidoo0a822f92019-05-08 15:15:57 -04001046func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001047 log.Info("deleteLogicalPort")
1048 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001049 // Get the logical port associated with this device
1050 var lPortId *voltha.LogicalPortId
1051 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001052 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001053 return err
1054 }
1055 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
1056 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001057 return err
1058 }
khenaidoo92e62c52018-10-03 14:02:54 -04001059 return nil
1060}
1061
khenaidoo0a822f92019-05-08 15:15:57 -04001062func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1063 log.Info("deleteLogicalPorts")
1064 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1065 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1066 return err
1067 }
1068 return nil
1069}
1070
khenaidoo59ef7be2019-06-21 12:40:28 -04001071func (dMgr *DeviceManager) MarkChildDevicesAsUnReachable(device *voltha.Device) error {
1072 log.Info("MarkChildDevicesAsUnReachable")
1073 // Set the connection status to unreachable
1074 connStatus := voltha.ConnectStatus_UNREACHABLE
1075 // Do not set the operational status. Setting it to -1 will do the trick
1076 operStatus := voltha.OperStatus_OperStatus(-1)
1077 if err := dMgr.updateChildrenStatus(device.Id, operStatus, connStatus); err != nil {
1078 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1079 return err
1080 }
1081 return nil
1082}
1083
khenaidoo92e62c52018-10-03 14:02:54 -04001084func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1085 // Sanity check
1086 if childDevice.Root {
1087 // childDevice is the parent device
1088 return childDevice
1089 }
khenaidoo19d7b632018-10-30 10:49:50 -04001090 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001091 return parentDevice
1092}
1093
khenaidoo0a822f92019-05-08 15:15:57 -04001094//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1095//cannot manage the child devices. This will trigger the Core to disable all the child devices.
1096func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
1097 log.Debug("childDevicesLost")
1098 var err error
1099 var parentDevice *voltha.Device
1100 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1101 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1102 return err
1103 }
1104 return dMgr.DisableAllChildDevices(parentDevice)
1105}
1106
1107//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1108// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
1109func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
1110 log.Debug("childDevicesDetected")
1111 var err error
1112 var parentDevice *voltha.Device
1113 var childDeviceIds []string
1114
1115 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1116 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1117 return err
1118 }
1119
1120 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1121 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1122 }
1123 if len(childDeviceIds) == 0 {
1124 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1125 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001126 allChildEnableRequestSent := true
khenaidoo0a822f92019-05-08 15:15:57 -04001127 for _, childDeviceId := range childDeviceIds {
1128 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001129 // Run the children re-registration in its own routine
1130 go agent.enableDevice(nil)
1131 } else {
1132 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceId)
1133 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceId})
1134 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001135 }
1136 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001137 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001138 return err
1139 }
1140 return nil
1141}
1142
khenaidoo4d4802d2018-10-04 21:59:49 -04001143/*
1144All the functions below are callback functions where they are invoked with the latest and previous data. We can
1145therefore use the data as is without trying to get the latest from the model.
1146*/
1147
khenaidoo0a822f92019-05-08 15:15:57 -04001148//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1149func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1150 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001151 var childDeviceIds []string
1152 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001153 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1154 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001155 }
1156 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001157 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001158 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001159 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -04001160 for _, childDeviceId := range childDeviceIds {
1161 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1162 if err = agent.disableDevice(nil); err != nil {
1163 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001164 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001165 }
1166 }
1167 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001168 if !allChildDisable {
1169 return err
1170 }
khenaidoo92e62c52018-10-03 14:02:54 -04001171 return nil
1172}
1173
khenaidoo0a822f92019-05-08 15:15:57 -04001174//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1175func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1176 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001177 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001178 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001179 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1180 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001181 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001182 if len(childDeviceIds) == 0 {
1183 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1184 }
1185 allChildDeleted := true
1186 for _, childDeviceId := range childDeviceIds {
1187 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1188 if err = agent.deleteDevice(nil); err != nil {
1189 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
1190 allChildDeleted = false
1191 } else {
1192 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -04001193 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo4d4802d2018-10-04 21:59:49 -04001194 }
1195 }
1196 }
1197 if !allChildDeleted {
1198 return err
1199 }
1200 return nil
1201}
1202
khenaidoo6d62c002019-05-15 21:57:03 -04001203//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1204// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1205// device during a delete device operation.
1206func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentId(id string) []string {
1207 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1208 deviceIds := make([]string, 0)
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001209 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
1210 agent := value.(*DeviceAgent)
khenaidoo6d62c002019-05-15 21:57:03 -04001211 if agent.parentId == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001212 deviceIds = append(deviceIds, key.(string))
khenaidoo6d62c002019-05-15 21:57:03 -04001213 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001214 return true
1215 })
khenaidoo6d62c002019-05-15 21:57:03 -04001216 return deviceIds
1217}
1218
khenaidoo4d4802d2018-10-04 21:59:49 -04001219//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1220func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1221 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001222 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001223 if parentDevice != nil {
1224 for _, port := range parentDevice.Ports {
1225 for _, peer := range port.Peers {
1226 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1227 }
khenaidoo92e62c52018-10-03 14:02:54 -04001228 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001229 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001230 }
1231 return childDeviceIds, nil
1232}
1233
khenaidoo297cd252019-02-07 22:10:23 -05001234//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1235func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
1236 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
1237 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
1238 childDevices := make([]*voltha.Device, 0)
1239 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
1240 for _, deviceId := range childDeviceIds {
1241 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
1242 childDevices = append(childDevices, d)
1243 }
1244 }
1245 }
1246 return &voltha.Devices{Items: childDevices}, nil
1247 }
1248 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
1249}
1250
khenaidoo0a822f92019-05-08 15:15:57 -04001251func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001252 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -04001253 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001254 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1255 return err
1256 }
1257 return nil
1258}
1259
khenaidoof5a5bfa2019-01-23 22:20:29 -05001260func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1261 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1262 var res interface{}
1263 var err error
1264 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1265 if res, err = agent.downloadImage(ctx, img); err != nil {
1266 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1267 res = err
1268 }
1269 } else {
1270 res = status.Errorf(codes.NotFound, "%s", img.Id)
1271 }
1272 sendResponse(ctx, ch, res)
1273}
1274
1275func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1276 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1277 var res interface{}
1278 var err error
1279 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1280 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1281 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1282 res = err
1283 }
1284 } else {
1285 res = status.Errorf(codes.NotFound, "%s", img.Id)
1286 }
1287 sendResponse(ctx, ch, res)
1288}
1289
1290func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1291 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1292 var res interface{}
1293 var err error
1294 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1295 if res, err = agent.activateImage(ctx, img); err != nil {
1296 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1297 res = err
1298 }
1299 } else {
1300 res = status.Errorf(codes.NotFound, "%s", img.Id)
1301 }
1302 sendResponse(ctx, ch, res)
1303}
1304
1305func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1306 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1307 var res interface{}
1308 var err error
1309 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1310 if res, err = agent.revertImage(ctx, img); err != nil {
1311 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1312 res = err
1313 }
1314 } else {
1315 res = status.Errorf(codes.NotFound, "%s", img.Id)
1316 }
1317 sendResponse(ctx, ch, res)
1318}
1319
1320func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1321 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1322 var res interface{}
1323 var err error
1324 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1325 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1326 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1327 res = err
1328 }
1329 } else {
1330 res = status.Errorf(codes.NotFound, "%s", img.Id)
1331 }
1332 sendResponse(ctx, ch, res)
1333}
1334
khenaidoof5a5bfa2019-01-23 22:20:29 -05001335func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1336 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1337 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1338 if err := agent.updateImageDownload(img); err != nil {
1339 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1340 return err
1341 }
1342 } else {
1343 return status.Errorf(codes.NotFound, "%s", img.Id)
1344 }
1345 return nil
1346}
1347
1348func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1349 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1350 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1351 return agent.getImageDownload(ctx, img)
1352 }
1353 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1354}
1355
1356func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1357 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1358 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1359 return agent.listImageDownloads(ctx, deviceId)
1360 }
1361 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1362}
1363
khenaidoo0a822f92019-05-08 15:15:57 -04001364func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1365 log.Info("SetAdminStateToEnable")
1366 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1367 return agent.updateAdminState(voltha.AdminState_ENABLED)
1368 }
1369 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1370}
1371
khenaidoo92e62c52018-10-03 14:02:54 -04001372func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001373 log.Info("activateDevice")
1374 return nil
1375}
1376
khenaidoo92e62c52018-10-03 14:02:54 -04001377func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1378 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001379 return nil
1380}
1381
khenaidoo92e62c52018-10-03 14:02:54 -04001382func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001383 log.Info("abandonDevice")
1384 return nil
1385}
1386
khenaidoo92e62c52018-10-03 14:02:54 -04001387func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001388 log.Info("reEnableDevice")
1389 return nil
1390}
1391
khenaidoo92e62c52018-10-03 14:02:54 -04001392func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001393 log.Info("noOp")
1394 return nil
1395}
1396
khenaidoo92e62c52018-10-03 14:02:54 -04001397func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001398 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001399 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001400}
1401
khenaidoo0a822f92019-05-08 15:15:57 -04001402func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001403 log.Errorw("NotifyInvalidTransition", log.Fields{
1404 "device": pcDevice.Id,
1405 "adminState": pcDevice.AdminState,
1406 "operState": pcDevice.OperStatus,
1407 "connState": pcDevice.ConnectStatus,
1408 })
khenaidoo0a822f92019-05-08 15:15:57 -04001409 //TODO: notify over kafka?
1410 return nil
1411}
1412
khenaidoob9203542018-09-17 22:56:37 -04001413func funcName(f interface{}) string {
1414 p := reflect.ValueOf(f).Pointer()
1415 rf := runtime.FuncForPC(p)
1416 return rf.Name()
1417}
1418
1419func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001420 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
1421 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001422 }
1423}
1424
khenaidoo4c9e5592019-09-09 16:20:41 -04001425func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) string {
khenaidoo19d7b632018-10-30 10:49:50 -04001426 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001427 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001428 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001429 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001430 return ""
khenaidoob9203542018-09-17 22:56:37 -04001431}
serkant.uluderya334479d2019-04-10 08:26:15 -07001432
1433func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1434 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1435 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1436 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1437 var res interface{}
1438 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1439 res = agent.simulateAlarm(ctx, simulatereq)
1440 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1441 }
1442 //TODO CLI always get successful response
1443 sendResponse(ctx, ch, res)
1444}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001445
1446func (dMgr *DeviceManager) updateDeviceReason(deviceId string, reason string) error {
1447 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceId, "reason": reason})
1448 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1449 return agent.updateDeviceReason(reason)
1450 }
1451 return status.Errorf(codes.NotFound, "%s", deviceId)
1452}