blob: d17330831c04898f12e19785d2671bf91dbc3016 [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
khenaidoo3ab34882019-05-02 21:33:30 -0400611//updatePortsState updates all ports on the device
612func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
613 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
614
615 var adminState voltha.AdminState_AdminState
616 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
617 switch state {
618 case voltha.OperStatus_ACTIVE:
619 adminState = voltha.AdminState_ENABLED
620 if err := agent.enablePorts(); err != nil {
621 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
622 return err
623 }
624 case voltha.OperStatus_UNKNOWN:
625 adminState = voltha.AdminState_DISABLED
626 if err := agent.disablePorts(); err != nil {
627 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
628 return err
629 }
630 default:
631 return status.Error(codes.Unimplemented, "state-change-not-implemented")
632 }
633 // Notify the logical device about the state change
634 if device, err := dMgr.GetDevice(deviceId); err != nil {
635 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
636 return err
637 } else {
638 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
639 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
640 return err
641 }
642 return nil
643 }
644 }
645 return status.Errorf(codes.NotFound, "%s", deviceId)
646}
647
Matt Jeanneret4e241952019-02-28 11:16:04 -0500648func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
649 channelId int64, vendorId string, serialNumber string, onuId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400650 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400651
652 // Create the ONU device
653 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400654 childDevice.Type = deviceType
655 childDevice.ParentId = parentDeviceId
656 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500657 childDevice.VendorId = vendorId
658 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400659 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400660
661 //Get parent device type
662 parent, err := dMgr.GetDevice(parentDeviceId)
663 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500664 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400665 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
666 }
667
Matt Jeanneret4e241952019-02-28 11:16:04 -0500668 if _, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
669 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
670 return status.Errorf(codes.AlreadyExists, "%s", serialNumber)
671 }
672
673 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400674
675 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400676 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400677 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500678 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400679
680 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400681 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500682 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400683 }
684
khenaidoo79232702018-12-04 11:00:41 -0500685 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500686 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500687
khenaidoob9203542018-09-17 22:56:37 -0400688 return nil
689}
690
691func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
692 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400693 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
694 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500695 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400696 return nil
khenaidoob9203542018-09-17 22:56:37 -0400697 }
khenaidoo92e62c52018-10-03 14:02:54 -0400698 for _, handler := range handlers {
699 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
700 if err := handler(current); err != nil {
701 return err
702 }
703 }
khenaidoob9203542018-09-17 22:56:37 -0400704 return nil
705}
706
khenaidoofdbad6e2018-11-06 22:26:38 -0500707func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
708 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
709 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
710 return agent.packetOut(outPort, packet)
711 }
712 return status.Errorf(codes.NotFound, "%s", deviceId)
713}
714
khenaidoo297cd252019-02-07 22:10:23 -0500715func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500716 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
717 // Get the logical device Id based on the deviceId
718 var device *voltha.Device
719 var err error
720 if device, err = dMgr.GetDevice(deviceId); err != nil {
721 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
722 return err
723 }
khenaidoo43c82122018-11-22 18:38:28 -0500724 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500725 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
726 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
727 }
728
khenaidoo297cd252019-02-07 22:10:23 -0500729 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500730 return err
731 }
732 return nil
733}
734
khenaidoo92e62c52018-10-03 14:02:54 -0400735func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400736 log.Info("createLogicalDevice")
737 var logicalId *string
738 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400739 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400740 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
741 return err
742 }
743 // Update the parent device with the logical id
744 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
745 return nil
746}
747
khenaidoo92e62c52018-10-03 14:02:54 -0400748func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
749 log.Info("deleteLogicalDevice")
750 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400751 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400752 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
753 return err
754 }
755 // Remove the logical device Id from the parent device
756 logicalId := ""
757 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
758 return nil
759}
760
khenaidoo19d7b632018-10-30 10:49:50 -0400761func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400762 log.Info("deleteLogicalPort")
763 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400764 // Get the logical port associated with this device
765 var lPortId *voltha.LogicalPortId
766 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400767 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400768 return err
769 }
770 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
771 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400772 return err
773 }
khenaidoo92e62c52018-10-03 14:02:54 -0400774 return nil
775}
776
777func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
778 // Sanity check
779 if childDevice.Root {
780 // childDevice is the parent device
781 return childDevice
782 }
khenaidoo19d7b632018-10-30 10:49:50 -0400783 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400784 return parentDevice
785}
786
khenaidoo4d4802d2018-10-04 21:59:49 -0400787/*
788All the functions below are callback functions where they are invoked with the latest and previous data. We can
789therefore use the data as is without trying to get the latest from the model.
790*/
791
792//disableAllChildDevices is invoked as a callback when the parent device is disabled
793func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400794 log.Debug("disableAllChildDevices")
795 var childDeviceIds []string
796 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400797 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
798 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400799 }
800 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400801 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400802 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400803 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400804 for _, childDeviceId := range childDeviceIds {
805 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
806 if err = agent.disableDevice(nil); err != nil {
807 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400808 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400809 }
810 }
811 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400812 if !allChildDisable {
813 return err
814 }
khenaidoo92e62c52018-10-03 14:02:54 -0400815 return nil
816}
817
khenaidoo4d4802d2018-10-04 21:59:49 -0400818//deleteAllChildDevices is invoked as a callback when the parent device is deleted
819func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
820 log.Debug("deleteAllChildDevices")
821 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400822 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400823 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
824 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400825 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400826 if len(childDeviceIds) == 0 {
827 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
828 }
829 allChildDeleted := true
830 for _, childDeviceId := range childDeviceIds {
831 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
832 if err = agent.deleteDevice(nil); err != nil {
833 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
834 allChildDeleted = false
835 } else {
836 agent.stop(nil)
837 dMgr.deleteDeviceAgentToMap(agent)
838 }
839 }
840 }
841 if !allChildDeleted {
842 return err
843 }
844 return nil
845}
846
847//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
848func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
849 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400850 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400851 if parentDevice != nil {
852 for _, port := range parentDevice.Ports {
853 for _, peer := range port.Peers {
854 childDeviceIds = append(childDeviceIds, peer.DeviceId)
855 }
khenaidoo92e62c52018-10-03 14:02:54 -0400856 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400857 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -0400858 }
859 return childDeviceIds, nil
860}
861
khenaidoo297cd252019-02-07 22:10:23 -0500862//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
863func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
864 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
865 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
866 childDevices := make([]*voltha.Device, 0)
867 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
868 for _, deviceId := range childDeviceIds {
869 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
870 childDevices = append(childDevices, d)
871 }
872 }
873 }
874 return &voltha.Devices{Items: childDevices}, nil
875 }
876 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
877}
878
khenaidoofc1314d2019-03-14 09:34:21 -0400879func (dMgr *DeviceManager) setupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400880 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -0400881 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400882 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
883 return err
884 }
885 return nil
886}
887
khenaidoof5a5bfa2019-01-23 22:20:29 -0500888func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
889 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
890 var res interface{}
891 var err error
892 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
893 if res, err = agent.downloadImage(ctx, img); err != nil {
894 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
895 res = err
896 }
897 } else {
898 res = status.Errorf(codes.NotFound, "%s", img.Id)
899 }
900 sendResponse(ctx, ch, res)
901}
902
903func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
904 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
905 var res interface{}
906 var err error
907 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
908 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
909 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
910 res = err
911 }
912 } else {
913 res = status.Errorf(codes.NotFound, "%s", img.Id)
914 }
915 sendResponse(ctx, ch, res)
916}
917
918func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
919 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
920 var res interface{}
921 var err error
922 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
923 if res, err = agent.activateImage(ctx, img); err != nil {
924 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
925 res = err
926 }
927 } else {
928 res = status.Errorf(codes.NotFound, "%s", img.Id)
929 }
930 sendResponse(ctx, ch, res)
931}
932
933func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
934 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
935 var res interface{}
936 var err error
937 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
938 if res, err = agent.revertImage(ctx, img); err != nil {
939 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
940 res = err
941 }
942 } else {
943 res = status.Errorf(codes.NotFound, "%s", img.Id)
944 }
945 sendResponse(ctx, ch, res)
946}
947
948func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
949 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
950 var res interface{}
951 var err error
952 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
953 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
954 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
955 res = err
956 }
957 } else {
958 res = status.Errorf(codes.NotFound, "%s", img.Id)
959 }
960 sendResponse(ctx, ch, res)
961}
962
khenaidoof5a5bfa2019-01-23 22:20:29 -0500963func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
964 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
965 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
966 if err := agent.updateImageDownload(img); err != nil {
967 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
968 return err
969 }
970 } else {
971 return status.Errorf(codes.NotFound, "%s", img.Id)
972 }
973 return nil
974}
975
976func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
977 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
978 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
979 return agent.getImageDownload(ctx, img)
980 }
981 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
982}
983
984func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
985 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
986 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
987 return agent.listImageDownloads(ctx, deviceId)
988 }
989 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
990}
991
khenaidoo92e62c52018-10-03 14:02:54 -0400992func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400993 log.Info("activateDevice")
994 return nil
995}
996
khenaidoo92e62c52018-10-03 14:02:54 -0400997func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
998 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400999 return nil
1000}
1001
khenaidoo92e62c52018-10-03 14:02:54 -04001002func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001003 log.Info("abandonDevice")
1004 return nil
1005}
1006
khenaidoo92e62c52018-10-03 14:02:54 -04001007func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001008 log.Info("reEnableDevice")
1009 return nil
1010}
1011
khenaidoo92e62c52018-10-03 14:02:54 -04001012func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001013 log.Info("noOp")
1014 return nil
1015}
1016
khenaidoo92e62c52018-10-03 14:02:54 -04001017func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001018 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001019 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001020}
1021
1022func funcName(f interface{}) string {
1023 p := reflect.ValueOf(f).Pointer()
1024 rf := runtime.FuncForPC(p)
1025 return rf.Name()
1026}
1027
1028func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
1029 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
1030 agent.updateDeviceAttribute(attribute, value)
1031 }
1032}
1033
1034func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -04001035 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001036 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -04001037 return &device.ParentId
1038 }
1039 return nil
1040}
serkant.uluderya334479d2019-04-10 08:26:15 -07001041
1042func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1043 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1044 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1045 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1046 var res interface{}
1047 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1048 res = agent.simulateAlarm(ctx, simulatereq)
1049 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1050 }
1051 //TODO CLI always get successful response
1052 sendResponse(ctx, ch, res)
1053}