blob: f6540e488586b6509297fbbde0fc0c5d28a9903c [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"
William Kurkiandaa6bb22019-03-07 12:26:28 -050024 ic "github.com/opencord/voltha-protos/go/inter_container"
25 ofp "github.com/opencord/voltha-protos/go/openflow_13"
26 "github.com/opencord/voltha-protos/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040027 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/status"
29 "reflect"
30 "runtime"
31 "sync"
32)
33
34type DeviceManager struct {
35 deviceAgents map[string]*DeviceAgent
khenaidoo2c6a0992019-04-29 13:46:56 -040036 rootDevices map[string]bool
37 lockRootDeviceMap sync.RWMutex
Richard Jankowski199fd862019-03-18 14:49:51 -040038 core *Core
khenaidoob9203542018-09-17 22:56:37 -040039 adapterProxy *AdapterProxy
khenaidoo297cd252019-02-07 22:10:23 -050040 adapterMgr *AdapterManager
khenaidoob9203542018-09-17 22:56:37 -040041 logicalDeviceMgr *LogicalDeviceManager
khenaidoo43c82122018-11-22 18:38:28 -050042 kafkaICProxy *kafka.InterContainerProxy
khenaidoob9203542018-09-17 22:56:37 -040043 stateTransitions *TransitionMap
khenaidoo9a468962018-09-19 15:33:13 -040044 clusterDataProxy *model.Proxy
khenaidood2b6df92018-12-13 16:37:20 -050045 coreInstanceId string
khenaidoob9203542018-09-17 22:56:37 -040046 exitChannel chan int
khenaidoo2c6a0992019-04-29 13:46:56 -040047 defaultTimeout int64
khenaidoob9203542018-09-17 22:56:37 -040048 lockDeviceAgentsMap sync.RWMutex
49}
50
Richard Jankowski199fd862019-03-18 14:49:51 -040051func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040052 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040053 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040054 deviceMgr.exitChannel = make(chan int, 1)
55 deviceMgr.deviceAgents = make(map[string]*DeviceAgent)
khenaidoo2c6a0992019-04-29 13:46:56 -040056 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040057 deviceMgr.kafkaICProxy = core.kmp
58 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp)
59 deviceMgr.coreInstanceId = core.instanceId
60 deviceMgr.clusterDataProxy = core.clusterDataProxy
61 deviceMgr.adapterMgr = core.adapterMgr
khenaidoob9203542018-09-17 22:56:37 -040062 deviceMgr.lockDeviceAgentsMap = sync.RWMutex{}
khenaidoo2c6a0992019-04-29 13:46:56 -040063 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
64 deviceMgr.defaultTimeout = core.config.DefaultCoreTimeout
khenaidoob9203542018-09-17 22:56:37 -040065 return &deviceMgr
66}
67
khenaidoo4d4802d2018-10-04 21:59:49 -040068func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040069 log.Info("starting-device-manager")
70 dMgr.logicalDeviceMgr = logicalDeviceMgr
71 dMgr.stateTransitions = NewTransitionMap(dMgr)
72 log.Info("device-manager-started")
73}
74
khenaidoo4d4802d2018-10-04 21:59:49 -040075func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040076 log.Info("stopping-device-manager")
77 dMgr.exitChannel <- 1
78 log.Info("device-manager-stopped")
79}
80
81func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
82 if ctx.Err() == nil {
83 // Returned response only of the ctx has not been cancelled/timeout/etc
84 // Channel is automatically closed when a context is Done
85 ch <- result
86 log.Debugw("sendResponse", log.Fields{"result": result})
87 } else {
88 // Should the transaction be reverted back?
89 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
90 }
91}
92
93func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
94 dMgr.lockDeviceAgentsMap.Lock()
khenaidoo2c6a0992019-04-29 13:46:56 -040095 //defer dMgr.lockDeviceAgentsMap.Unlock()
khenaidoob9203542018-09-17 22:56:37 -040096 if _, exist := dMgr.deviceAgents[agent.deviceId]; !exist {
97 dMgr.deviceAgents[agent.deviceId] = agent
98 }
khenaidoo2c6a0992019-04-29 13:46:56 -040099 dMgr.lockDeviceAgentsMap.Unlock()
100 dMgr.lockRootDeviceMap.Lock()
101 defer dMgr.lockRootDeviceMap.Unlock()
102 dMgr.rootDevices[agent.deviceId] = agent.isRootdevice
103
khenaidoob9203542018-09-17 22:56:37 -0400104}
105
khenaidoo4d4802d2018-10-04 21:59:49 -0400106func (dMgr *DeviceManager) deleteDeviceAgentToMap(agent *DeviceAgent) {
107 dMgr.lockDeviceAgentsMap.Lock()
khenaidoo2c6a0992019-04-29 13:46:56 -0400108 //defer dMgr.lockDeviceAgentsMap.Unlock()
khenaidoo4d4802d2018-10-04 21:59:49 -0400109 delete(dMgr.deviceAgents, agent.deviceId)
khenaidoo2c6a0992019-04-29 13:46:56 -0400110 dMgr.lockDeviceAgentsMap.Unlock()
111 dMgr.lockRootDeviceMap.Lock()
112 defer dMgr.lockRootDeviceMap.Unlock()
113 delete(dMgr.rootDevices, agent.deviceId)
114
khenaidoo4d4802d2018-10-04 21:59:49 -0400115}
116
khenaidoo297cd252019-02-07 22:10:23 -0500117// 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 -0400118func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400119 dMgr.lockDeviceAgentsMap.RLock()
khenaidoob9203542018-09-17 22:56:37 -0400120 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400121 dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoob9203542018-09-17 22:56:37 -0400122 return agent
khenaidoo297cd252019-02-07 22:10:23 -0500123 } else {
124 // Try to load into memory - loading will also create the device agent
khenaidoo1ce37ad2019-03-24 22:07:24 -0400125 dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoo297cd252019-02-07 22:10:23 -0500126 if err := dMgr.load(deviceId); err == nil {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400127 dMgr.lockDeviceAgentsMap.RLock()
128 defer dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoo297cd252019-02-07 22:10:23 -0500129 if agent, ok = dMgr.deviceAgents[deviceId]; ok {
130 return agent
131 }
132 }
khenaidoob9203542018-09-17 22:56:37 -0400133 }
134 return nil
135}
136
khenaidoo297cd252019-02-07 22:10:23 -0500137// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500138func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400139 dMgr.lockDeviceAgentsMap.RLock()
140 defer dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoo7ccedd52018-12-14 16:48:54 -0500141 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
khenaidoo2c6a0992019-04-29 13:46:56 -0400142 for key := range dMgr.deviceAgents {
khenaidoo7ccedd52018-12-14 16:48:54 -0500143 result.Items = append(result.Items, &voltha.ID{Id: key})
144 }
145 return result
146}
147
khenaidoob9203542018-09-17 22:56:37 -0400148func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400149 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400150
khenaidoo5e677ae2019-02-28 17:26:29 -0500151 // Ensure this device is set as root
152 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400153 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400154 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400155 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500156 agent.start(ctx, false)
khenaidoob9203542018-09-17 22:56:37 -0400157
khenaidoo92e62c52018-10-03 14:02:54 -0400158 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400159}
160
161func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400162 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400163 var res interface{}
164 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
165 res = agent.enableDevice(ctx)
166 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400167 }
168
169 sendResponse(ctx, ch, res)
170}
171
khenaidoo92e62c52018-10-03 14:02:54 -0400172func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
173 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400174 var res interface{}
175 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
176 res = agent.disableDevice(ctx)
177 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400178 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400179 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400180 }
khenaidoo92e62c52018-10-03 14:02:54 -0400181
182 sendResponse(ctx, ch, res)
183}
184
khenaidoo4d4802d2018-10-04 21:59:49 -0400185func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
186 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
187 var res interface{}
188 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
189 res = agent.rebootDevice(ctx)
190 log.Debugw("rebootDevice-result", log.Fields{"result": res})
191 } else {
192 res = status.Errorf(codes.NotFound, "%s", id.Id)
193 }
194 sendResponse(ctx, ch, res)
195}
196
197func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
198 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
199 var res interface{}
200 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
201 res = agent.deleteDevice(ctx)
202 if res == nil { //Success
203 agent.stop(ctx)
204 dMgr.deleteDeviceAgentToMap(agent)
Richard Jankowski199fd862019-03-18 14:49:51 -0400205 dMgr.core.deviceOwnership.AbandonDevice(id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400206 }
207 log.Debugw("deleteDevice-result", log.Fields{"result": res})
208 } else {
209 res = status.Errorf(codes.NotFound, "%s", id.Id)
210 }
211 sendResponse(ctx, ch, res)
212}
213
khenaidoo297cd252019-02-07 22:10:23 -0500214// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400215func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
216 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400217 if agent := dMgr.getDeviceAgent(id); agent != nil {
218 return agent.getDevice()
219 }
220 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400221}
222
Matt Jeanneret4e241952019-02-28 11:16:04 -0500223func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
Matt Jeanneret0c5088c2019-04-22 16:16:19 -0400224 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber,
225 "parentPortNo": parentPortNo, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500226
227 var parentDevice *voltha.Device
228 var err error
229 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
230 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
231 }
232 var childDeviceIds []string
233 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
234 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
235 }
236 if len(childDeviceIds) == 0 {
237 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
238 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
239 }
240
241 var foundChildDevice *voltha.Device
242 for _, childDeviceId := range childDeviceIds {
243 found := false
244 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
245
246 foundOnuId := false
247 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
248 if searchDevice.ParentPortNo == uint32(parentPortNo) {
249 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
250 foundOnuId = true
251 }
252 }
253
254 foundSerialNumber := false
255 if searchDevice.SerialNumber == serialNumber {
256 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
257 foundSerialNumber = true
258 }
259
260 // if both onuId and serialNumber are provided both must be true for the device to be found
261 // otherwise whichever one found a match is good enough
262 if onuId > 0 && serialNumber != "" {
263 found = foundOnuId && foundSerialNumber
264 } else {
265 found = foundOnuId || foundSerialNumber
266 }
267
268 if found == true {
269 foundChildDevice = searchDevice
270 break
271 }
272 }
273 }
274
275 if foundChildDevice != nil {
276 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
277 return foundChildDevice, nil
278 }
279
280 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
281 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
282 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
283}
284
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500285func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
286 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
287
288 var parentDevice *voltha.Device
289 var err error
290 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
291 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
292 }
293 var childDeviceIds []string
294 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
295 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
296 }
297 if len(childDeviceIds) == 0 {
298 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
299 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
300 }
301
302 var foundChildDevice *voltha.Device
303 for _, childDeviceId := range childDeviceIds {
304 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
305 if searchDevice.ProxyAddress == proxyAddress {
306 foundChildDevice = searchDevice
307 break
308 }
309 }
310 }
311
312 if foundChildDevice != nil {
313 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
314 return foundChildDevice, nil
315 }
316
317 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
318 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
319}
320
khenaidoo297cd252019-02-07 22:10:23 -0500321func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400322 dMgr.lockDeviceAgentsMap.RLock()
323 defer dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoo297cd252019-02-07 22:10:23 -0500324 _, exist := dMgr.deviceAgents[id]
325 return exist
326}
327
khenaidoo19d7b632018-10-30 10:49:50 -0400328func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400329 dMgr.lockRootDeviceMap.RLock()
330 defer dMgr.lockRootDeviceMap.RUnlock()
331 if exist := dMgr.rootDevices[id]; exist {
332 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400333 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400334 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400335}
336
Stephane Barbarieaa467942019-02-06 14:09:44 -0500337// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400338func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400339 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400340 result := &voltha.Devices{}
Stephane Barbarieaa467942019-02-06 14:09:44 -0500341 if devices := dMgr.clusterDataProxy.List("/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500342 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500343 // If device is not in memory then set it up
344 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400345 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500346 if err := agent.start(nil, true); err != nil {
347 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
348 agent.stop(nil)
349 } else {
350 dMgr.addDeviceAgentToMap(agent)
351 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500352 }
353 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400354 }
355 }
356 return result, nil
357}
358
khenaidoo297cd252019-02-07 22:10:23 -0500359// loadDevice loads the deviceId in memory, if not present
360func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
361 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
362 // Sanity check
363 if deviceId == "" {
364 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
365 }
366 if !dMgr.IsDeviceInCache(deviceId) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400367 agent := newDeviceAgent(dMgr.adapterProxy, &voltha.Device{Id: deviceId}, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500368 if err := agent.start(nil, true); err != nil {
369 agent.stop(nil)
370 return nil, err
371 }
372 dMgr.addDeviceAgentToMap(agent)
373 }
374 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
375 return agent, nil
376 }
Matt Jeanneret4e241952019-02-28 11:16:04 -0500377 return nil, status.Error(codes.NotFound, deviceId) // This should not happen
khenaidoo297cd252019-02-07 22:10:23 -0500378}
379
380// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
381func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
382 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
383 if device.Root {
384 // Scenario A
385 if device.ParentId != "" {
386 // Load logical device if needed.
387 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
388 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
389 }
390 } else {
391 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
392 }
393 // Load all child devices, if needed
394 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
395 for _, childDeviceId := range childDeviceIds {
396 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
397 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId})
398 return err
399 }
400 }
401 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
402 } else {
403 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
404 }
405 }
406 return nil
407}
408
409// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
410// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
411// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
412// and the proceed with the request.
413func (dMgr *DeviceManager) load(deviceId string) error {
414 log.Debug("load...")
415 // First load the device - this may fail in case the device was deleted intentionally by the other core
416 var dAgent *DeviceAgent
417 var err error
418 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
419 log.Warnw("failure-loading-device", log.Fields{"deviceId": deviceId})
420 return err
421 }
422 // Get the loaded device details
423 var device *voltha.Device
424 if device, err = dAgent.getDevice(); err != nil {
425 return err
426 }
427
428 // If the device is in Pre-provisioning or deleted state stop here
429 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
430 return nil
431 }
432
433 // Now we face two scenarios
434 if device.Root {
435 // Load all children as well as the parent of this device (logical_device)
436 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
437 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
438 return err
439 }
440 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
441 } else {
442 // Scenario B - use the parentId of that device (root device) to trigger the loading
443 if device.ParentId != "" {
444 return dMgr.load(device.ParentId)
445 }
446 }
447 return nil
448}
449
khenaidoo7ccedd52018-12-14 16:48:54 -0500450// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
451func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
452 log.Debug("ListDeviceIDs")
453 // Report only device IDs that are in the device agent map
454 return dMgr.listDeviceIdsFromMap(), nil
455}
456
457//ReconcileDevices is a request to a voltha core to managed a list of devices based on their IDs
458func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
459 log.Debug("ReconcileDevices")
460 var res interface{}
461 if ids != nil {
462 toReconcile := len(ids.Items)
463 reconciled := 0
464 for _, id := range ids.Items {
465 // Act on the device only if its not present in the agent map
khenaidoo297cd252019-02-07 22:10:23 -0500466 if !dMgr.IsDeviceInCache(id.Id) {
khenaidoo7ccedd52018-12-14 16:48:54 -0500467 // Device Id not in memory
468 log.Debugw("reconciling-device", log.Fields{"id": id.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500469 // Load device from dB
khenaidoo2c6a0992019-04-29 13:46:56 -0400470 agent := newDeviceAgent(dMgr.adapterProxy, &voltha.Device{Id: id.Id}, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500471 if err := agent.start(nil, true); err != nil {
472 log.Warnw("failure-loading-device", log.Fields{"deviceId": id.Id})
473 agent.stop(nil)
khenaidoo7ccedd52018-12-14 16:48:54 -0500474 } else {
khenaidoo297cd252019-02-07 22:10:23 -0500475 dMgr.addDeviceAgentToMap(agent)
476 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500477 }
478 } else {
479 reconciled += 1
480 }
481 }
482 if toReconcile != reconciled {
483 res = status.Errorf(codes.DataLoss, "less-device-reconciled:%d/%d", reconciled, toReconcile)
484 }
485 } else {
486 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
487 }
488 sendResponse(ctx, ch, res)
489}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500490
khenaidoob9203542018-09-17 22:56:37 -0400491func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400492 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400493 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
494 return agent.updateDevice(device)
495 }
496 return status.Errorf(codes.NotFound, "%s", device.Id)
497}
498
499func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
500 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400501 if err := agent.addPort(port); err != nil {
502 return err
503 }
504 // Setup peer ports
505 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
506 for _, peerPort := range port.Peers {
507 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
508 if err := agent.addPeerPort(meAsPeer); err != nil {
509 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
510 return err
511 }
512 }
513 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400514 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
515 // then a logical port will be added to the logical device and the device graph generated. If the port is a
516 // PON port then only the device graph will be generated.
517 if device, err := dMgr.GetDevice(deviceId); err == nil {
518 go dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
519 } else {
520 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
521 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400522 }
khenaidoo92e62c52018-10-03 14:02:54 -0400523 return nil
524 } else {
525 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400526 }
khenaidoob9203542018-09-17 22:56:37 -0400527}
528
khenaidoo2c6a0992019-04-29 13:46:56 -0400529func (dMgr *DeviceManager) addFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) error {
530 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400531 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400532 return agent.addFlowsAndGroups(flows, groups)
533 //go agent.addFlowsAndGroups(flows, groups)
534 //return nil
khenaidoo19d7b632018-10-30 10:49:50 -0400535 }
536 return status.Errorf(codes.NotFound, "%s", deviceId)
537}
538
khenaidoob9203542018-09-17 22:56:37 -0400539func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
540 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
541 return agent.updatePmConfigs(pmConfigs)
542 }
543 return status.Errorf(codes.NotFound, "%s", deviceId)
544}
545
khenaidoo79232702018-12-04 11:00:41 -0500546func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400547 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400548 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
549 return agent.getSwitchCapability(ctx)
550 }
551 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
552}
553
khenaidoo92e62c52018-10-03 14:02:54 -0400554func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
555 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400556 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400557 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400558 }
559 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400560
khenaidoob9203542018-09-17 22:56:37 -0400561}
562
khenaidoo79232702018-12-04 11:00:41 -0500563func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400564 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400565 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
566 return agent.getPortCapability(ctx, portNo)
567 }
568 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
569}
570
khenaidoo92e62c52018-10-03 14:02:54 -0400571func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
572 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400573 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400574 return agent.updateDeviceStatus(operStatus, connStatus)
575 }
576 return status.Errorf(codes.NotFound, "%s", deviceId)
577}
578
khenaidoo4d4802d2018-10-04 21:59:49 -0400579func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
580 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
581 var parentDevice *voltha.Device
582 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400583 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400584 return status.Errorf(codes.Aborted, "%s", err.Error())
585 }
586 var childDeviceIds []string
587 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
588 return status.Errorf(codes.Aborted, "%s", err.Error())
589 }
590 if len(childDeviceIds) == 0 {
591 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
592 }
593 for _, childDeviceId := range childDeviceIds {
594 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
595 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
596 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
597 }
598 }
599 }
600 return nil
601}
602
khenaidoo92e62c52018-10-03 14:02:54 -0400603func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
604 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
605 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
606 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400607 }
608 return status.Errorf(codes.NotFound, "%s", deviceId)
609}
610
Matt Jeanneret4e241952019-02-28 11:16:04 -0500611func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
612 channelId int64, vendorId string, serialNumber string, onuId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400613 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400614
615 // Create the ONU device
616 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400617 childDevice.Type = deviceType
618 childDevice.ParentId = parentDeviceId
619 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500620 childDevice.VendorId = vendorId
621 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400622 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400623
624 //Get parent device type
625 parent, err := dMgr.GetDevice(parentDeviceId)
626 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500627 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400628 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
629 }
630
Matt Jeanneret4e241952019-02-28 11:16:04 -0500631 if _, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
632 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
633 return status.Errorf(codes.AlreadyExists, "%s", serialNumber)
634 }
635
636 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400637
638 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400639 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400640 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500641 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400642
643 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400644 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500645 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400646 }
647
khenaidoo79232702018-12-04 11:00:41 -0500648 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500649 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500650
khenaidoob9203542018-09-17 22:56:37 -0400651 return nil
652}
653
654func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
655 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400656 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
657 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500658 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400659 return nil
khenaidoob9203542018-09-17 22:56:37 -0400660 }
khenaidoo92e62c52018-10-03 14:02:54 -0400661 for _, handler := range handlers {
662 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
663 if err := handler(current); err != nil {
664 return err
665 }
666 }
khenaidoob9203542018-09-17 22:56:37 -0400667 return nil
668}
669
khenaidoofdbad6e2018-11-06 22:26:38 -0500670func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
671 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
672 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
673 return agent.packetOut(outPort, packet)
674 }
675 return status.Errorf(codes.NotFound, "%s", deviceId)
676}
677
khenaidoo297cd252019-02-07 22:10:23 -0500678func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500679 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
680 // Get the logical device Id based on the deviceId
681 var device *voltha.Device
682 var err error
683 if device, err = dMgr.GetDevice(deviceId); err != nil {
684 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
685 return err
686 }
khenaidoo43c82122018-11-22 18:38:28 -0500687 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500688 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
689 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
690 }
691
khenaidoo297cd252019-02-07 22:10:23 -0500692 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500693 return err
694 }
695 return nil
696}
697
khenaidoo92e62c52018-10-03 14:02:54 -0400698func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400699 log.Info("createLogicalDevice")
700 var logicalId *string
701 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400702 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400703 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
704 return err
705 }
706 // Update the parent device with the logical id
707 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
708 return nil
709}
710
khenaidoo92e62c52018-10-03 14:02:54 -0400711func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
712 log.Info("deleteLogicalDevice")
713 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400714 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400715 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
716 return err
717 }
718 // Remove the logical device Id from the parent device
719 logicalId := ""
720 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
721 return nil
722}
723
khenaidoo19d7b632018-10-30 10:49:50 -0400724func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400725 log.Info("deleteLogicalPort")
726 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400727 // Get the logical port associated with this device
728 var lPortId *voltha.LogicalPortId
729 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400730 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400731 return err
732 }
733 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
734 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400735 return err
736 }
khenaidoo92e62c52018-10-03 14:02:54 -0400737 return nil
738}
739
740func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
741 // Sanity check
742 if childDevice.Root {
743 // childDevice is the parent device
744 return childDevice
745 }
khenaidoo19d7b632018-10-30 10:49:50 -0400746 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400747 return parentDevice
748}
749
khenaidoo4d4802d2018-10-04 21:59:49 -0400750/*
751All the functions below are callback functions where they are invoked with the latest and previous data. We can
752therefore use the data as is without trying to get the latest from the model.
753*/
754
755//disableAllChildDevices is invoked as a callback when the parent device is disabled
756func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400757 log.Debug("disableAllChildDevices")
758 var childDeviceIds []string
759 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400760 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
761 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400762 }
763 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400764 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400765 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400766 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400767 for _, childDeviceId := range childDeviceIds {
768 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
769 if err = agent.disableDevice(nil); err != nil {
770 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400771 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400772 }
773 }
774 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400775 if !allChildDisable {
776 return err
777 }
khenaidoo92e62c52018-10-03 14:02:54 -0400778 return nil
779}
780
khenaidoo4d4802d2018-10-04 21:59:49 -0400781//deleteAllChildDevices is invoked as a callback when the parent device is deleted
782func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
783 log.Debug("deleteAllChildDevices")
784 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400785 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400786 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
787 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400788 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400789 if len(childDeviceIds) == 0 {
790 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
791 }
792 allChildDeleted := true
793 for _, childDeviceId := range childDeviceIds {
794 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
795 if err = agent.deleteDevice(nil); err != nil {
796 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
797 allChildDeleted = false
798 } else {
799 agent.stop(nil)
800 dMgr.deleteDeviceAgentToMap(agent)
801 }
802 }
803 }
804 if !allChildDeleted {
805 return err
806 }
807 return nil
808}
809
810//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
811func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
812 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400813 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400814 if parentDevice != nil {
815 for _, port := range parentDevice.Ports {
816 for _, peer := range port.Peers {
817 childDeviceIds = append(childDeviceIds, peer.DeviceId)
818 }
khenaidoo92e62c52018-10-03 14:02:54 -0400819 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400820 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -0400821 }
822 return childDeviceIds, nil
823}
824
khenaidoo297cd252019-02-07 22:10:23 -0500825//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
826func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
827 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
828 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
829 childDevices := make([]*voltha.Device, 0)
830 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
831 for _, deviceId := range childDeviceIds {
832 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
833 childDevices = append(childDevices, d)
834 }
835 }
836 }
837 return &voltha.Devices{Items: childDevices}, nil
838 }
839 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
840}
841
khenaidoofc1314d2019-03-14 09:34:21 -0400842func (dMgr *DeviceManager) setupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400843 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -0400844 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400845 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
846 return err
847 }
848 return nil
849}
850
khenaidoof5a5bfa2019-01-23 22:20:29 -0500851func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
852 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
853 var res interface{}
854 var err error
855 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
856 if res, err = agent.downloadImage(ctx, img); err != nil {
857 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
858 res = err
859 }
860 } else {
861 res = status.Errorf(codes.NotFound, "%s", img.Id)
862 }
863 sendResponse(ctx, ch, res)
864}
865
866func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
867 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
868 var res interface{}
869 var err error
870 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
871 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
872 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
873 res = err
874 }
875 } else {
876 res = status.Errorf(codes.NotFound, "%s", img.Id)
877 }
878 sendResponse(ctx, ch, res)
879}
880
881func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
882 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
883 var res interface{}
884 var err error
885 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
886 if res, err = agent.activateImage(ctx, img); err != nil {
887 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
888 res = err
889 }
890 } else {
891 res = status.Errorf(codes.NotFound, "%s", img.Id)
892 }
893 sendResponse(ctx, ch, res)
894}
895
896func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
897 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
898 var res interface{}
899 var err error
900 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
901 if res, err = agent.revertImage(ctx, img); err != nil {
902 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
903 res = err
904 }
905 } else {
906 res = status.Errorf(codes.NotFound, "%s", img.Id)
907 }
908 sendResponse(ctx, ch, res)
909}
910
911func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
912 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
913 var res interface{}
914 var err error
915 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
916 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
917 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
918 res = err
919 }
920 } else {
921 res = status.Errorf(codes.NotFound, "%s", img.Id)
922 }
923 sendResponse(ctx, ch, res)
924}
925
khenaidoof5a5bfa2019-01-23 22:20:29 -0500926func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
927 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
928 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
929 if err := agent.updateImageDownload(img); err != nil {
930 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
931 return err
932 }
933 } else {
934 return status.Errorf(codes.NotFound, "%s", img.Id)
935 }
936 return nil
937}
938
939func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
940 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
941 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
942 return agent.getImageDownload(ctx, img)
943 }
944 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
945}
946
947func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
948 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
949 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
950 return agent.listImageDownloads(ctx, deviceId)
951 }
952 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
953}
954
khenaidoo92e62c52018-10-03 14:02:54 -0400955func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400956 log.Info("activateDevice")
957 return nil
958}
959
khenaidoo92e62c52018-10-03 14:02:54 -0400960func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
961 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400962 return nil
963}
964
khenaidoo92e62c52018-10-03 14:02:54 -0400965func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400966 log.Info("abandonDevice")
967 return nil
968}
969
khenaidoo92e62c52018-10-03 14:02:54 -0400970func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400971 log.Info("reEnableDevice")
972 return nil
973}
974
khenaidoo92e62c52018-10-03 14:02:54 -0400975func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400976 log.Info("noOp")
977 return nil
978}
979
khenaidoo92e62c52018-10-03 14:02:54 -0400980func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400981 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -0400982 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -0400983}
984
985func funcName(f interface{}) string {
986 p := reflect.ValueOf(f).Pointer()
987 rf := runtime.FuncForPC(p)
988 return rf.Name()
989}
990
991func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
992 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
993 agent.updateDeviceAttribute(attribute, value)
994 }
995}
996
997func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -0400998 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400999 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -04001000 return &device.ParentId
1001 }
1002 return nil
1003}
serkant.uluderya334479d2019-04-10 08:26:15 -07001004
1005func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1006 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1007 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1008 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1009 var res interface{}
1010 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1011 res = agent.simulateAlarm(ctx, simulatereq)
1012 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1013 }
1014 //TODO CLI always get successful response
1015 sendResponse(ctx, ch, res)
1016}