blob: f5b017c6f617721ffa9848f20409160f954d361f [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"
21 "github.com/opencord/voltha-go/common/log"
22 "github.com/opencord/voltha-go/db/model"
23 "github.com/opencord/voltha-go/kafka"
khenaidoo3d3b8c22019-05-22 18:10:39 -040024 "github.com/opencord/voltha-go/rw_core/utils"
William Kurkiandaa6bb22019-03-07 12:26:28 -050025 ic "github.com/opencord/voltha-protos/go/inter_container"
26 ofp "github.com/opencord/voltha-protos/go/openflow_13"
27 "github.com/opencord/voltha-protos/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040028 "google.golang.org/grpc/codes"
29 "google.golang.org/grpc/status"
30 "reflect"
31 "runtime"
32 "sync"
33)
34
35type DeviceManager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040036 deviceAgents sync.Map
37 rootDevices map[string]bool
38 lockRootDeviceMap sync.RWMutex
39 core *Core
40 adapterProxy *AdapterProxy
41 adapterMgr *AdapterManager
42 logicalDeviceMgr *LogicalDeviceManager
43 kafkaICProxy *kafka.InterContainerProxy
44 stateTransitions *TransitionMap
45 clusterDataProxy *model.Proxy
46 coreInstanceId string
47 exitChannel chan int
48 defaultTimeout int64
49 devicesLoadingLock sync.RWMutex
50 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040051}
52
Richard Jankowski199fd862019-03-18 14:49:51 -040053func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040054 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040055 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040056 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040057 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040058 deviceMgr.kafkaICProxy = core.kmp
Kent Hagermana6d0c362019-07-30 12:50:21 -040059 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic)
Richard Jankowski199fd862019-03-18 14:49:51 -040060 deviceMgr.coreInstanceId = core.instanceId
61 deviceMgr.clusterDataProxy = core.clusterDataProxy
62 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040063 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
64 deviceMgr.defaultTimeout = core.config.DefaultCoreTimeout
khenaidoo4c9e5592019-09-09 16:20:41 -040065 deviceMgr.devicesLoadingLock = sync.RWMutex{}
66 deviceMgr.deviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040067 return &deviceMgr
68}
69
khenaidoo4d4802d2018-10-04 21:59:49 -040070func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040071 log.Info("starting-device-manager")
72 dMgr.logicalDeviceMgr = logicalDeviceMgr
73 dMgr.stateTransitions = NewTransitionMap(dMgr)
74 log.Info("device-manager-started")
75}
76
khenaidoo4d4802d2018-10-04 21:59:49 -040077func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040078 log.Info("stopping-device-manager")
79 dMgr.exitChannel <- 1
80 log.Info("device-manager-stopped")
81}
82
83func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
84 if ctx.Err() == nil {
85 // Returned response only of the ctx has not been cancelled/timeout/etc
86 // Channel is automatically closed when a context is Done
87 ch <- result
88 log.Debugw("sendResponse", log.Fields{"result": result})
89 } else {
90 // Should the transaction be reverted back?
91 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
92 }
93}
94
95func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040096 if _, exist := dMgr.deviceAgents.Load(agent.deviceId); !exist {
97 dMgr.deviceAgents.Store(agent.deviceId, agent)
khenaidoob9203542018-09-17 22:56:37 -040098 }
khenaidoo2c6a0992019-04-29 13:46:56 -040099 dMgr.lockRootDeviceMap.Lock()
100 defer dMgr.lockRootDeviceMap.Unlock()
101 dMgr.rootDevices[agent.deviceId] = agent.isRootdevice
102
khenaidoob9203542018-09-17 22:56:37 -0400103}
104
khenaidoo4c9e5592019-09-09 16:20:41 -0400105func (dMgr *DeviceManager) deleteDeviceAgentFromMap(agent *DeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400106 dMgr.deviceAgents.Delete(agent.deviceId)
khenaidoo2c6a0992019-04-29 13:46:56 -0400107 dMgr.lockRootDeviceMap.Lock()
108 defer dMgr.lockRootDeviceMap.Unlock()
109 delete(dMgr.rootDevices, agent.deviceId)
khenaidoo4d4802d2018-10-04 21:59:49 -0400110}
111
khenaidoo297cd252019-02-07 22:10:23 -0500112// 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 -0400113func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400114 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
115 return agent.(*DeviceAgent)
khenaidoo297cd252019-02-07 22:10:23 -0500116 } else {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400117 // Try to load into memory - loading will also create the device agent and set the device ownership
khenaidoo297cd252019-02-07 22:10:23 -0500118 if err := dMgr.load(deviceId); err == nil {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400119 if agent, ok = dMgr.deviceAgents.Load(deviceId); !ok {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400120 return nil
121 } else {
122 // Register this device for ownership tracking
123 go dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: deviceId})
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400124 return agent.(*DeviceAgent)
khenaidoo297cd252019-02-07 22:10:23 -0500125 }
khenaidoo3d3b8c22019-05-22 18:10:39 -0400126 } else {
127 //TODO: Change the return params to return an error as well
128 log.Errorw("loading-device-failed", log.Fields{"deviceId": deviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500129 }
khenaidoob9203542018-09-17 22:56:37 -0400130 }
131 return nil
132}
133
khenaidoo297cd252019-02-07 22:10:23 -0500134// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500135func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500136 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400137
138 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
139 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
140 return true
141 })
142
khenaidoo7ccedd52018-12-14 16:48:54 -0500143 return result
144}
145
khenaidoob9203542018-09-17 22:56:37 -0400146func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400147 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400148
khenaidoo5e677ae2019-02-28 17:26:29 -0500149 // Ensure this device is set as root
150 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400151 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400152 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400153 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500154 agent.start(ctx, false)
khenaidoob9203542018-09-17 22:56:37 -0400155
khenaidoo92e62c52018-10-03 14:02:54 -0400156 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400157}
158
159func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400160 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400161 var res interface{}
162 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
163 res = agent.enableDevice(ctx)
164 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400165 }
166
167 sendResponse(ctx, ch, res)
168}
169
khenaidoo92e62c52018-10-03 14:02:54 -0400170func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
171 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400172 var res interface{}
173 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
174 res = agent.disableDevice(ctx)
175 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400176 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400177 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400178 }
khenaidoo92e62c52018-10-03 14:02:54 -0400179
180 sendResponse(ctx, ch, res)
181}
182
khenaidoo4d4802d2018-10-04 21:59:49 -0400183func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
184 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
185 var res interface{}
186 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
187 res = agent.rebootDevice(ctx)
188 log.Debugw("rebootDevice-result", log.Fields{"result": res})
189 } else {
190 res = status.Errorf(codes.NotFound, "%s", id.Id)
191 }
192 sendResponse(ctx, ch, res)
193}
194
195func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
196 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
197 var res interface{}
198 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
199 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400200 log.Debugw("deleteDevice-result", log.Fields{"result": res})
201 } else {
202 res = status.Errorf(codes.NotFound, "%s", id.Id)
203 }
204 sendResponse(ctx, ch, res)
205}
206
khenaidoo6d62c002019-05-15 21:57:03 -0400207// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
208// This function is called only in the Core that does not own this device. In the Core that owns this device then a
209// deletion deletion also includes removal of any reference of this device.
210func (dMgr *DeviceManager) stopManagingDevice(id string) {
211 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
212 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
213 if root, _ := dMgr.IsRootDevice(id); root == true {
214 // stop managing the logical device
215 ldeviceId := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceId(id)
216 if ldeviceId != "" { // Can happen if logical device agent was already stopped
217 dMgr.core.deviceOwnership.AbandonDevice(ldeviceId)
218 }
219 // stop managing the child devices
220 childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentId(id)
221 for _, cId := range childDeviceIds {
222 dMgr.stopManagingDevice(cId)
223 }
224 }
225 if agent := dMgr.getDeviceAgent(id); agent != nil {
226 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -0400227 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400228 // Abandon the device ownership
229 dMgr.core.deviceOwnership.AbandonDevice(id)
230 }
231 }
232}
233
khenaidoo0a822f92019-05-08 15:15:57 -0400234func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
235 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400236 dMgr.stopManagingDevice(cDevice.Id)
237 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400238}
239
khenaidoo297cd252019-02-07 22:10:23 -0500240// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400241func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
242 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400243 if agent := dMgr.getDeviceAgent(id); agent != nil {
244 return agent.getDevice()
245 }
246 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400247}
248
Matt Jeanneret4e241952019-02-28 11:16:04 -0500249func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
Matt Jeanneret0c5088c2019-04-22 16:16:19 -0400250 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber,
251 "parentPortNo": parentPortNo, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500252
253 var parentDevice *voltha.Device
254 var err error
255 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
256 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
257 }
258 var childDeviceIds []string
259 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
260 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
261 }
262 if len(childDeviceIds) == 0 {
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700263 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500264 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
265 }
266
267 var foundChildDevice *voltha.Device
268 for _, childDeviceId := range childDeviceIds {
269 found := false
270 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
271
272 foundOnuId := false
273 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
274 if searchDevice.ParentPortNo == uint32(parentPortNo) {
275 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
276 foundOnuId = true
277 }
278 }
279
280 foundSerialNumber := false
281 if searchDevice.SerialNumber == serialNumber {
282 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
283 foundSerialNumber = true
284 }
285
286 // if both onuId and serialNumber are provided both must be true for the device to be found
287 // otherwise whichever one found a match is good enough
288 if onuId > 0 && serialNumber != "" {
289 found = foundOnuId && foundSerialNumber
290 } else {
291 found = foundOnuId || foundSerialNumber
292 }
293
294 if found == true {
295 foundChildDevice = searchDevice
296 break
297 }
298 }
299 }
300
301 if foundChildDevice != nil {
302 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
303 return foundChildDevice, nil
304 }
305
306 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
307 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
308 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
309}
310
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500311func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
312 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
313
314 var parentDevice *voltha.Device
315 var err error
316 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
317 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
318 }
319 var childDeviceIds []string
320 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
321 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
322 }
323 if len(childDeviceIds) == 0 {
324 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
325 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
326 }
327
328 var foundChildDevice *voltha.Device
329 for _, childDeviceId := range childDeviceIds {
330 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
331 if searchDevice.ProxyAddress == proxyAddress {
332 foundChildDevice = searchDevice
333 break
334 }
335 }
336 }
337
338 if foundChildDevice != nil {
339 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
340 return foundChildDevice, nil
341 }
342
343 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
344 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
345}
346
khenaidoo297cd252019-02-07 22:10:23 -0500347func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400348 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500349 return exist
350}
351
khenaidoo19d7b632018-10-30 10:49:50 -0400352func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400353 dMgr.lockRootDeviceMap.RLock()
354 defer dMgr.lockRootDeviceMap.RUnlock()
355 if exist := dMgr.rootDevices[id]; exist {
356 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400357 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400358 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400359}
360
Stephane Barbarieaa467942019-02-06 14:09:44 -0500361// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400362func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400363 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400364 result := &voltha.Devices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400365 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500366 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500367 // If device is not in memory then set it up
368 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400369 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400370 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500371 if err := agent.start(nil, true); err != nil {
372 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
373 agent.stop(nil)
374 } else {
375 dMgr.addDeviceAgentToMap(agent)
376 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500377 }
378 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400379 }
380 }
khenaidoo6d62c002019-05-15 21:57:03 -0400381 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400382 return result, nil
383}
384
khenaidoo6d62c002019-05-15 21:57:03 -0400385//getDeviceFromModelretrieves the device data from the model.
386func (dMgr *DeviceManager) getDeviceFromModel(deviceId string) (*voltha.Device, error) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400387 if device := dMgr.clusterDataProxy.Get(context.Background(), "/devices/"+deviceId, 0, false, ""); device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400388 if d, ok := device.(*voltha.Device); ok {
389 return d, nil
390 }
391 }
392 return nil, status.Error(codes.NotFound, deviceId)
393}
394
khenaidoo297cd252019-02-07 22:10:23 -0500395// loadDevice loads the deviceId in memory, if not present
396func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
khenaidoo297cd252019-02-07 22:10:23 -0500397 if deviceId == "" {
398 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
399 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400400 var err error
401 var device *voltha.Device
402 dMgr.devicesLoadingLock.Lock()
403 if _, exist := dMgr.deviceLoadingInProgress[deviceId]; !exist {
404 if !dMgr.IsDeviceInCache(deviceId) {
405 dMgr.deviceLoadingInProgress[deviceId] = []chan int{make(chan int, 1)}
406 dMgr.devicesLoadingLock.Unlock()
407 // Proceed with the loading only if the device exist in the Model (could have been deleted)
408 if device, err = dMgr.getDeviceFromModel(deviceId); err == nil {
409 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
410 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
411 if err = agent.start(nil, true); err != nil {
412 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceId, "error": err})
413 agent.stop(nil)
414 } else {
415 dMgr.addDeviceAgentToMap(agent)
416 }
417 } else {
418 log.Debugw("Device not in model", log.Fields{"deviceId": deviceId})
khenaidoo6d62c002019-05-15 21:57:03 -0400419 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400420 // announce completion of task to any number of waiting channels
421 dMgr.devicesLoadingLock.Lock()
422 if v, ok := dMgr.deviceLoadingInProgress[deviceId]; ok {
423 for _, ch := range v {
424 close(ch)
425 }
426 delete(dMgr.deviceLoadingInProgress, deviceId)
427 }
428 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400429 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400430 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500431 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400432 } else {
433 ch := make(chan int, 1)
434 dMgr.deviceLoadingInProgress[deviceId] = append(dMgr.deviceLoadingInProgress[deviceId], ch)
435 dMgr.devicesLoadingLock.Unlock()
436 // Wait for the channel to be closed, implying the process loading this device is done.
437 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500438 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400439 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
440 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500441 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400442 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceId)
khenaidoo297cd252019-02-07 22:10:23 -0500443}
444
445// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
446func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
447 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
448 if device.Root {
449 // Scenario A
450 if device.ParentId != "" {
451 // Load logical device if needed.
452 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
453 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
454 }
455 } else {
456 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
457 }
458 // Load all child devices, if needed
459 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
460 for _, childDeviceId := range childDeviceIds {
461 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400462 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500463 return err
464 }
465 }
466 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
467 } else {
468 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
469 }
470 }
471 return nil
472}
473
474// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
475// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
476// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
477// and the proceed with the request.
478func (dMgr *DeviceManager) load(deviceId string) error {
479 log.Debug("load...")
480 // First load the device - this may fail in case the device was deleted intentionally by the other core
481 var dAgent *DeviceAgent
482 var err error
483 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500484 return err
485 }
486 // Get the loaded device details
487 var device *voltha.Device
488 if device, err = dAgent.getDevice(); err != nil {
489 return err
490 }
491
492 // If the device is in Pre-provisioning or deleted state stop here
493 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
494 return nil
495 }
496
497 // Now we face two scenarios
498 if device.Root {
499 // Load all children as well as the parent of this device (logical_device)
500 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
501 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
502 return err
503 }
504 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
505 } else {
506 // Scenario B - use the parentId of that device (root device) to trigger the loading
507 if device.ParentId != "" {
508 return dMgr.load(device.ParentId)
509 }
510 }
511 return nil
512}
513
khenaidoo7ccedd52018-12-14 16:48:54 -0500514// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
515func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
516 log.Debug("ListDeviceIDs")
517 // Report only device IDs that are in the device agent map
518 return dMgr.listDeviceIdsFromMap(), nil
519}
520
khenaidoo4c9e5592019-09-09 16:20:41 -0400521//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
522//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500523func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400524 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500525 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400526 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500527 toReconcile := len(ids.Items)
528 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400529 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500530 for _, id := range ids.Items {
khenaidoo4c9e5592019-09-09 16:20:41 -0400531 if err = dMgr.load(id.Id); err != nil {
532 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
533 } else {
534 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500535 }
536 }
537 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400538 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500539 }
540 } else {
541 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
542 }
543 sendResponse(ctx, ch, res)
544}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500545
khenaidooba6b6c42019-08-02 09:11:56 -0400546// isOkToReconcile validates whether a device is in the correct status to be reconciled
547func isOkToReconcile(device *voltha.Device) bool {
548 if device == nil {
549 return false
550 }
551 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
552}
553
554// adapterRestarted is invoked whenever an adapter is restarted
555func (dMgr *DeviceManager) adapterRestarted(adapter *voltha.Adapter) error {
556 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
557
558 // Let's reconcile the device managed by this Core only
559 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
560 if len(rootDeviceIds) == 0 {
561 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
562 return nil
563 }
564
565 chnlsList := make([]chan interface{}, 0)
566 for _, rootDeviceId := range rootDeviceIds {
567 if rootDevice, _ := dMgr.getDeviceFromModel(rootDeviceId); rootDevice != nil {
568 if rootDevice.Adapter == adapter.Id {
569 if isOkToReconcile(rootDevice) {
570 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
571 chnlsList = dMgr.sendReconcileDeviceRequest(rootDevice, chnlsList)
572 } else {
573 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
574 }
575 } else { // Should we be reconciling the root's children instead?
576 childManagedByAdapter:
577 for _, port := range rootDevice.Ports {
578 for _, peer := range port.Peers {
579 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
580 if childDevice.Adapter == adapter.Id {
581 if isOkToReconcile(childDevice) {
582 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
583 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
584 } else {
585 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
586 }
587 } else {
588 // All child devices under a parent device are typically managed by the same adapter type.
589 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
590 break childManagedByAdapter
591 }
592 }
593 }
594 }
595 }
596 }
597 }
598 if len(chnlsList) > 0 {
599 // Wait for completion
600 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
601 return status.Errorf(codes.Aborted, "errors-%s", res)
602 }
603 } else {
604 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
605 }
606 return nil
607}
608
609func (dMgr *DeviceManager) sendReconcileDeviceRequest(device *voltha.Device, chnlsList []chan interface{}) []chan interface{} {
610 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
611 // point of creating a device agent (if the device is not being managed by this Core) before sending the request
612 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to teh adapter via
613 // the adapter_proxy.
614 ch := make(chan interface{})
615 chnlsList = append(chnlsList, ch)
616 go func(device *voltha.Device) {
617 if err := dMgr.adapterProxy.ReconcileDevice(context.Background(), device); err != nil {
618 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
619 ch <- status.Errorf(codes.Internal, "device: %s", device.Id)
620 }
621 ch <- nil
622 }(device)
623
624 return chnlsList
625}
626
627func (dMgr *DeviceManager) reconcileChildDevices(parentDeviceId string) error {
628 if parentDevice, _ := dMgr.getDeviceFromModel(parentDeviceId); parentDevice != nil {
629 chnlsList := make([]chan interface{}, 0)
630 for _, port := range parentDevice.Ports {
631 for _, peer := range port.Peers {
632 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
633 chnlsList = dMgr.sendReconcileDeviceRequest(childDevice, chnlsList)
634 }
635 }
636 }
637 // Wait for completion
638 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, chnlsList...); res != nil {
639 return status.Errorf(codes.Aborted, "errors-%s", res)
640 }
641 }
642 return nil
643}
644
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700645func (dMgr *DeviceManager) updateDeviceUsingAdapterData(device *voltha.Device) error {
646 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400647 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700648 return agent.updateDeviceUsingAdapterData(device)
khenaidoob9203542018-09-17 22:56:37 -0400649 }
650 return status.Errorf(codes.NotFound, "%s", device.Id)
651}
652
653func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
654 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400655 if err := agent.addPort(port); err != nil {
656 return err
657 }
658 // Setup peer ports
659 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
660 for _, peerPort := range port.Peers {
661 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
662 if err := agent.addPeerPort(meAsPeer); err != nil {
663 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
664 return err
665 }
666 }
667 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400668 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
669 // then a logical port will be added to the logical device and the device graph generated. If the port is a
670 // PON port then only the device graph will be generated.
671 if device, err := dMgr.GetDevice(deviceId); err == nil {
672 go dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
673 } else {
674 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
675 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400676 }
khenaidoo92e62c52018-10-03 14:02:54 -0400677 return nil
678 } else {
679 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400680 }
khenaidoob9203542018-09-17 22:56:37 -0400681}
682
khenaidoo0a822f92019-05-08 15:15:57 -0400683func (dMgr *DeviceManager) deletePeerPorts(fromDeviceId string, deviceId string) error {
684 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceId, "deviceid": deviceId})
685 if agent := dMgr.getDeviceAgent(fromDeviceId); agent != nil {
686 return agent.deletePeerPorts(deviceId)
687 }
688 return status.Errorf(codes.NotFound, "%s", deviceId)
689}
690
Manikkaraj kb1a10922019-07-29 12:10:34 -0400691func (dMgr *DeviceManager) addFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
692 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceId, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -0400693 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400694 return agent.addFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400695 }
696 return status.Errorf(codes.NotFound, "%s", deviceId)
697}
698
Manikkaraj kb1a10922019-07-29 12:10:34 -0400699func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400700 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceId})
701 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400702 return agent.deleteFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400703 }
704 return status.Errorf(codes.NotFound, "%s", deviceId)
705}
706
Manikkaraj kb1a10922019-07-29 12:10:34 -0400707func (dMgr *DeviceManager) updateFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -0400708 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceId})
709 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400710 return agent.updateFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400711 }
712 return status.Errorf(codes.NotFound, "%s", deviceId)
713}
714
khenaidoob3127472019-07-24 21:04:55 -0400715// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
716// following a user action
717func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
718 var res interface{}
719 if pmConfigs.Id == "" {
720 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
721 } else if agent := dMgr.getDeviceAgent(pmConfigs.Id); agent != nil {
722 res = agent.updatePmConfigs(ctx, pmConfigs)
723 } else {
724 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
725 }
726 sendResponse(ctx, ch, res)
727}
728
729// initPmConfigs initialize the pm configs as defined by the adapter.
730func (dMgr *DeviceManager) initPmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
731 if pmConfigs.Id == "" {
732 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
733 }
khenaidoob9203542018-09-17 22:56:37 -0400734 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400735 return agent.initPmConfigs(pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400736 }
737 return status.Errorf(codes.NotFound, "%s", deviceId)
738}
739
khenaidoob3127472019-07-24 21:04:55 -0400740func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceId string) (*voltha.PmConfigs, error) {
741 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
742 return agent.listPmConfigs(ctx)
743 }
744 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
745}
746
khenaidoo79232702018-12-04 11:00:41 -0500747func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400748 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400749 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
750 return agent.getSwitchCapability(ctx)
751 }
752 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
753}
754
khenaidoo92e62c52018-10-03 14:02:54 -0400755func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
756 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400757 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400758 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400759 }
760 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
761}
762
khenaidoo79232702018-12-04 11:00:41 -0500763func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400764 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400765 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
766 return agent.getPortCapability(ctx, portNo)
767 }
768 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
769}
770
khenaidoo92e62c52018-10-03 14:02:54 -0400771func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
772 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400773 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400774 return agent.updateDeviceStatus(operStatus, connStatus)
775 }
776 return status.Errorf(codes.NotFound, "%s", deviceId)
777}
778
khenaidoo4d4802d2018-10-04 21:59:49 -0400779func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
780 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
781 var parentDevice *voltha.Device
782 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400783 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400784 return status.Errorf(codes.Aborted, "%s", err.Error())
785 }
786 var childDeviceIds []string
787 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
788 return status.Errorf(codes.Aborted, "%s", err.Error())
789 }
790 if len(childDeviceIds) == 0 {
791 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
792 }
793 for _, childDeviceId := range childDeviceIds {
794 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
795 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
796 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
797 }
798 }
799 }
800 return nil
801}
802
khenaidoo92e62c52018-10-03 14:02:54 -0400803func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
804 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
805 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
806 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400807 }
808 return status.Errorf(codes.NotFound, "%s", deviceId)
809}
810
khenaidoo0a822f92019-05-08 15:15:57 -0400811func (dMgr *DeviceManager) deleteAllPorts(deviceId string) error {
812 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceId})
813 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
814 if err := agent.deleteAllPorts(); err != nil {
815 return err
816 }
817 // Notify the logical device manager to remove all logical ports, if needed.
818 // At this stage the device itself may gave been deleted already at a deleteAllPorts
819 // typically is part of a device deletion phase.
820 if device, err := dMgr.GetDevice(deviceId); err == nil {
821 go dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
822 } else {
823 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
824 return err
825 }
826 return nil
827 }
828 return status.Errorf(codes.NotFound, "%s", deviceId)
829}
830
khenaidoo3ab34882019-05-02 21:33:30 -0400831//updatePortsState updates all ports on the device
832func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
833 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
834
835 var adminState voltha.AdminState_AdminState
836 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
837 switch state {
838 case voltha.OperStatus_ACTIVE:
839 adminState = voltha.AdminState_ENABLED
840 if err := agent.enablePorts(); err != nil {
841 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
842 return err
843 }
844 case voltha.OperStatus_UNKNOWN:
845 adminState = voltha.AdminState_DISABLED
846 if err := agent.disablePorts(); err != nil {
847 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
848 return err
849 }
850 default:
851 return status.Error(codes.Unimplemented, "state-change-not-implemented")
852 }
853 // Notify the logical device about the state change
854 if device, err := dMgr.GetDevice(deviceId); err != nil {
855 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
856 return err
857 } else {
858 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
859 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
860 return err
861 }
862 return nil
863 }
864 }
865 return status.Errorf(codes.NotFound, "%s", deviceId)
866}
867
Matt Jeanneret4e241952019-02-28 11:16:04 -0500868func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700869 channelId int64, vendorId string, serialNumber string, onuId int64) (*voltha.Device, error) {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700870 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId, "parentPortNo": parentPortNo, "deviceType": deviceType, "channelId": channelId, "vendorId": vendorId, "serialNumber": serialNumber, "onuId": onuId})
871
872 if deviceType == "" && vendorId != "" {
873 log.Debug("device-type-is-nil-fetching-device-type")
874 if deviceTypesIf := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, ""); deviceTypesIf != nil {
875 OLoop:
876 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
877 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
878 for _, v := range dType.VendorIds {
879 if v == vendorId {
880 deviceType = dType.Adapter
881 break OLoop
882 }
883 }
884 }
885 }
886 }
887 }
888 //if no match found for the vendorid,report adapter with the custom error message
889 if deviceType == "" {
890 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorId})
891 return nil, status.Errorf(codes.NotFound, "%s", vendorId)
892 }
khenaidoob9203542018-09-17 22:56:37 -0400893
894 // Create the ONU device
895 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400896 childDevice.Type = deviceType
897 childDevice.ParentId = parentDeviceId
898 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500899 childDevice.VendorId = vendorId
900 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400901 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400902
903 //Get parent device type
904 parent, err := dMgr.GetDevice(parentDeviceId)
905 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500906 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700907 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400908 }
909
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700910 if device, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500911 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700912 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500913 }
914
915 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400916
917 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400918 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400919 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500920 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400921
922 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400923 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500924 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400925 }
926
khenaidoo79232702018-12-04 11:00:41 -0500927 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500928 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500929
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700930 return agent.lastData, nil
khenaidoob9203542018-09-17 22:56:37 -0400931}
932
933func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
934 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400935 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
936 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500937 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400938 return nil
khenaidoob9203542018-09-17 22:56:37 -0400939 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400940 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -0400941 for _, handler := range handlers {
942 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
943 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400944 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400945 return err
946 }
947 }
khenaidoob9203542018-09-17 22:56:37 -0400948 return nil
949}
950
khenaidoofdbad6e2018-11-06 22:26:38 -0500951func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
952 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
953 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
954 return agent.packetOut(outPort, packet)
955 }
956 return status.Errorf(codes.NotFound, "%s", deviceId)
957}
958
khenaidoo297cd252019-02-07 22:10:23 -0500959func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500960 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
961 // Get the logical device Id based on the deviceId
962 var device *voltha.Device
963 var err error
964 if device, err = dMgr.GetDevice(deviceId); err != nil {
965 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
966 return err
967 }
khenaidoo43c82122018-11-22 18:38:28 -0500968 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500969 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
970 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
971 }
972
khenaidoo297cd252019-02-07 22:10:23 -0500973 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500974 return err
975 }
976 return nil
977}
978
khenaidoo0a822f92019-05-08 15:15:57 -0400979func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
980 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -0400981 // Verify whether the logical device has already been created
982 if cDevice.ParentId != "" {
983 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
984 return nil
985 }
khenaidoob9203542018-09-17 22:56:37 -0400986 var logicalId *string
987 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400988 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400989 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
990 return err
991 }
992 // Update the parent device with the logical id
993 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
994 return nil
995}
996
khenaidoo0a822f92019-05-08 15:15:57 -0400997func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
998 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -0400999 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001000 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001001 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1002 return err
1003 }
1004 // Remove the logical device Id from the parent device
1005 logicalId := ""
1006 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
1007 return nil
1008}
1009
khenaidoo0a822f92019-05-08 15:15:57 -04001010func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001011 log.Info("deleteLogicalPort")
1012 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001013 // Get the logical port associated with this device
1014 var lPortId *voltha.LogicalPortId
1015 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001016 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001017 return err
1018 }
1019 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
1020 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001021 return err
1022 }
khenaidoo92e62c52018-10-03 14:02:54 -04001023 return nil
1024}
1025
khenaidoo0a822f92019-05-08 15:15:57 -04001026func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1027 log.Info("deleteLogicalPorts")
1028 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1029 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1030 return err
1031 }
1032 return nil
1033}
1034
khenaidoo59ef7be2019-06-21 12:40:28 -04001035func (dMgr *DeviceManager) MarkChildDevicesAsUnReachable(device *voltha.Device) error {
1036 log.Info("MarkChildDevicesAsUnReachable")
1037 // Set the connection status to unreachable
1038 connStatus := voltha.ConnectStatus_UNREACHABLE
1039 // Do not set the operational status. Setting it to -1 will do the trick
1040 operStatus := voltha.OperStatus_OperStatus(-1)
1041 if err := dMgr.updateChildrenStatus(device.Id, operStatus, connStatus); err != nil {
1042 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1043 return err
1044 }
1045 return nil
1046}
1047
khenaidoo92e62c52018-10-03 14:02:54 -04001048func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1049 // Sanity check
1050 if childDevice.Root {
1051 // childDevice is the parent device
1052 return childDevice
1053 }
khenaidoo19d7b632018-10-30 10:49:50 -04001054 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001055 return parentDevice
1056}
1057
khenaidoo0a822f92019-05-08 15:15:57 -04001058//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1059//cannot manage the child devices. This will trigger the Core to disable all the child devices.
1060func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
1061 log.Debug("childDevicesLost")
1062 var err error
1063 var parentDevice *voltha.Device
1064 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1065 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1066 return err
1067 }
1068 return dMgr.DisableAllChildDevices(parentDevice)
1069}
1070
1071//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1072// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
1073func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
1074 log.Debug("childDevicesDetected")
1075 var err error
1076 var parentDevice *voltha.Device
1077 var childDeviceIds []string
1078
1079 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
1080 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
1081 return err
1082 }
1083
1084 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1085 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1086 }
1087 if len(childDeviceIds) == 0 {
1088 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1089 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001090 allChildEnableRequestSent := true
khenaidoo0a822f92019-05-08 15:15:57 -04001091 for _, childDeviceId := range childDeviceIds {
1092 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001093 // Run the children re-registration in its own routine
1094 go agent.enableDevice(nil)
1095 } else {
1096 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceId)
1097 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceId})
1098 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001099 }
1100 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001101 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001102 return err
1103 }
1104 return nil
1105}
1106
khenaidoo4d4802d2018-10-04 21:59:49 -04001107/*
1108All the functions below are callback functions where they are invoked with the latest and previous data. We can
1109therefore use the data as is without trying to get the latest from the model.
1110*/
1111
khenaidoo0a822f92019-05-08 15:15:57 -04001112//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1113func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1114 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001115 var childDeviceIds []string
1116 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001117 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1118 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001119 }
1120 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001121 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001122 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001123 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -04001124 for _, childDeviceId := range childDeviceIds {
1125 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1126 if err = agent.disableDevice(nil); err != nil {
1127 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001128 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001129 }
1130 }
1131 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001132 if !allChildDisable {
1133 return err
1134 }
khenaidoo92e62c52018-10-03 14:02:54 -04001135 return nil
1136}
1137
khenaidoo0a822f92019-05-08 15:15:57 -04001138//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1139func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1140 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001141 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001142 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001143 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1144 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001145 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001146 if len(childDeviceIds) == 0 {
1147 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1148 }
1149 allChildDeleted := true
1150 for _, childDeviceId := range childDeviceIds {
1151 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1152 if err = agent.deleteDevice(nil); err != nil {
1153 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
1154 allChildDeleted = false
1155 } else {
1156 agent.stop(nil)
khenaidoo4c9e5592019-09-09 16:20:41 -04001157 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo4d4802d2018-10-04 21:59:49 -04001158 }
1159 }
1160 }
1161 if !allChildDeleted {
1162 return err
1163 }
1164 return nil
1165}
1166
khenaidoo6d62c002019-05-15 21:57:03 -04001167//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1168// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1169// device during a delete device operation.
1170func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentId(id string) []string {
1171 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1172 deviceIds := make([]string, 0)
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001173 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
1174 agent := value.(*DeviceAgent)
khenaidoo6d62c002019-05-15 21:57:03 -04001175 if agent.parentId == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001176 deviceIds = append(deviceIds, key.(string))
khenaidoo6d62c002019-05-15 21:57:03 -04001177 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001178 return true
1179 })
khenaidoo6d62c002019-05-15 21:57:03 -04001180 return deviceIds
1181}
1182
khenaidoo4d4802d2018-10-04 21:59:49 -04001183//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1184func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1185 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001186 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001187 if parentDevice != nil {
1188 for _, port := range parentDevice.Ports {
1189 for _, peer := range port.Peers {
1190 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1191 }
khenaidoo92e62c52018-10-03 14:02:54 -04001192 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001193 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001194 }
1195 return childDeviceIds, nil
1196}
1197
khenaidoo297cd252019-02-07 22:10:23 -05001198//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1199func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
1200 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
1201 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
1202 childDevices := make([]*voltha.Device, 0)
1203 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
1204 for _, deviceId := range childDeviceIds {
1205 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
1206 childDevices = append(childDevices, d)
1207 }
1208 }
1209 }
1210 return &voltha.Devices{Items: childDevices}, nil
1211 }
1212 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
1213}
1214
khenaidoo0a822f92019-05-08 15:15:57 -04001215func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001216 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -04001217 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001218 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1219 return err
1220 }
1221 return nil
1222}
1223
khenaidoof5a5bfa2019-01-23 22:20:29 -05001224func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1225 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1226 var res interface{}
1227 var err error
1228 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1229 if res, err = agent.downloadImage(ctx, img); err != nil {
1230 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1231 res = err
1232 }
1233 } else {
1234 res = status.Errorf(codes.NotFound, "%s", img.Id)
1235 }
1236 sendResponse(ctx, ch, res)
1237}
1238
1239func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1240 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1241 var res interface{}
1242 var err error
1243 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1244 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1245 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1246 res = err
1247 }
1248 } else {
1249 res = status.Errorf(codes.NotFound, "%s", img.Id)
1250 }
1251 sendResponse(ctx, ch, res)
1252}
1253
1254func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1255 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1256 var res interface{}
1257 var err error
1258 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1259 if res, err = agent.activateImage(ctx, img); err != nil {
1260 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1261 res = err
1262 }
1263 } else {
1264 res = status.Errorf(codes.NotFound, "%s", img.Id)
1265 }
1266 sendResponse(ctx, ch, res)
1267}
1268
1269func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1270 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1271 var res interface{}
1272 var err error
1273 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1274 if res, err = agent.revertImage(ctx, img); err != nil {
1275 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1276 res = err
1277 }
1278 } else {
1279 res = status.Errorf(codes.NotFound, "%s", img.Id)
1280 }
1281 sendResponse(ctx, ch, res)
1282}
1283
1284func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1285 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1286 var res interface{}
1287 var err error
1288 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1289 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1290 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1291 res = err
1292 }
1293 } else {
1294 res = status.Errorf(codes.NotFound, "%s", img.Id)
1295 }
1296 sendResponse(ctx, ch, res)
1297}
1298
khenaidoof5a5bfa2019-01-23 22:20:29 -05001299func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1300 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1301 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1302 if err := agent.updateImageDownload(img); err != nil {
1303 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1304 return err
1305 }
1306 } else {
1307 return status.Errorf(codes.NotFound, "%s", img.Id)
1308 }
1309 return nil
1310}
1311
1312func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1313 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1314 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1315 return agent.getImageDownload(ctx, img)
1316 }
1317 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1318}
1319
1320func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1321 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1322 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1323 return agent.listImageDownloads(ctx, deviceId)
1324 }
1325 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1326}
1327
khenaidoo0a822f92019-05-08 15:15:57 -04001328func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1329 log.Info("SetAdminStateToEnable")
1330 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1331 return agent.updateAdminState(voltha.AdminState_ENABLED)
1332 }
1333 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1334}
1335
khenaidoo92e62c52018-10-03 14:02:54 -04001336func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001337 log.Info("activateDevice")
1338 return nil
1339}
1340
khenaidoo92e62c52018-10-03 14:02:54 -04001341func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1342 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001343 return nil
1344}
1345
khenaidoo92e62c52018-10-03 14:02:54 -04001346func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001347 log.Info("abandonDevice")
1348 return nil
1349}
1350
khenaidoo92e62c52018-10-03 14:02:54 -04001351func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001352 log.Info("reEnableDevice")
1353 return nil
1354}
1355
khenaidoo92e62c52018-10-03 14:02:54 -04001356func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001357 log.Info("noOp")
1358 return nil
1359}
1360
khenaidoo92e62c52018-10-03 14:02:54 -04001361func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001362 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001363 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001364}
1365
khenaidoo0a822f92019-05-08 15:15:57 -04001366func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001367 log.Errorw("NotifyInvalidTransition", log.Fields{
1368 "device": pcDevice.Id,
1369 "adminState": pcDevice.AdminState,
1370 "operState": pcDevice.OperStatus,
1371 "connState": pcDevice.ConnectStatus,
1372 })
khenaidoo0a822f92019-05-08 15:15:57 -04001373 //TODO: notify over kafka?
1374 return nil
1375}
1376
khenaidoob9203542018-09-17 22:56:37 -04001377func funcName(f interface{}) string {
1378 p := reflect.ValueOf(f).Pointer()
1379 rf := runtime.FuncForPC(p)
1380 return rf.Name()
1381}
1382
1383func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001384 if agent, ok := dMgr.deviceAgents.Load(deviceId); ok {
1385 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001386 }
1387}
1388
khenaidoo4c9e5592019-09-09 16:20:41 -04001389func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) string {
khenaidoo19d7b632018-10-30 10:49:50 -04001390 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001391 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001392 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001393 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001394 return ""
khenaidoob9203542018-09-17 22:56:37 -04001395}
serkant.uluderya334479d2019-04-10 08:26:15 -07001396
1397func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1398 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1399 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1400 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1401 var res interface{}
1402 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1403 res = agent.simulateAlarm(ctx, simulatereq)
1404 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1405 }
1406 //TODO CLI always get successful response
1407 sendResponse(ctx, ch, res)
1408}