blob: ce7ecd9f53cfc7654eefbe81755b3c8850e03a31 [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package core
17
18import (
19 "context"
20 "errors"
sbarbari17d7e222019-11-05 10:02:29 -050021 "github.com/opencord/voltha-go/db/model"
khenaidoo3d3b8c22019-05-22 18:10:39 -040022 "github.com/opencord/voltha-go/rw_core/utils"
Scott Baker807addd2019-10-24 15:16:21 -070023 "github.com/opencord/voltha-lib-go/v2/pkg/kafka"
24 "github.com/opencord/voltha-lib-go/v2/pkg/log"
25 "github.com/opencord/voltha-lib-go/v2/pkg/probe"
Scott Baker555307d2019-11-04 08:58:01 -080026 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
27 ofp "github.com/opencord/voltha-protos/v2/go/openflow_13"
28 "github.com/opencord/voltha-protos/v2/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040029 "google.golang.org/grpc/codes"
30 "google.golang.org/grpc/status"
31 "reflect"
32 "runtime"
33 "sync"
34)
35
36type DeviceManager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040037 deviceAgents sync.Map
38 rootDevices map[string]bool
39 lockRootDeviceMap sync.RWMutex
40 core *Core
41 adapterProxy *AdapterProxy
42 adapterMgr *AdapterManager
43 logicalDeviceMgr *LogicalDeviceManager
44 kafkaICProxy *kafka.InterContainerProxy
45 stateTransitions *TransitionMap
46 clusterDataProxy *model.Proxy
47 coreInstanceId string
48 exitChannel chan int
49 defaultTimeout int64
50 devicesLoadingLock sync.RWMutex
51 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040052}
53
Richard Jankowski199fd862019-03-18 14:49:51 -040054func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040055 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040056 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040057 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040058 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040059 deviceMgr.kafkaICProxy = core.kmp
Kent Hagermana6d0c362019-07-30 12:50:21 -040060 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic)
Richard Jankowski199fd862019-03-18 14:49:51 -040061 deviceMgr.coreInstanceId = core.instanceId
62 deviceMgr.clusterDataProxy = core.clusterDataProxy
63 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040064 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
65 deviceMgr.defaultTimeout = core.config.DefaultCoreTimeout
khenaidoo4c9e5592019-09-09 16:20:41 -040066 deviceMgr.devicesLoadingLock = sync.RWMutex{}
67 deviceMgr.deviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040068 return &deviceMgr
69}
70
khenaidoo4d4802d2018-10-04 21:59:49 -040071func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040072 log.Info("starting-device-manager")
73 dMgr.logicalDeviceMgr = logicalDeviceMgr
74 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070075 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
khenaidoob9203542018-09-17 22:56:37 -040076 log.Info("device-manager-started")
77}
78
khenaidoo4d4802d2018-10-04 21:59:49 -040079func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040080 log.Info("stopping-device-manager")
81 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070082 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
khenaidoob9203542018-09-17 22:56:37 -040083 log.Info("device-manager-stopped")
84}
85
86func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
87 if ctx.Err() == nil {
88 // Returned response only of the ctx has not been cancelled/timeout/etc
89 // Channel is automatically closed when a context is Done
90 ch <- result
91 log.Debugw("sendResponse", log.Fields{"result": result})
92 } else {
93 // Should the transaction be reverted back?
94 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
95 }
96}
97
98func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040099 if _, exist := dMgr.deviceAgents.Load(agent.deviceId); !exist {
100 dMgr.deviceAgents.Store(agent.deviceId, agent)
khenaidoob9203542018-09-17 22:56:37 -0400101 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400102 dMgr.lockRootDeviceMap.Lock()
103 defer dMgr.lockRootDeviceMap.Unlock()
104 dMgr.rootDevices[agent.deviceId] = agent.isRootdevice
105
khenaidoob9203542018-09-17 22:56:37 -0400106}
107
khenaidoo4c9e5592019-09-09 16:20:41 -0400108func (dMgr *DeviceManager) deleteDeviceAgentFromMap(agent *DeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400109 dMgr.deviceAgents.Delete(agent.deviceId)
khenaidoo2c6a0992019-04-29 13:46:56 -0400110 dMgr.lockRootDeviceMap.Lock()
111 defer dMgr.lockRootDeviceMap.Unlock()
112 delete(dMgr.rootDevices, agent.deviceId)
khenaidoo4d4802d2018-10-04 21:59:49 -0400113}
114
khenaidoo297cd252019-02-07 22:10:23 -0500115// getDeviceAgent returns the agent managing the device. If the device is not in memory, it will loads it, if it exists
khenaidoob9203542018-09-17 22:56:37 -0400116func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400117 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
118 return agent.(*DeviceAgent)
khenaidoo297cd252019-02-07 22:10:23 -0500119 } else {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400120 // Try to load into memory - loading will also create the device agent and set the device ownership
khenaidoo297cd252019-02-07 22:10:23 -0500121 if err := dMgr.load(deviceId); err == nil {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400122 if agent, ok = dMgr.deviceAgents.Load(deviceId); !ok {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400123 return nil
124 } else {
125 // Register this device for ownership tracking
126 go dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: deviceId})
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400127 return agent.(*DeviceAgent)
khenaidoo297cd252019-02-07 22:10:23 -0500128 }
khenaidoo3d3b8c22019-05-22 18:10:39 -0400129 } else {
130 //TODO: Change the return params to return an error as well
131 log.Errorw("loading-device-failed", log.Fields{"deviceId": deviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500132 }
khenaidoob9203542018-09-17 22:56:37 -0400133 }
134 return nil
135}
136
khenaidoo297cd252019-02-07 22:10:23 -0500137// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500138func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500139 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400140
141 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
142 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
143 return true
144 })
145
khenaidoo7ccedd52018-12-14 16:48:54 -0500146 return result
147}
148
khenaidoob9203542018-09-17 22:56:37 -0400149func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530150 if dMgr.isParentDeviceExist(device) {
151 log.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
152 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
153 return
154 }
khenaidoo92e62c52018-10-03 14:02:54 -0400155 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400156
khenaidoo5e677ae2019-02-28 17:26:29 -0500157 // Ensure this device is set as root
158 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400159 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400160 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400161 dMgr.addDeviceAgentToMap(agent)
Scott Baker80678602019-11-14 16:57:36 -0800162 device, err := agent.start(ctx, device)
163 if err != nil {
164 log.Errorf("Failed to start device")
165 sendResponse(ctx, ch, errors.New("Failed to start device"))
166 return
167 }
khenaidoob9203542018-09-17 22:56:37 -0400168
Scott Baker80678602019-11-14 16:57:36 -0800169 sendResponse(ctx, ch, device)
khenaidoob9203542018-09-17 22:56:37 -0400170}
171
172func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400173 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400174 var res interface{}
175 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
176 res = agent.enableDevice(ctx)
177 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400178 }
179
180 sendResponse(ctx, ch, res)
181}
182
khenaidoo92e62c52018-10-03 14:02:54 -0400183func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
184 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400185 var res interface{}
186 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
187 res = agent.disableDevice(ctx)
188 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400189 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400190 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400191 }
khenaidoo92e62c52018-10-03 14:02:54 -0400192
193 sendResponse(ctx, ch, res)
194}
195
khenaidoo4d4802d2018-10-04 21:59:49 -0400196func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
197 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
198 var res interface{}
199 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
200 res = agent.rebootDevice(ctx)
201 log.Debugw("rebootDevice-result", log.Fields{"result": res})
202 } else {
203 res = status.Errorf(codes.NotFound, "%s", id.Id)
204 }
205 sendResponse(ctx, ch, res)
206}
207
208func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
209 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
210 var res interface{}
211 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
212 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400213 log.Debugw("deleteDevice-result", log.Fields{"result": res})
214 } else {
215 res = status.Errorf(codes.NotFound, "%s", id.Id)
216 }
217 sendResponse(ctx, ch, res)
218}
219
khenaidoo6d62c002019-05-15 21:57:03 -0400220// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
221// This function is called only in the Core that does not own this device. In the Core that owns this device then a
222// deletion deletion also includes removal of any reference of this device.
223func (dMgr *DeviceManager) stopManagingDevice(id string) {
224 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
225 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
226 if root, _ := dMgr.IsRootDevice(id); root == true {
227 // stop managing the logical device
228 ldeviceId := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceId(id)
229 if ldeviceId != "" { // Can happen if logical device agent was already stopped
230 dMgr.core.deviceOwnership.AbandonDevice(ldeviceId)
231 }
232 // stop managing the child devices
233 childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentId(id)
234 for _, cId := range childDeviceIds {
235 dMgr.stopManagingDevice(cId)
236 }
237 }
238 if agent := dMgr.getDeviceAgent(id); agent != nil {
239 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -0400240 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400241 // Abandon the device ownership
242 dMgr.core.deviceOwnership.AbandonDevice(id)
243 }
244 }
245}
246
khenaidoo0a822f92019-05-08 15:15:57 -0400247func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
248 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400249 dMgr.stopManagingDevice(cDevice.Id)
250 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400251}
252
khenaidoo297cd252019-02-07 22:10:23 -0500253// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400254func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
255 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400256 if agent := dMgr.getDeviceAgent(id); agent != nil {
257 return agent.getDevice()
258 }
259 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400260}
261
Matt Jeanneret4e241952019-02-28 11:16:04 -0500262func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
Matt Jeanneret0c5088c2019-04-22 16:16:19 -0400263 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber,
264 "parentPortNo": parentPortNo, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500265
266 var parentDevice *voltha.Device
267 var err error
268 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
269 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
270 }
271 var childDeviceIds []string
272 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
273 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
274 }
275 if len(childDeviceIds) == 0 {
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700276 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500277 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
278 }
279
280 var foundChildDevice *voltha.Device
281 for _, childDeviceId := range childDeviceIds {
282 found := false
283 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
284
285 foundOnuId := false
286 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
287 if searchDevice.ParentPortNo == uint32(parentPortNo) {
288 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
289 foundOnuId = true
290 }
291 }
292
293 foundSerialNumber := false
294 if searchDevice.SerialNumber == serialNumber {
295 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
296 foundSerialNumber = true
297 }
298
299 // if both onuId and serialNumber are provided both must be true for the device to be found
300 // otherwise whichever one found a match is good enough
301 if onuId > 0 && serialNumber != "" {
302 found = foundOnuId && foundSerialNumber
303 } else {
304 found = foundOnuId || foundSerialNumber
305 }
306
307 if found == true {
308 foundChildDevice = searchDevice
309 break
310 }
311 }
312 }
313
314 if foundChildDevice != nil {
315 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
316 return foundChildDevice, nil
317 }
318
319 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
320 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
321 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
322}
323
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500324func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
325 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
326
327 var parentDevice *voltha.Device
328 var err error
329 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
330 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
331 }
332 var childDeviceIds []string
333 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
334 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
335 }
336 if len(childDeviceIds) == 0 {
337 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
338 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
339 }
340
341 var foundChildDevice *voltha.Device
342 for _, childDeviceId := range childDeviceIds {
343 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
344 if searchDevice.ProxyAddress == proxyAddress {
345 foundChildDevice = searchDevice
346 break
347 }
348 }
349 }
350
351 if foundChildDevice != nil {
352 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
353 return foundChildDevice, nil
354 }
355
356 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
357 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
358}
359
khenaidoo297cd252019-02-07 22:10:23 -0500360func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400361 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500362 return exist
363}
364
khenaidoo19d7b632018-10-30 10:49:50 -0400365func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400366 dMgr.lockRootDeviceMap.RLock()
367 defer dMgr.lockRootDeviceMap.RUnlock()
368 if exist := dMgr.rootDevices[id]; exist {
369 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400370 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400371 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400372}
373
Stephane Barbarieaa467942019-02-06 14:09:44 -0500374// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400375func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400376 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400377 result := &voltha.Devices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400378 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500379 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500380 // If device is not in memory then set it up
381 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400382 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400383 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Scott Baker80678602019-11-14 16:57:36 -0800384 if _, err := agent.start(nil, nil); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500385 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
386 agent.stop(nil)
387 } else {
388 dMgr.addDeviceAgentToMap(agent)
389 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500390 }
391 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400392 }
393 }
khenaidoo6d62c002019-05-15 21:57:03 -0400394 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400395 return result, nil
396}
397
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530398//isParentDeviceExist checks whether device is already preprovisioned.
399func (dMgr *DeviceManager) isParentDeviceExist(newDevice *voltha.Device) bool {
400 hostPort := newDevice.GetHostAndPort()
401 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
402 for _, device := range devices.([]interface{}) {
403 if !device.(*voltha.Device).Root {
404 continue
405 }
406 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() {
407 return true
408 }
409 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress {
410 return true
411 }
412 }
413 }
414 return false
415}
416
khenaidoo6d62c002019-05-15 21:57:03 -0400417//getDeviceFromModelretrieves the device data from the model.
418func (dMgr *DeviceManager) getDeviceFromModel(deviceId string) (*voltha.Device, error) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400419 if device := dMgr.clusterDataProxy.Get(context.Background(), "/devices/"+deviceId, 0, false, ""); device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400420 if d, ok := device.(*voltha.Device); ok {
421 return d, nil
422 }
423 }
424 return nil, status.Error(codes.NotFound, deviceId)
425}
426
khenaidoo297cd252019-02-07 22:10:23 -0500427// loadDevice loads the deviceId in memory, if not present
428func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
khenaidoo297cd252019-02-07 22:10:23 -0500429 if deviceId == "" {
430 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
431 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400432 var err error
433 var device *voltha.Device
434 dMgr.devicesLoadingLock.Lock()
435 if _, exist := dMgr.deviceLoadingInProgress[deviceId]; !exist {
436 if !dMgr.IsDeviceInCache(deviceId) {
437 dMgr.deviceLoadingInProgress[deviceId] = []chan int{make(chan int, 1)}
438 dMgr.devicesLoadingLock.Unlock()
439 // Proceed with the loading only if the device exist in the Model (could have been deleted)
440 if device, err = dMgr.getDeviceFromModel(deviceId); err == nil {
441 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
442 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Scott Baker80678602019-11-14 16:57:36 -0800443 if _, err = agent.start(nil, nil); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400444 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceId, "error": err})
445 agent.stop(nil)
446 } else {
447 dMgr.addDeviceAgentToMap(agent)
448 }
449 } else {
450 log.Debugw("Device not in model", log.Fields{"deviceId": deviceId})
khenaidoo6d62c002019-05-15 21:57:03 -0400451 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400452 // announce completion of task to any number of waiting channels
453 dMgr.devicesLoadingLock.Lock()
454 if v, ok := dMgr.deviceLoadingInProgress[deviceId]; ok {
455 for _, ch := range v {
456 close(ch)
457 }
458 delete(dMgr.deviceLoadingInProgress, deviceId)
459 }
460 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400461 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400462 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500463 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400464 } else {
465 ch := make(chan int, 1)
466 dMgr.deviceLoadingInProgress[deviceId] = append(dMgr.deviceLoadingInProgress[deviceId], ch)
467 dMgr.devicesLoadingLock.Unlock()
468 // Wait for the channel to be closed, implying the process loading this device is done.
469 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500470 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400471 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
472 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500473 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400474 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceId)
khenaidoo297cd252019-02-07 22:10:23 -0500475}
476
477// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
478func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
479 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
480 if device.Root {
481 // Scenario A
482 if device.ParentId != "" {
483 // Load logical device if needed.
484 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
485 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
486 }
487 } else {
488 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
489 }
490 // Load all child devices, if needed
491 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
492 for _, childDeviceId := range childDeviceIds {
493 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400494 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500495 return err
496 }
497 }
498 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
499 } else {
500 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
501 }
502 }
503 return nil
504}
505
506// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
507// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
508// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
509// and the proceed with the request.
510func (dMgr *DeviceManager) load(deviceId string) error {
511 log.Debug("load...")
512 // First load the device - this may fail in case the device was deleted intentionally by the other core
513 var dAgent *DeviceAgent
514 var err error
515 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500516 return err
517 }
518 // Get the loaded device details
519 var device *voltha.Device
520 if device, err = dAgent.getDevice(); err != nil {
521 return err
522 }
523
524 // If the device is in Pre-provisioning or deleted state stop here
525 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
526 return nil
527 }
528
529 // Now we face two scenarios
530 if device.Root {
531 // Load all children as well as the parent of this device (logical_device)
532 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
533 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
534 return err
535 }
536 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
537 } else {
538 // Scenario B - use the parentId of that device (root device) to trigger the loading
539 if device.ParentId != "" {
540 return dMgr.load(device.ParentId)
541 }
542 }
543 return nil
544}
545
khenaidoo7ccedd52018-12-14 16:48:54 -0500546// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
547func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
548 log.Debug("ListDeviceIDs")
549 // Report only device IDs that are in the device agent map
550 return dMgr.listDeviceIdsFromMap(), nil
551}
552
khenaidoo4c9e5592019-09-09 16:20:41 -0400553//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
554//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500555func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400556 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500557 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400558 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500559 toReconcile := len(ids.Items)
560 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400561 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500562 for _, id := range ids.Items {
khenaidoo4c9e5592019-09-09 16:20:41 -0400563 if err = dMgr.load(id.Id); err != nil {
564 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
565 } else {
566 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500567 }
568 }
569 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400570 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500571 }
572 } else {
573 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
574 }
575 sendResponse(ctx, ch, res)
576}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500577
khenaidooba6b6c42019-08-02 09:11:56 -0400578// isOkToReconcile validates whether a device is in the correct status to be reconciled
579func isOkToReconcile(device *voltha.Device) bool {
580 if device == nil {
581 return false
582 }
583 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
584}
585
586// adapterRestarted is invoked whenever an adapter is restarted
587func (dMgr *DeviceManager) adapterRestarted(adapter *voltha.Adapter) error {
588 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
589
590 // Let's reconcile the device managed by this Core only
591 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
592 if len(rootDeviceIds) == 0 {
593 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
594 return nil
595 }
596
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500597 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400598 for _, rootDeviceId := range rootDeviceIds {
599 if rootDevice, _ := dMgr.getDeviceFromModel(rootDeviceId); rootDevice != nil {
600 if rootDevice.Adapter == adapter.Id {
601 if isOkToReconcile(rootDevice) {
602 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500603 responses = append(responses, dMgr.sendReconcileDeviceRequest(rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400604 } else {
605 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
606 }
607 } else { // Should we be reconciling the root's children instead?
608 childManagedByAdapter:
609 for _, port := range rootDevice.Ports {
610 for _, peer := range port.Peers {
611 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
612 if childDevice.Adapter == adapter.Id {
613 if isOkToReconcile(childDevice) {
614 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500615 responses = append(responses, dMgr.sendReconcileDeviceRequest(childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400616 } else {
617 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
618 }
619 } else {
620 // All child devices under a parent device are typically managed by the same adapter type.
621 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
622 break childManagedByAdapter
623 }
624 }
625 }
626 }
627 }
628 }
629 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500630 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400631 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500632 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400633 return status.Errorf(codes.Aborted, "errors-%s", res)
634 }
635 } else {
636 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
637 }
638 return nil
639}
640
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500641func (dMgr *DeviceManager) sendReconcileDeviceRequest(device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400642 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
643 // point of creating a device agent (if the device is not being managed by this Core) before sending the request
644 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to teh adapter via
645 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500646 response := utils.NewResponse()
khenaidooba6b6c42019-08-02 09:11:56 -0400647 go func(device *voltha.Device) {
648 if err := dMgr.adapterProxy.ReconcileDevice(context.Background(), device); err != nil {
649 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500650 response.Error(status.Errorf(codes.Internal, "device: %s", device.Id))
khenaidooba6b6c42019-08-02 09:11:56 -0400651 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500652 response.Done()
khenaidooba6b6c42019-08-02 09:11:56 -0400653 }(device)
654
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500655 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400656}
657
658func (dMgr *DeviceManager) reconcileChildDevices(parentDeviceId string) error {
659 if parentDevice, _ := dMgr.getDeviceFromModel(parentDeviceId); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500660 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400661 for _, port := range parentDevice.Ports {
662 for _, peer := range port.Peers {
663 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500664 responses = append(responses, dMgr.sendReconcileDeviceRequest(childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400665 }
666 }
667 }
668 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500669 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400670 return status.Errorf(codes.Aborted, "errors-%s", res)
671 }
672 }
673 return nil
674}
675
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700676func (dMgr *DeviceManager) updateDeviceUsingAdapterData(device *voltha.Device) error {
677 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400678 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700679 return agent.updateDeviceUsingAdapterData(device)
khenaidoob9203542018-09-17 22:56:37 -0400680 }
681 return status.Errorf(codes.NotFound, "%s", device.Id)
682}
683
684func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
685 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400686 if err := agent.addPort(port); err != nil {
687 return err
688 }
689 // Setup peer ports
690 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
691 for _, peerPort := range port.Peers {
692 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
693 if err := agent.addPeerPort(meAsPeer); err != nil {
694 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
695 return err
696 }
697 }
698 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400699 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
700 // then a logical port will be added to the logical device and the device graph generated. If the port is a
701 // PON port then only the device graph will be generated.
702 if device, err := dMgr.GetDevice(deviceId); err == nil {
703 go dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
704 } else {
705 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
706 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400707 }
khenaidoo92e62c52018-10-03 14:02:54 -0400708 return nil
709 } else {
710 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400711 }
khenaidoob9203542018-09-17 22:56:37 -0400712}
713
khenaidoo0a822f92019-05-08 15:15:57 -0400714func (dMgr *DeviceManager) deletePeerPorts(fromDeviceId string, deviceId string) error {
715 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceId, "deviceid": deviceId})
716 if agent := dMgr.getDeviceAgent(fromDeviceId); agent != nil {
717 return agent.deletePeerPorts(deviceId)
718 }
719 return status.Errorf(codes.NotFound, "%s", deviceId)
720}
721
Manikkaraj kb1a10922019-07-29 12:10:34 -0400722func (dMgr *DeviceManager) addFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
723 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceId, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -0400724 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400725 return agent.addFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400726 }
727 return status.Errorf(codes.NotFound, "%s", deviceId)
728}
729
Manikkaraj kb1a10922019-07-29 12:10:34 -0400730func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400731 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceId})
732 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400733 return agent.deleteFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400734 }
735 return status.Errorf(codes.NotFound, "%s", deviceId)
736}
737
Manikkaraj kb1a10922019-07-29 12:10:34 -0400738func (dMgr *DeviceManager) updateFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400739 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceId})
740 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400741 return agent.updateFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400742 }
743 return status.Errorf(codes.NotFound, "%s", deviceId)
744}
745
khenaidoob3127472019-07-24 21:04:55 -0400746// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
747// following a user action
748func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
749 var res interface{}
750 if pmConfigs.Id == "" {
751 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
752 } else if agent := dMgr.getDeviceAgent(pmConfigs.Id); agent != nil {
753 res = agent.updatePmConfigs(ctx, pmConfigs)
754 } else {
755 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
756 }
757 sendResponse(ctx, ch, res)
758}
759
760// initPmConfigs initialize the pm configs as defined by the adapter.
761func (dMgr *DeviceManager) initPmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
762 if pmConfigs.Id == "" {
763 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
764 }
khenaidoob9203542018-09-17 22:56:37 -0400765 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400766 return agent.initPmConfigs(pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400767 }
768 return status.Errorf(codes.NotFound, "%s", deviceId)
769}
770
khenaidoob3127472019-07-24 21:04:55 -0400771func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceId string) (*voltha.PmConfigs, error) {
772 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
773 return agent.listPmConfigs(ctx)
774 }
775 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
776}
777
khenaidoo79232702018-12-04 11:00:41 -0500778func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400779 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400780 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
781 return agent.getSwitchCapability(ctx)
782 }
783 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
784}
785
khenaidoo92e62c52018-10-03 14:02:54 -0400786func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
787 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400788 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400789 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400790 }
791 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
792}
793
khenaidoo79232702018-12-04 11:00:41 -0500794func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400795 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400796 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
797 return agent.getPortCapability(ctx, portNo)
798 }
799 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
800}
801
khenaidoo92e62c52018-10-03 14:02:54 -0400802func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
803 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400804 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400805 return agent.updateDeviceStatus(operStatus, connStatus)
806 }
807 return status.Errorf(codes.NotFound, "%s", deviceId)
808}
809
khenaidoo4d4802d2018-10-04 21:59:49 -0400810func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
811 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
812 var parentDevice *voltha.Device
813 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400814 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400815 return status.Errorf(codes.Aborted, "%s", err.Error())
816 }
817 var childDeviceIds []string
818 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
819 return status.Errorf(codes.Aborted, "%s", err.Error())
820 }
821 if len(childDeviceIds) == 0 {
822 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
823 }
824 for _, childDeviceId := range childDeviceIds {
825 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
826 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
827 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
828 }
829 }
830 }
831 return nil
832}
833
khenaidoo92e62c52018-10-03 14:02:54 -0400834func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
835 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
836 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo171b98e2019-10-31 11:48:15 -0400837 if err := agent.updatePortState(portType, portNo, operStatus); err != nil {
838 log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceId, "portNo": portNo, "error": err})
839 return err
840 }
841 // Notify the logical device manager to change the port state
842 go dMgr.logicalDeviceMgr.updatePortState(deviceId, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400843 }
844 return status.Errorf(codes.NotFound, "%s", deviceId)
845}
846
khenaidoo0a822f92019-05-08 15:15:57 -0400847func (dMgr *DeviceManager) deleteAllPorts(deviceId string) error {
848 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceId})
849 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
850 if err := agent.deleteAllPorts(); err != nil {
851 return err
852 }
853 // Notify the logical device manager to remove all logical ports, if needed.
854 // At this stage the device itself may gave been deleted already at a deleteAllPorts
855 // typically is part of a device deletion phase.
856 if device, err := dMgr.GetDevice(deviceId); err == nil {
857 go dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
858 } else {
859 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
860 return err
861 }
862 return nil
863 }
864 return status.Errorf(codes.NotFound, "%s", deviceId)
865}
866
khenaidoo3ab34882019-05-02 21:33:30 -0400867//updatePortsState updates all ports on the device
868func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
869 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
870
871 var adminState voltha.AdminState_AdminState
872 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
873 switch state {
874 case voltha.OperStatus_ACTIVE:
875 adminState = voltha.AdminState_ENABLED
876 if err := agent.enablePorts(); err != nil {
877 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
878 return err
879 }
880 case voltha.OperStatus_UNKNOWN:
881 adminState = voltha.AdminState_DISABLED
882 if err := agent.disablePorts(); err != nil {
883 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
884 return err
885 }
886 default:
887 return status.Error(codes.Unimplemented, "state-change-not-implemented")
888 }
889 // Notify the logical device about the state change
890 if device, err := dMgr.GetDevice(deviceId); err != nil {
891 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
892 return err
893 } else {
894 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
895 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
896 return err
897 }
898 return nil
899 }
900 }
901 return status.Errorf(codes.NotFound, "%s", deviceId)
902}
903
Matt Jeanneret4e241952019-02-28 11:16:04 -0500904func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700905 channelId int64, vendorId string, serialNumber string, onuId int64) (*voltha.Device, error) {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700906 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId, "parentPortNo": parentPortNo, "deviceType": deviceType, "channelId": channelId, "vendorId": vendorId, "serialNumber": serialNumber, "onuId": onuId})
907
908 if deviceType == "" && vendorId != "" {
909 log.Debug("device-type-is-nil-fetching-device-type")
910 if deviceTypesIf := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, ""); deviceTypesIf != nil {
911 OLoop:
912 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
913 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
914 for _, v := range dType.VendorIds {
915 if v == vendorId {
916 deviceType = dType.Adapter
917 break OLoop
918 }
919 }
920 }
921 }
922 }
923 }
924 //if no match found for the vendorid,report adapter with the custom error message
925 if deviceType == "" {
926 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorId})
927 return nil, status.Errorf(codes.NotFound, "%s", vendorId)
928 }
khenaidoob9203542018-09-17 22:56:37 -0400929
930 // Create the ONU device
931 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400932 childDevice.Type = deviceType
933 childDevice.ParentId = parentDeviceId
934 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500935 childDevice.VendorId = vendorId
936 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400937 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400938
939 //Get parent device type
940 parent, err := dMgr.GetDevice(parentDeviceId)
941 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500942 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700943 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400944 }
945
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700946 if device, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500947 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700948 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500949 }
950
951 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400952
953 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400954 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400955 dMgr.addDeviceAgentToMap(agent)
Scott Baker80678602019-11-14 16:57:36 -0800956 childDevice, err = agent.start(nil, childDevice)
957 if err != nil {
958 log.Error("error-starting-child")
959 return nil, err
960 }
khenaidoob9203542018-09-17 22:56:37 -0400961
khenaidoo09771ef2019-10-11 14:25:02 -0400962 // Since this Core has handled this request then it therefore owns this child device. Set the
963 // ownership of this device to this Core
964 dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: agent.deviceId})
965
khenaidoob9203542018-09-17 22:56:37 -0400966 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400967 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500968 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400969 }
970
khenaidoo79232702018-12-04 11:00:41 -0500971 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500972 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500973
Scott Baker80678602019-11-14 16:57:36 -0800974 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -0400975}
976
977func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
978 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400979 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
980 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500981 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400982 return nil
khenaidoob9203542018-09-17 22:56:37 -0400983 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400984 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -0400985 for _, handler := range handlers {
986 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
987 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400988 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400989 return err
990 }
991 }
khenaidoob9203542018-09-17 22:56:37 -0400992 return nil
993}
994
khenaidoofdbad6e2018-11-06 22:26:38 -0500995func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
996 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
997 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
998 return agent.packetOut(outPort, packet)
999 }
1000 return status.Errorf(codes.NotFound, "%s", deviceId)
1001}
1002
khenaidoo297cd252019-02-07 22:10:23 -05001003func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -05001004 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
1005 // Get the logical device Id based on the deviceId
1006 var device *voltha.Device
1007 var err error
1008 if device, err = dMgr.GetDevice(deviceId); err != nil {
1009 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
1010 return err
1011 }
khenaidoo43c82122018-11-22 18:38:28 -05001012 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -05001013 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
1014 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
1015 }
1016
khenaidoo297cd252019-02-07 22:10:23 -05001017 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001018 return err
1019 }
1020 return nil
1021}
1022
khenaidooad06fd72019-10-28 12:26:05 -04001023func (dMgr *DeviceManager) setParentId(device *voltha.Device, parentId string) error {
1024 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentId})
1025 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
1026 return agent.setParentId(device, parentId)
1027 }
1028 return status.Errorf(codes.NotFound, "%s", device.Id)
1029}
1030
khenaidoo0a822f92019-05-08 15:15:57 -04001031func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
1032 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001033 // Verify whether the logical device has already been created
1034 if cDevice.ParentId != "" {
1035 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1036 return nil
1037 }
khenaidoob9203542018-09-17 22:56:37 -04001038 var err error
khenaidooad06fd72019-10-28 12:26:05 -04001039 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001040 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1041 return err
1042 }
khenaidoob9203542018-09-17 22:56:37 -04001043 return nil
1044}
1045
khenaidoo0a822f92019-05-08 15:15:57 -04001046func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
1047 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001048 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001049 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001050 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1051 return err
1052 }
1053 // Remove the logical device Id from the parent device
1054 logicalId := ""
1055 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
1056 return nil
1057}
1058
khenaidoo0a822f92019-05-08 15:15:57 -04001059func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001060 log.Info("deleteLogicalPort")
1061 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001062 // Get the logical port associated with this device
1063 var lPortId *voltha.LogicalPortId
1064 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001065 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001066 return err
1067 }
1068 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
1069 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001070 return err
1071 }
khenaidoo92e62c52018-10-03 14:02:54 -04001072 return nil
1073}
1074
khenaidoo0a822f92019-05-08 15:15:57 -04001075func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1076 log.Info("deleteLogicalPorts")
1077 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); 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}