blob: ad4f36286fe74d0081dbdf9c0f95cf45479c221d [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 {
36 deviceAgents map[string]*DeviceAgent
khenaidoo2c6a0992019-04-29 13:46:56 -040037 rootDevices map[string]bool
38 lockRootDeviceMap sync.RWMutex
Richard Jankowski199fd862019-03-18 14:49:51 -040039 core *Core
khenaidoob9203542018-09-17 22:56:37 -040040 adapterProxy *AdapterProxy
khenaidoo297cd252019-02-07 22:10:23 -050041 adapterMgr *AdapterManager
khenaidoob9203542018-09-17 22:56:37 -040042 logicalDeviceMgr *LogicalDeviceManager
khenaidoo43c82122018-11-22 18:38:28 -050043 kafkaICProxy *kafka.InterContainerProxy
khenaidoob9203542018-09-17 22:56:37 -040044 stateTransitions *TransitionMap
khenaidoo9a468962018-09-19 15:33:13 -040045 clusterDataProxy *model.Proxy
khenaidood2b6df92018-12-13 16:37:20 -050046 coreInstanceId string
khenaidoob9203542018-09-17 22:56:37 -040047 exitChannel chan int
khenaidoo2c6a0992019-04-29 13:46:56 -040048 defaultTimeout int64
khenaidoob9203542018-09-17 22:56:37 -040049 lockDeviceAgentsMap sync.RWMutex
50}
51
Richard Jankowski199fd862019-03-18 14:49:51 -040052func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040053 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040054 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040055 deviceMgr.exitChannel = make(chan int, 1)
56 deviceMgr.deviceAgents = make(map[string]*DeviceAgent)
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
59 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp)
60 deviceMgr.coreInstanceId = core.instanceId
61 deviceMgr.clusterDataProxy = core.clusterDataProxy
62 deviceMgr.adapterMgr = core.adapterMgr
khenaidoob9203542018-09-17 22:56:37 -040063 deviceMgr.lockDeviceAgentsMap = sync.RWMutex{}
khenaidoo2c6a0992019-04-29 13:46:56 -040064 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
65 deviceMgr.defaultTimeout = core.config.DefaultCoreTimeout
khenaidoob9203542018-09-17 22:56:37 -040066 return &deviceMgr
67}
68
khenaidoo4d4802d2018-10-04 21:59:49 -040069func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040070 log.Info("starting-device-manager")
71 dMgr.logicalDeviceMgr = logicalDeviceMgr
72 dMgr.stateTransitions = NewTransitionMap(dMgr)
73 log.Info("device-manager-started")
74}
75
khenaidoo4d4802d2018-10-04 21:59:49 -040076func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040077 log.Info("stopping-device-manager")
78 dMgr.exitChannel <- 1
79 log.Info("device-manager-stopped")
80}
81
82func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
83 if ctx.Err() == nil {
84 // Returned response only of the ctx has not been cancelled/timeout/etc
85 // Channel is automatically closed when a context is Done
86 ch <- result
87 log.Debugw("sendResponse", log.Fields{"result": result})
88 } else {
89 // Should the transaction be reverted back?
90 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
91 }
92}
93
94func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
95 dMgr.lockDeviceAgentsMap.Lock()
khenaidoo2c6a0992019-04-29 13:46:56 -040096 //defer dMgr.lockDeviceAgentsMap.Unlock()
khenaidoob9203542018-09-17 22:56:37 -040097 if _, exist := dMgr.deviceAgents[agent.deviceId]; !exist {
98 dMgr.deviceAgents[agent.deviceId] = agent
99 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400100 dMgr.lockDeviceAgentsMap.Unlock()
101 dMgr.lockRootDeviceMap.Lock()
102 defer dMgr.lockRootDeviceMap.Unlock()
103 dMgr.rootDevices[agent.deviceId] = agent.isRootdevice
104
khenaidoob9203542018-09-17 22:56:37 -0400105}
106
khenaidoo4d4802d2018-10-04 21:59:49 -0400107func (dMgr *DeviceManager) deleteDeviceAgentToMap(agent *DeviceAgent) {
108 dMgr.lockDeviceAgentsMap.Lock()
khenaidoo2c6a0992019-04-29 13:46:56 -0400109 //defer dMgr.lockDeviceAgentsMap.Unlock()
khenaidoo4d4802d2018-10-04 21:59:49 -0400110 delete(dMgr.deviceAgents, agent.deviceId)
khenaidoo2c6a0992019-04-29 13:46:56 -0400111 dMgr.lockDeviceAgentsMap.Unlock()
112 dMgr.lockRootDeviceMap.Lock()
113 defer dMgr.lockRootDeviceMap.Unlock()
114 delete(dMgr.rootDevices, agent.deviceId)
115
khenaidoo4d4802d2018-10-04 21:59:49 -0400116}
117
khenaidoo297cd252019-02-07 22:10:23 -0500118// 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 -0400119func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400120 dMgr.lockDeviceAgentsMap.RLock()
khenaidoob9203542018-09-17 22:56:37 -0400121 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400122 dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoob9203542018-09-17 22:56:37 -0400123 return agent
khenaidoo297cd252019-02-07 22:10:23 -0500124 } else {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400125 // Try to load into memory - loading will also create the device agent and set the device ownership
khenaidoo1ce37ad2019-03-24 22:07:24 -0400126 dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoo297cd252019-02-07 22:10:23 -0500127 if err := dMgr.load(deviceId); err == nil {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400128 dMgr.lockDeviceAgentsMap.RLock()
129 defer dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoo3d3b8c22019-05-22 18:10:39 -0400130 if agent, ok = dMgr.deviceAgents[deviceId]; !ok {
131 return nil
132 } else {
133 // Register this device for ownership tracking
134 go dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{Id: deviceId})
khenaidoo297cd252019-02-07 22:10:23 -0500135 return agent
136 }
khenaidoo3d3b8c22019-05-22 18:10:39 -0400137 } else {
138 //TODO: Change the return params to return an error as well
139 log.Errorw("loading-device-failed", log.Fields{"deviceId": deviceId, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500140 }
khenaidoob9203542018-09-17 22:56:37 -0400141 }
142 return nil
143}
144
khenaidoo297cd252019-02-07 22:10:23 -0500145// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500146func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400147 dMgr.lockDeviceAgentsMap.RLock()
148 defer dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoo7ccedd52018-12-14 16:48:54 -0500149 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
khenaidoo2c6a0992019-04-29 13:46:56 -0400150 for key := range dMgr.deviceAgents {
khenaidoo7ccedd52018-12-14 16:48:54 -0500151 result.Items = append(result.Items, &voltha.ID{Id: key})
152 }
153 return result
154}
155
khenaidoob9203542018-09-17 22:56:37 -0400156func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400157 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400158
khenaidoo5e677ae2019-02-28 17:26:29 -0500159 // Ensure this device is set as root
160 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400161 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400162 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400163 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500164 agent.start(ctx, false)
khenaidoob9203542018-09-17 22:56:37 -0400165
khenaidoo92e62c52018-10-03 14:02:54 -0400166 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400167}
168
169func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400170 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400171 var res interface{}
172 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
173 res = agent.enableDevice(ctx)
174 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400175 }
176
177 sendResponse(ctx, ch, res)
178}
179
khenaidoo92e62c52018-10-03 14:02:54 -0400180func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
181 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400182 var res interface{}
183 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
184 res = agent.disableDevice(ctx)
185 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400186 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400187 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400188 }
khenaidoo92e62c52018-10-03 14:02:54 -0400189
190 sendResponse(ctx, ch, res)
191}
192
khenaidoo4d4802d2018-10-04 21:59:49 -0400193func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
194 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
195 var res interface{}
196 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
197 res = agent.rebootDevice(ctx)
198 log.Debugw("rebootDevice-result", log.Fields{"result": res})
199 } else {
200 res = status.Errorf(codes.NotFound, "%s", id.Id)
201 }
202 sendResponse(ctx, ch, res)
203}
204
205func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
206 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
207 var res interface{}
208 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
209 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400210 log.Debugw("deleteDevice-result", log.Fields{"result": res})
211 } else {
212 res = status.Errorf(codes.NotFound, "%s", id.Id)
213 }
214 sendResponse(ctx, ch, res)
215}
216
khenaidoo6d62c002019-05-15 21:57:03 -0400217// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
218// This function is called only in the Core that does not own this device. In the Core that owns this device then a
219// deletion deletion also includes removal of any reference of this device.
220func (dMgr *DeviceManager) stopManagingDevice(id string) {
221 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
222 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
223 if root, _ := dMgr.IsRootDevice(id); root == true {
224 // stop managing the logical device
225 ldeviceId := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceId(id)
226 if ldeviceId != "" { // Can happen if logical device agent was already stopped
227 dMgr.core.deviceOwnership.AbandonDevice(ldeviceId)
228 }
229 // stop managing the child devices
230 childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentId(id)
231 for _, cId := range childDeviceIds {
232 dMgr.stopManagingDevice(cId)
233 }
234 }
235 if agent := dMgr.getDeviceAgent(id); agent != nil {
236 agent.stop(nil)
237 dMgr.deleteDeviceAgentToMap(agent)
238 // Abandon the device ownership
239 dMgr.core.deviceOwnership.AbandonDevice(id)
240 }
241 }
242}
243
khenaidoo0a822f92019-05-08 15:15:57 -0400244func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
245 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400246 dMgr.stopManagingDevice(cDevice.Id)
247 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400248}
249
khenaidoo297cd252019-02-07 22:10:23 -0500250// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400251func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
252 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400253 if agent := dMgr.getDeviceAgent(id); agent != nil {
254 return agent.getDevice()
255 }
256 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400257}
258
Matt Jeanneret4e241952019-02-28 11:16:04 -0500259func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
Matt Jeanneret0c5088c2019-04-22 16:16:19 -0400260 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber,
261 "parentPortNo": parentPortNo, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500262
263 var parentDevice *voltha.Device
264 var err error
265 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
266 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
267 }
268 var childDeviceIds []string
269 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
270 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
271 }
272 if len(childDeviceIds) == 0 {
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700273 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500274 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
275 }
276
277 var foundChildDevice *voltha.Device
278 for _, childDeviceId := range childDeviceIds {
279 found := false
280 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
281
282 foundOnuId := false
283 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
284 if searchDevice.ParentPortNo == uint32(parentPortNo) {
285 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
286 foundOnuId = true
287 }
288 }
289
290 foundSerialNumber := false
291 if searchDevice.SerialNumber == serialNumber {
292 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
293 foundSerialNumber = true
294 }
295
296 // if both onuId and serialNumber are provided both must be true for the device to be found
297 // otherwise whichever one found a match is good enough
298 if onuId > 0 && serialNumber != "" {
299 found = foundOnuId && foundSerialNumber
300 } else {
301 found = foundOnuId || foundSerialNumber
302 }
303
304 if found == true {
305 foundChildDevice = searchDevice
306 break
307 }
308 }
309 }
310
311 if foundChildDevice != nil {
312 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
313 return foundChildDevice, nil
314 }
315
316 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
317 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
318 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
319}
320
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500321func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
322 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
323
324 var parentDevice *voltha.Device
325 var err error
326 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
327 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
328 }
329 var childDeviceIds []string
330 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
331 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
332 }
333 if len(childDeviceIds) == 0 {
334 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
335 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
336 }
337
338 var foundChildDevice *voltha.Device
339 for _, childDeviceId := range childDeviceIds {
340 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
341 if searchDevice.ProxyAddress == proxyAddress {
342 foundChildDevice = searchDevice
343 break
344 }
345 }
346 }
347
348 if foundChildDevice != nil {
349 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
350 return foundChildDevice, nil
351 }
352
353 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
354 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
355}
356
khenaidoo297cd252019-02-07 22:10:23 -0500357func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400358 dMgr.lockDeviceAgentsMap.RLock()
359 defer dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoo297cd252019-02-07 22:10:23 -0500360 _, exist := dMgr.deviceAgents[id]
361 return exist
362}
363
khenaidoo19d7b632018-10-30 10:49:50 -0400364func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400365 dMgr.lockRootDeviceMap.RLock()
366 defer dMgr.lockRootDeviceMap.RUnlock()
367 if exist := dMgr.rootDevices[id]; exist {
368 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400369 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400370 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400371}
372
Stephane Barbarieaa467942019-02-06 14:09:44 -0500373// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400374func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400375 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400376 result := &voltha.Devices{}
Stephane Barbarieaa467942019-02-06 14:09:44 -0500377 if devices := dMgr.clusterDataProxy.List("/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500378 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500379 // If device is not in memory then set it up
380 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400381 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400382 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500383 if err := agent.start(nil, true); err != nil {
384 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
385 agent.stop(nil)
386 } else {
387 dMgr.addDeviceAgentToMap(agent)
388 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500389 }
390 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400391 }
392 }
khenaidoo6d62c002019-05-15 21:57:03 -0400393 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400394 return result, nil
395}
396
khenaidoo6d62c002019-05-15 21:57:03 -0400397//getDeviceFromModelretrieves the device data from the model.
398func (dMgr *DeviceManager) getDeviceFromModel(deviceId string) (*voltha.Device, error) {
399 if device := dMgr.clusterDataProxy.Get("/devices/"+deviceId, 0, false, ""); device != nil {
400 if d, ok := device.(*voltha.Device); ok {
401 return d, nil
402 }
403 }
404 return nil, status.Error(codes.NotFound, deviceId)
405}
406
khenaidoo297cd252019-02-07 22:10:23 -0500407// loadDevice loads the deviceId in memory, if not present
408func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
409 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
410 // Sanity check
411 if deviceId == "" {
412 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
413 }
414 if !dMgr.IsDeviceInCache(deviceId) {
khenaidoo6d62c002019-05-15 21:57:03 -0400415 // Proceed with the loading only if the device exist in the Model (could have been deleted)
416 if device, err := dMgr.getDeviceFromModel(deviceId); err == nil {
417 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
418 if err := agent.start(nil, true); err != nil {
419 agent.stop(nil)
420 return nil, err
421 }
422 dMgr.addDeviceAgentToMap(agent)
423 } else {
424 return nil, status.Error(codes.NotFound, deviceId)
khenaidoo297cd252019-02-07 22:10:23 -0500425 }
khenaidoo297cd252019-02-07 22:10:23 -0500426 }
427 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
428 return agent, nil
429 }
Matt Jeanneret4e241952019-02-28 11:16:04 -0500430 return nil, status.Error(codes.NotFound, deviceId) // This should not happen
khenaidoo297cd252019-02-07 22:10:23 -0500431}
432
433// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
434func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
435 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
436 if device.Root {
437 // Scenario A
438 if device.ParentId != "" {
439 // Load logical device if needed.
440 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
441 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
442 }
443 } else {
444 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
445 }
446 // Load all child devices, if needed
447 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
448 for _, childDeviceId := range childDeviceIds {
449 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
450 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId})
451 return err
452 }
453 }
454 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
455 } else {
456 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
457 }
458 }
459 return nil
460}
461
462// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
463// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
464// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
465// and the proceed with the request.
466func (dMgr *DeviceManager) load(deviceId string) error {
467 log.Debug("load...")
468 // First load the device - this may fail in case the device was deleted intentionally by the other core
469 var dAgent *DeviceAgent
470 var err error
471 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500472 return err
473 }
474 // Get the loaded device details
475 var device *voltha.Device
476 if device, err = dAgent.getDevice(); err != nil {
477 return err
478 }
479
480 // If the device is in Pre-provisioning or deleted state stop here
481 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
482 return nil
483 }
484
485 // Now we face two scenarios
486 if device.Root {
487 // Load all children as well as the parent of this device (logical_device)
488 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
489 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
490 return err
491 }
492 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
493 } else {
494 // Scenario B - use the parentId of that device (root device) to trigger the loading
495 if device.ParentId != "" {
496 return dMgr.load(device.ParentId)
497 }
498 }
499 return nil
500}
501
khenaidoo7ccedd52018-12-14 16:48:54 -0500502// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
503func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
504 log.Debug("ListDeviceIDs")
505 // Report only device IDs that are in the device agent map
506 return dMgr.listDeviceIdsFromMap(), nil
507}
508
509//ReconcileDevices is a request to a voltha core to managed a list of devices based on their IDs
510func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
511 log.Debug("ReconcileDevices")
512 var res interface{}
513 if ids != nil {
514 toReconcile := len(ids.Items)
515 reconciled := 0
516 for _, id := range ids.Items {
517 // Act on the device only if its not present in the agent map
khenaidoo297cd252019-02-07 22:10:23 -0500518 if !dMgr.IsDeviceInCache(id.Id) {
khenaidoo7ccedd52018-12-14 16:48:54 -0500519 // Device Id not in memory
520 log.Debugw("reconciling-device", log.Fields{"id": id.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400521 // Proceed with the loading only if the device exist in the Model (could have been deleted)
522 if device, err := dMgr.getDeviceFromModel(id.Id); err == nil {
523 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
524 if err := agent.start(nil, true); err != nil {
525 log.Warnw("failure-loading-device", log.Fields{"deviceId": id.Id})
526 agent.stop(nil)
527 } else {
528 dMgr.addDeviceAgentToMap(agent)
529 reconciled += 1
530 }
khenaidoo7ccedd52018-12-14 16:48:54 -0500531 } else {
khenaidoo297cd252019-02-07 22:10:23 -0500532 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500533 }
khenaidoo7ccedd52018-12-14 16:48:54 -0500534 }
535 }
536 if toReconcile != reconciled {
537 res = status.Errorf(codes.DataLoss, "less-device-reconciled:%d/%d", reconciled, toReconcile)
538 }
539 } else {
540 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
541 }
542 sendResponse(ctx, ch, res)
543}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500544
khenaidoob9203542018-09-17 22:56:37 -0400545func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400546 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400547 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
548 return agent.updateDevice(device)
549 }
550 return status.Errorf(codes.NotFound, "%s", device.Id)
551}
552
553func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
554 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400555 if err := agent.addPort(port); err != nil {
556 return err
557 }
558 // Setup peer ports
559 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
560 for _, peerPort := range port.Peers {
561 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
562 if err := agent.addPeerPort(meAsPeer); err != nil {
563 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
564 return err
565 }
566 }
567 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400568 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
569 // then a logical port will be added to the logical device and the device graph generated. If the port is a
570 // PON port then only the device graph will be generated.
571 if device, err := dMgr.GetDevice(deviceId); err == nil {
572 go dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
573 } else {
574 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
575 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400576 }
khenaidoo92e62c52018-10-03 14:02:54 -0400577 return nil
578 } else {
579 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400580 }
khenaidoob9203542018-09-17 22:56:37 -0400581}
582
khenaidoo0a822f92019-05-08 15:15:57 -0400583func (dMgr *DeviceManager) deletePeerPorts(fromDeviceId string, deviceId string) error {
584 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceId, "deviceid": deviceId})
585 if agent := dMgr.getDeviceAgent(fromDeviceId); agent != nil {
586 return agent.deletePeerPorts(deviceId)
587 }
588 return status.Errorf(codes.NotFound, "%s", deviceId)
589}
590
khenaidoo2c6a0992019-04-29 13:46:56 -0400591func (dMgr *DeviceManager) addFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) error {
592 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400593 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400594 return agent.addFlowsAndGroups(flows, groups)
khenaidoo0458db62019-06-20 08:50:36 -0400595 }
596 return status.Errorf(codes.NotFound, "%s", deviceId)
597}
598
599func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) error {
600 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceId})
601 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
602 return agent.deleteFlowsAndGroups(flows, groups)
603 }
604 return status.Errorf(codes.NotFound, "%s", deviceId)
605}
606
607func (dMgr *DeviceManager) updateFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) error {
608 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceId})
609 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
610 return agent.updateFlowsAndGroups(flows, groups)
khenaidoo19d7b632018-10-30 10:49:50 -0400611 }
612 return status.Errorf(codes.NotFound, "%s", deviceId)
613}
614
khenaidoob9203542018-09-17 22:56:37 -0400615func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
616 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
617 return agent.updatePmConfigs(pmConfigs)
618 }
619 return status.Errorf(codes.NotFound, "%s", deviceId)
620}
621
khenaidoo79232702018-12-04 11:00:41 -0500622func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400623 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400624 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
625 return agent.getSwitchCapability(ctx)
626 }
627 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
628}
629
khenaidoo92e62c52018-10-03 14:02:54 -0400630func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
631 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400632 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400633 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400634 }
635 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400636
khenaidoob9203542018-09-17 22:56:37 -0400637}
638
khenaidoo79232702018-12-04 11:00:41 -0500639func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400640 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400641 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
642 return agent.getPortCapability(ctx, portNo)
643 }
644 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
645}
646
khenaidoo92e62c52018-10-03 14:02:54 -0400647func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
648 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400649 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400650 return agent.updateDeviceStatus(operStatus, connStatus)
651 }
652 return status.Errorf(codes.NotFound, "%s", deviceId)
653}
654
khenaidoo4d4802d2018-10-04 21:59:49 -0400655func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
656 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
657 var parentDevice *voltha.Device
658 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400659 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400660 return status.Errorf(codes.Aborted, "%s", err.Error())
661 }
662 var childDeviceIds []string
663 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
664 return status.Errorf(codes.Aborted, "%s", err.Error())
665 }
666 if len(childDeviceIds) == 0 {
667 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
668 }
669 for _, childDeviceId := range childDeviceIds {
670 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
671 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
672 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
673 }
674 }
675 }
676 return nil
677}
678
khenaidoo92e62c52018-10-03 14:02:54 -0400679func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
680 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
681 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
682 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400683 }
684 return status.Errorf(codes.NotFound, "%s", deviceId)
685}
686
khenaidoo0a822f92019-05-08 15:15:57 -0400687func (dMgr *DeviceManager) deleteAllPorts(deviceId string) error {
688 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceId})
689 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
690 if err := agent.deleteAllPorts(); err != nil {
691 return err
692 }
693 // Notify the logical device manager to remove all logical ports, if needed.
694 // At this stage the device itself may gave been deleted already at a deleteAllPorts
695 // typically is part of a device deletion phase.
696 if device, err := dMgr.GetDevice(deviceId); err == nil {
697 go dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
698 } else {
699 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
700 return err
701 }
702 return nil
703 }
704 return status.Errorf(codes.NotFound, "%s", deviceId)
705}
706
khenaidoo3ab34882019-05-02 21:33:30 -0400707//updatePortsState updates all ports on the device
708func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
709 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
710
711 var adminState voltha.AdminState_AdminState
712 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
713 switch state {
714 case voltha.OperStatus_ACTIVE:
715 adminState = voltha.AdminState_ENABLED
716 if err := agent.enablePorts(); err != nil {
717 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
718 return err
719 }
720 case voltha.OperStatus_UNKNOWN:
721 adminState = voltha.AdminState_DISABLED
722 if err := agent.disablePorts(); err != nil {
723 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
724 return err
725 }
726 default:
727 return status.Error(codes.Unimplemented, "state-change-not-implemented")
728 }
729 // Notify the logical device about the state change
730 if device, err := dMgr.GetDevice(deviceId); err != nil {
731 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
732 return err
733 } else {
734 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
735 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
736 return err
737 }
738 return nil
739 }
740 }
741 return status.Errorf(codes.NotFound, "%s", deviceId)
742}
743
Matt Jeanneret4e241952019-02-28 11:16:04 -0500744func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700745 channelId int64, vendorId string, serialNumber string, onuId int64) (*voltha.Device, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400746 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400747
748 // Create the ONU device
749 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400750 childDevice.Type = deviceType
751 childDevice.ParentId = parentDeviceId
752 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500753 childDevice.VendorId = vendorId
754 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400755 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400756
757 //Get parent device type
758 parent, err := dMgr.GetDevice(parentDeviceId)
759 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500760 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700761 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400762 }
763
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700764 if device, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500765 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700766 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500767 }
768
769 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400770
771 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400772 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400773 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500774 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400775
776 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400777 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500778 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400779 }
780
khenaidoo79232702018-12-04 11:00:41 -0500781 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500782 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500783
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700784 return agent.lastData, nil
khenaidoob9203542018-09-17 22:56:37 -0400785}
786
787func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
788 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400789 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
790 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500791 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400792 return nil
khenaidoob9203542018-09-17 22:56:37 -0400793 }
khenaidoo0a822f92019-05-08 15:15:57 -0400794 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root})
khenaidoo92e62c52018-10-03 14:02:54 -0400795 for _, handler := range handlers {
796 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
797 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400798 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400799 return err
800 }
801 }
khenaidoob9203542018-09-17 22:56:37 -0400802 return nil
803}
804
khenaidoofdbad6e2018-11-06 22:26:38 -0500805func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
806 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
807 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
808 return agent.packetOut(outPort, packet)
809 }
810 return status.Errorf(codes.NotFound, "%s", deviceId)
811}
812
khenaidoo297cd252019-02-07 22:10:23 -0500813func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500814 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
815 // Get the logical device Id based on the deviceId
816 var device *voltha.Device
817 var err error
818 if device, err = dMgr.GetDevice(deviceId); err != nil {
819 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
820 return err
821 }
khenaidoo43c82122018-11-22 18:38:28 -0500822 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500823 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
824 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
825 }
826
khenaidoo297cd252019-02-07 22:10:23 -0500827 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500828 return err
829 }
830 return nil
831}
832
khenaidoo0a822f92019-05-08 15:15:57 -0400833func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
834 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -0400835 // Verify whether the logical device has already been created
836 if cDevice.ParentId != "" {
837 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
838 return nil
839 }
khenaidoob9203542018-09-17 22:56:37 -0400840 var logicalId *string
841 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400842 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400843 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
844 return err
845 }
846 // Update the parent device with the logical id
847 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
848 return nil
849}
850
khenaidoo0a822f92019-05-08 15:15:57 -0400851func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
852 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -0400853 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400854 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400855 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
856 return err
857 }
858 // Remove the logical device Id from the parent device
859 logicalId := ""
860 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
861 return nil
862}
863
khenaidoo0a822f92019-05-08 15:15:57 -0400864func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400865 log.Info("deleteLogicalPort")
866 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400867 // Get the logical port associated with this device
868 var lPortId *voltha.LogicalPortId
869 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400870 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400871 return err
872 }
873 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
874 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400875 return err
876 }
khenaidoo92e62c52018-10-03 14:02:54 -0400877 return nil
878}
879
khenaidoo0a822f92019-05-08 15:15:57 -0400880func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
881 log.Info("deleteLogicalPorts")
882 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
883 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
884 return err
885 }
886 return nil
887}
888
khenaidoo59ef7be2019-06-21 12:40:28 -0400889func (dMgr *DeviceManager) MarkChildDevicesAsUnReachable(device *voltha.Device) error {
890 log.Info("MarkChildDevicesAsUnReachable")
891 // Set the connection status to unreachable
892 connStatus := voltha.ConnectStatus_UNREACHABLE
893 // Do not set the operational status. Setting it to -1 will do the trick
894 operStatus := voltha.OperStatus_OperStatus(-1)
895 if err := dMgr.updateChildrenStatus(device.Id, operStatus, connStatus); err != nil {
896 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
897 return err
898 }
899 return nil
900}
901
khenaidoo92e62c52018-10-03 14:02:54 -0400902func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
903 // Sanity check
904 if childDevice.Root {
905 // childDevice is the parent device
906 return childDevice
907 }
khenaidoo19d7b632018-10-30 10:49:50 -0400908 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400909 return parentDevice
910}
911
khenaidoo0a822f92019-05-08 15:15:57 -0400912//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
913//cannot manage the child devices. This will trigger the Core to disable all the child devices.
914func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
915 log.Debug("childDevicesLost")
916 var err error
917 var parentDevice *voltha.Device
918 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
919 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
920 return err
921 }
922 return dMgr.DisableAllChildDevices(parentDevice)
923}
924
925//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
926// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
927func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
928 log.Debug("childDevicesDetected")
929 var err error
930 var parentDevice *voltha.Device
931 var childDeviceIds []string
932
933 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
934 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
935 return err
936 }
937
938 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
939 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
940 }
941 if len(childDeviceIds) == 0 {
942 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
943 }
khenaidoo59ef7be2019-06-21 12:40:28 -0400944 allChildEnableRequestSent := true
khenaidoo0a822f92019-05-08 15:15:57 -0400945 for _, childDeviceId := range childDeviceIds {
946 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -0400947 // Run the children re-registration in its own routine
948 go agent.enableDevice(nil)
949 } else {
950 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceId)
951 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceId})
952 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -0400953 }
954 }
khenaidoo59ef7be2019-06-21 12:40:28 -0400955 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -0400956 return err
957 }
958 return nil
959}
960
khenaidoo4d4802d2018-10-04 21:59:49 -0400961/*
962All the functions below are callback functions where they are invoked with the latest and previous data. We can
963therefore use the data as is without trying to get the latest from the model.
964*/
965
khenaidoo0a822f92019-05-08 15:15:57 -0400966//DisableAllChildDevices is invoked as a callback when the parent device is disabled
967func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
968 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -0400969 var childDeviceIds []string
970 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400971 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
972 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400973 }
974 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400975 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400976 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400977 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400978 for _, childDeviceId := range childDeviceIds {
979 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
980 if err = agent.disableDevice(nil); err != nil {
981 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400982 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400983 }
984 }
985 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400986 if !allChildDisable {
987 return err
988 }
khenaidoo92e62c52018-10-03 14:02:54 -0400989 return nil
990}
991
khenaidoo0a822f92019-05-08 15:15:57 -0400992//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
993func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
994 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -0400995 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400996 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400997 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
998 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400999 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001000 if len(childDeviceIds) == 0 {
1001 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1002 }
1003 allChildDeleted := true
1004 for _, childDeviceId := range childDeviceIds {
1005 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
1006 if err = agent.deleteDevice(nil); err != nil {
1007 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
1008 allChildDeleted = false
1009 } else {
1010 agent.stop(nil)
1011 dMgr.deleteDeviceAgentToMap(agent)
1012 }
1013 }
1014 }
1015 if !allChildDeleted {
1016 return err
1017 }
1018 return nil
1019}
1020
khenaidoo6d62c002019-05-15 21:57:03 -04001021//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1022// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1023// device during a delete device operation.
1024func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentId(id string) []string {
1025 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1026 deviceIds := make([]string, 0)
1027 dMgr.lockDeviceAgentsMap.RLock()
1028 defer dMgr.lockDeviceAgentsMap.RUnlock()
1029 for deviceId, agent := range dMgr.deviceAgents {
1030 if agent.parentId == id {
1031 deviceIds = append(deviceIds, deviceId)
1032 }
1033 }
1034 return deviceIds
1035}
1036
khenaidoo4d4802d2018-10-04 21:59:49 -04001037//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1038func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1039 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001040 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001041 if parentDevice != nil {
1042 for _, port := range parentDevice.Ports {
1043 for _, peer := range port.Peers {
1044 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1045 }
khenaidoo92e62c52018-10-03 14:02:54 -04001046 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001047 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001048 }
1049 return childDeviceIds, nil
1050}
1051
khenaidoo297cd252019-02-07 22:10:23 -05001052//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1053func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
1054 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
1055 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
1056 childDevices := make([]*voltha.Device, 0)
1057 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
1058 for _, deviceId := range childDeviceIds {
1059 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
1060 childDevices = append(childDevices, d)
1061 }
1062 }
1063 }
1064 return &voltha.Devices{Items: childDevices}, nil
1065 }
1066 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
1067}
1068
khenaidoo0a822f92019-05-08 15:15:57 -04001069func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001070 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -04001071 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001072 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1073 return err
1074 }
1075 return nil
1076}
1077
khenaidoof5a5bfa2019-01-23 22:20:29 -05001078func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1079 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1080 var res interface{}
1081 var err error
1082 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1083 if res, err = agent.downloadImage(ctx, img); err != nil {
1084 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1085 res = err
1086 }
1087 } else {
1088 res = status.Errorf(codes.NotFound, "%s", img.Id)
1089 }
1090 sendResponse(ctx, ch, res)
1091}
1092
1093func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1094 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1095 var res interface{}
1096 var err error
1097 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1098 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1099 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1100 res = err
1101 }
1102 } else {
1103 res = status.Errorf(codes.NotFound, "%s", img.Id)
1104 }
1105 sendResponse(ctx, ch, res)
1106}
1107
1108func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1109 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1110 var res interface{}
1111 var err error
1112 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1113 if res, err = agent.activateImage(ctx, img); err != nil {
1114 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1115 res = err
1116 }
1117 } else {
1118 res = status.Errorf(codes.NotFound, "%s", img.Id)
1119 }
1120 sendResponse(ctx, ch, res)
1121}
1122
1123func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1124 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1125 var res interface{}
1126 var err error
1127 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1128 if res, err = agent.revertImage(ctx, img); err != nil {
1129 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1130 res = err
1131 }
1132 } else {
1133 res = status.Errorf(codes.NotFound, "%s", img.Id)
1134 }
1135 sendResponse(ctx, ch, res)
1136}
1137
1138func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1139 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1140 var res interface{}
1141 var err error
1142 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1143 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1144 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1145 res = err
1146 }
1147 } else {
1148 res = status.Errorf(codes.NotFound, "%s", img.Id)
1149 }
1150 sendResponse(ctx, ch, res)
1151}
1152
khenaidoof5a5bfa2019-01-23 22:20:29 -05001153func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1154 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1155 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1156 if err := agent.updateImageDownload(img); err != nil {
1157 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1158 return err
1159 }
1160 } else {
1161 return status.Errorf(codes.NotFound, "%s", img.Id)
1162 }
1163 return nil
1164}
1165
1166func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1167 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1168 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1169 return agent.getImageDownload(ctx, img)
1170 }
1171 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1172}
1173
1174func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1175 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1176 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1177 return agent.listImageDownloads(ctx, deviceId)
1178 }
1179 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1180}
1181
khenaidoo0a822f92019-05-08 15:15:57 -04001182func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1183 log.Info("SetAdminStateToEnable")
1184 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1185 return agent.updateAdminState(voltha.AdminState_ENABLED)
1186 }
1187 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1188}
1189
khenaidoo92e62c52018-10-03 14:02:54 -04001190func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001191 log.Info("activateDevice")
1192 return nil
1193}
1194
khenaidoo92e62c52018-10-03 14:02:54 -04001195func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1196 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001197 return nil
1198}
1199
khenaidoo92e62c52018-10-03 14:02:54 -04001200func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001201 log.Info("abandonDevice")
1202 return nil
1203}
1204
khenaidoo92e62c52018-10-03 14:02:54 -04001205func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001206 log.Info("reEnableDevice")
1207 return nil
1208}
1209
khenaidoo92e62c52018-10-03 14:02:54 -04001210func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001211 log.Info("noOp")
1212 return nil
1213}
1214
khenaidoo92e62c52018-10-03 14:02:54 -04001215func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001216 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001217 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001218}
1219
khenaidoo0a822f92019-05-08 15:15:57 -04001220func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
1221 log.Errorw("NotifyInvalidTransition", log.Fields{"device": pcDevice.Id, "adminState": pcDevice.AdminState})
1222 //TODO: notify over kafka?
1223 return nil
1224}
1225
khenaidoob9203542018-09-17 22:56:37 -04001226func funcName(f interface{}) string {
1227 p := reflect.ValueOf(f).Pointer()
1228 rf := runtime.FuncForPC(p)
1229 return rf.Name()
1230}
1231
1232func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
1233 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
1234 agent.updateDeviceAttribute(attribute, value)
1235 }
1236}
1237
1238func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -04001239 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001240 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -04001241 return &device.ParentId
1242 }
1243 return nil
1244}
serkant.uluderya334479d2019-04-10 08:26:15 -07001245
1246func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1247 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1248 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1249 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1250 var res interface{}
1251 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1252 res = agent.simulateAlarm(ctx, simulatereq)
1253 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1254 }
1255 //TODO CLI always get successful response
1256 sendResponse(ctx, ch, res)
1257}