blob: f52345e33890646ff261f34a54f6578366431114 [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 {
273 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
274 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,
745 channelId int64, vendorId string, serialNumber string, onuId int64) 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})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400761 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
762 }
763
Matt Jeanneret4e241952019-02-28 11:16:04 -0500764 if _, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
765 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
766 return status.Errorf(codes.AlreadyExists, "%s", serialNumber)
767 }
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
khenaidoob9203542018-09-17 22:56:37 -0400784 return nil
785}
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")
khenaidoob9203542018-09-17 22:56:37 -0400835 var logicalId *string
836 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400837 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400838 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
839 return err
840 }
841 // Update the parent device with the logical id
842 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
843 return nil
844}
845
khenaidoo0a822f92019-05-08 15:15:57 -0400846func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
847 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -0400848 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400849 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400850 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
851 return err
852 }
853 // Remove the logical device Id from the parent device
854 logicalId := ""
855 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
856 return nil
857}
858
khenaidoo0a822f92019-05-08 15:15:57 -0400859func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400860 log.Info("deleteLogicalPort")
861 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400862 // Get the logical port associated with this device
863 var lPortId *voltha.LogicalPortId
864 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400865 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400866 return err
867 }
868 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
869 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400870 return err
871 }
khenaidoo92e62c52018-10-03 14:02:54 -0400872 return nil
873}
874
khenaidoo0a822f92019-05-08 15:15:57 -0400875func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
876 log.Info("deleteLogicalPorts")
877 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
878 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
879 return err
880 }
881 return nil
882}
883
khenaidoo92e62c52018-10-03 14:02:54 -0400884func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
885 // Sanity check
886 if childDevice.Root {
887 // childDevice is the parent device
888 return childDevice
889 }
khenaidoo19d7b632018-10-30 10:49:50 -0400890 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400891 return parentDevice
892}
893
khenaidoo0a822f92019-05-08 15:15:57 -0400894//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
895//cannot manage the child devices. This will trigger the Core to disable all the child devices.
896func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
897 log.Debug("childDevicesLost")
898 var err error
899 var parentDevice *voltha.Device
900 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
901 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
902 return err
903 }
904 return dMgr.DisableAllChildDevices(parentDevice)
905}
906
907//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
908// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
909func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
910 log.Debug("childDevicesDetected")
911 var err error
912 var parentDevice *voltha.Device
913 var childDeviceIds []string
914
915 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
916 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
917 return err
918 }
919
920 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
921 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
922 }
923 if len(childDeviceIds) == 0 {
924 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
925 }
926 allChildDisable := true
927 for _, childDeviceId := range childDeviceIds {
928 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
929 if err = agent.enableDevice(nil); err != nil {
930 log.Errorw("failure-enable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
931 allChildDisable = false
932 }
933 }
934 }
935 if !allChildDisable {
936 return err
937 }
938 return nil
939}
940
khenaidoo4d4802d2018-10-04 21:59:49 -0400941/*
942All the functions below are callback functions where they are invoked with the latest and previous data. We can
943therefore use the data as is without trying to get the latest from the model.
944*/
945
khenaidoo0a822f92019-05-08 15:15:57 -0400946//DisableAllChildDevices is invoked as a callback when the parent device is disabled
947func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
948 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -0400949 var childDeviceIds []string
950 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400951 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
952 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400953 }
954 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400955 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400956 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400957 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400958 for _, childDeviceId := range childDeviceIds {
959 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
960 if err = agent.disableDevice(nil); err != nil {
961 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400962 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400963 }
964 }
965 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400966 if !allChildDisable {
967 return err
968 }
khenaidoo92e62c52018-10-03 14:02:54 -0400969 return nil
970}
971
khenaidoo0a822f92019-05-08 15:15:57 -0400972//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
973func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
974 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -0400975 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400976 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400977 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
978 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400979 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400980 if len(childDeviceIds) == 0 {
981 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
982 }
983 allChildDeleted := true
984 for _, childDeviceId := range childDeviceIds {
985 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
986 if err = agent.deleteDevice(nil); err != nil {
987 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
988 allChildDeleted = false
989 } else {
990 agent.stop(nil)
991 dMgr.deleteDeviceAgentToMap(agent)
992 }
993 }
994 }
995 if !allChildDeleted {
996 return err
997 }
998 return nil
999}
1000
khenaidoo6d62c002019-05-15 21:57:03 -04001001//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1002// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1003// device during a delete device operation.
1004func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentId(id string) []string {
1005 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1006 deviceIds := make([]string, 0)
1007 dMgr.lockDeviceAgentsMap.RLock()
1008 defer dMgr.lockDeviceAgentsMap.RUnlock()
1009 for deviceId, agent := range dMgr.deviceAgents {
1010 if agent.parentId == id {
1011 deviceIds = append(deviceIds, deviceId)
1012 }
1013 }
1014 return deviceIds
1015}
1016
khenaidoo4d4802d2018-10-04 21:59:49 -04001017//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1018func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1019 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001020 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001021 if parentDevice != nil {
1022 for _, port := range parentDevice.Ports {
1023 for _, peer := range port.Peers {
1024 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1025 }
khenaidoo92e62c52018-10-03 14:02:54 -04001026 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001027 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001028 }
1029 return childDeviceIds, nil
1030}
1031
khenaidoo297cd252019-02-07 22:10:23 -05001032//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1033func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
1034 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
1035 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
1036 childDevices := make([]*voltha.Device, 0)
1037 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
1038 for _, deviceId := range childDeviceIds {
1039 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
1040 childDevices = append(childDevices, d)
1041 }
1042 }
1043 }
1044 return &voltha.Devices{Items: childDevices}, nil
1045 }
1046 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
1047}
1048
khenaidoo0a822f92019-05-08 15:15:57 -04001049func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001050 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -04001051 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001052 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1053 return err
1054 }
1055 return nil
1056}
1057
khenaidoof5a5bfa2019-01-23 22:20:29 -05001058func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1059 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1060 var res interface{}
1061 var err error
1062 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1063 if res, err = agent.downloadImage(ctx, img); err != nil {
1064 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1065 res = err
1066 }
1067 } else {
1068 res = status.Errorf(codes.NotFound, "%s", img.Id)
1069 }
1070 sendResponse(ctx, ch, res)
1071}
1072
1073func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1074 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1075 var res interface{}
1076 var err error
1077 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1078 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1079 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1080 res = err
1081 }
1082 } else {
1083 res = status.Errorf(codes.NotFound, "%s", img.Id)
1084 }
1085 sendResponse(ctx, ch, res)
1086}
1087
1088func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1089 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1090 var res interface{}
1091 var err error
1092 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1093 if res, err = agent.activateImage(ctx, img); err != nil {
1094 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1095 res = err
1096 }
1097 } else {
1098 res = status.Errorf(codes.NotFound, "%s", img.Id)
1099 }
1100 sendResponse(ctx, ch, res)
1101}
1102
1103func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1104 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1105 var res interface{}
1106 var err error
1107 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1108 if res, err = agent.revertImage(ctx, img); err != nil {
1109 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1110 res = err
1111 }
1112 } else {
1113 res = status.Errorf(codes.NotFound, "%s", img.Id)
1114 }
1115 sendResponse(ctx, ch, res)
1116}
1117
1118func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1119 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1120 var res interface{}
1121 var err error
1122 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1123 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1124 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1125 res = err
1126 }
1127 } else {
1128 res = status.Errorf(codes.NotFound, "%s", img.Id)
1129 }
1130 sendResponse(ctx, ch, res)
1131}
1132
khenaidoof5a5bfa2019-01-23 22:20:29 -05001133func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1134 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1135 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1136 if err := agent.updateImageDownload(img); err != nil {
1137 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1138 return err
1139 }
1140 } else {
1141 return status.Errorf(codes.NotFound, "%s", img.Id)
1142 }
1143 return nil
1144}
1145
1146func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1147 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1148 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1149 return agent.getImageDownload(ctx, img)
1150 }
1151 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1152}
1153
1154func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1155 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1156 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1157 return agent.listImageDownloads(ctx, deviceId)
1158 }
1159 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1160}
1161
khenaidoo0a822f92019-05-08 15:15:57 -04001162func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1163 log.Info("SetAdminStateToEnable")
1164 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1165 return agent.updateAdminState(voltha.AdminState_ENABLED)
1166 }
1167 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1168}
1169
khenaidoo92e62c52018-10-03 14:02:54 -04001170func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001171 log.Info("activateDevice")
1172 return nil
1173}
1174
khenaidoo92e62c52018-10-03 14:02:54 -04001175func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1176 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001177 return nil
1178}
1179
khenaidoo92e62c52018-10-03 14:02:54 -04001180func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001181 log.Info("abandonDevice")
1182 return nil
1183}
1184
khenaidoo92e62c52018-10-03 14:02:54 -04001185func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001186 log.Info("reEnableDevice")
1187 return nil
1188}
1189
khenaidoo92e62c52018-10-03 14:02:54 -04001190func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001191 log.Info("noOp")
1192 return nil
1193}
1194
khenaidoo92e62c52018-10-03 14:02:54 -04001195func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001196 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001197 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001198}
1199
khenaidoo0a822f92019-05-08 15:15:57 -04001200func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
1201 log.Errorw("NotifyInvalidTransition", log.Fields{"device": pcDevice.Id, "adminState": pcDevice.AdminState})
1202 //TODO: notify over kafka?
1203 return nil
1204}
1205
khenaidoob9203542018-09-17 22:56:37 -04001206func funcName(f interface{}) string {
1207 p := reflect.ValueOf(f).Pointer()
1208 rf := runtime.FuncForPC(p)
1209 return rf.Name()
1210}
1211
1212func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
1213 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
1214 agent.updateDeviceAttribute(attribute, value)
1215 }
1216}
1217
1218func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -04001219 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001220 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -04001221 return &device.ParentId
1222 }
1223 return nil
1224}
serkant.uluderya334479d2019-04-10 08:26:15 -07001225
1226func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1227 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1228 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1229 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1230 var res interface{}
1231 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1232 res = agent.simulateAlarm(ctx, simulatereq)
1233 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1234 }
1235 //TODO CLI always get successful response
1236 sendResponse(ctx, ch, res)
1237}