blob: eff6fe84c863b4535d39dba1216e200fe3fc32f1 [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)
khenaidoo4d4802d2018-10-04 21:59:49 -0400202 log.Debugw("deleteDevice-result", log.Fields{"result": res})
203 } else {
204 res = status.Errorf(codes.NotFound, "%s", id.Id)
205 }
206 sendResponse(ctx, ch, res)
207}
208
khenaidoo0a822f92019-05-08 15:15:57 -0400209func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
210 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
211 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
212 agent.stop(nil)
213 dMgr.deleteDeviceAgentToMap(agent)
214 if err := dMgr.core.deviceOwnership.AbandonDevice(cDevice.Id); err != nil {
215 log.Errorw("failed-abandoning-device-ownership", log.Fields{"deviceId": cDevice.Id, "error": err})
216 return err
217 }
218 return nil
219 }
220 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
221}
222
khenaidoo297cd252019-02-07 22:10:23 -0500223// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400224func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
225 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400226 if agent := dMgr.getDeviceAgent(id); agent != nil {
227 return agent.getDevice()
228 }
229 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400230}
231
Matt Jeanneret4e241952019-02-28 11:16:04 -0500232func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
Matt Jeanneret0c5088c2019-04-22 16:16:19 -0400233 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber,
234 "parentPortNo": parentPortNo, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500235
236 var parentDevice *voltha.Device
237 var err error
238 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
239 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
240 }
241 var childDeviceIds []string
242 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
243 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
244 }
245 if len(childDeviceIds) == 0 {
246 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
247 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
248 }
249
250 var foundChildDevice *voltha.Device
251 for _, childDeviceId := range childDeviceIds {
252 found := false
253 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
254
255 foundOnuId := false
256 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
257 if searchDevice.ParentPortNo == uint32(parentPortNo) {
258 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
259 foundOnuId = true
260 }
261 }
262
263 foundSerialNumber := false
264 if searchDevice.SerialNumber == serialNumber {
265 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
266 foundSerialNumber = true
267 }
268
269 // if both onuId and serialNumber are provided both must be true for the device to be found
270 // otherwise whichever one found a match is good enough
271 if onuId > 0 && serialNumber != "" {
272 found = foundOnuId && foundSerialNumber
273 } else {
274 found = foundOnuId || foundSerialNumber
275 }
276
277 if found == true {
278 foundChildDevice = searchDevice
279 break
280 }
281 }
282 }
283
284 if foundChildDevice != nil {
285 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
286 return foundChildDevice, nil
287 }
288
289 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
290 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
291 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
292}
293
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500294func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
295 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
296
297 var parentDevice *voltha.Device
298 var err error
299 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
300 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
301 }
302 var childDeviceIds []string
303 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
304 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
305 }
306 if len(childDeviceIds) == 0 {
307 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
308 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
309 }
310
311 var foundChildDevice *voltha.Device
312 for _, childDeviceId := range childDeviceIds {
313 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
314 if searchDevice.ProxyAddress == proxyAddress {
315 foundChildDevice = searchDevice
316 break
317 }
318 }
319 }
320
321 if foundChildDevice != nil {
322 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
323 return foundChildDevice, nil
324 }
325
326 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
327 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
328}
329
khenaidoo297cd252019-02-07 22:10:23 -0500330func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400331 dMgr.lockDeviceAgentsMap.RLock()
332 defer dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoo297cd252019-02-07 22:10:23 -0500333 _, exist := dMgr.deviceAgents[id]
334 return exist
335}
336
khenaidoo19d7b632018-10-30 10:49:50 -0400337func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400338 dMgr.lockRootDeviceMap.RLock()
339 defer dMgr.lockRootDeviceMap.RUnlock()
340 if exist := dMgr.rootDevices[id]; exist {
341 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400342 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400343 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400344}
345
Stephane Barbarieaa467942019-02-06 14:09:44 -0500346// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400347func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400348 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400349 result := &voltha.Devices{}
Stephane Barbarieaa467942019-02-06 14:09:44 -0500350 if devices := dMgr.clusterDataProxy.List("/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500351 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500352 // If device is not in memory then set it up
353 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400354 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500355 if err := agent.start(nil, true); err != nil {
356 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
357 agent.stop(nil)
358 } else {
359 dMgr.addDeviceAgentToMap(agent)
360 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500361 }
362 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400363 }
364 }
365 return result, nil
366}
367
khenaidoo297cd252019-02-07 22:10:23 -0500368// loadDevice loads the deviceId in memory, if not present
369func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
370 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
371 // Sanity check
372 if deviceId == "" {
373 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
374 }
375 if !dMgr.IsDeviceInCache(deviceId) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400376 agent := newDeviceAgent(dMgr.adapterProxy, &voltha.Device{Id: deviceId}, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500377 if err := agent.start(nil, true); err != nil {
378 agent.stop(nil)
379 return nil, err
380 }
381 dMgr.addDeviceAgentToMap(agent)
382 }
383 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
384 return agent, nil
385 }
Matt Jeanneret4e241952019-02-28 11:16:04 -0500386 return nil, status.Error(codes.NotFound, deviceId) // This should not happen
khenaidoo297cd252019-02-07 22:10:23 -0500387}
388
389// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
390func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
391 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
392 if device.Root {
393 // Scenario A
394 if device.ParentId != "" {
395 // Load logical device if needed.
396 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
397 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
398 }
399 } else {
400 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
401 }
402 // Load all child devices, if needed
403 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
404 for _, childDeviceId := range childDeviceIds {
405 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
406 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId})
407 return err
408 }
409 }
410 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
411 } else {
412 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
413 }
414 }
415 return nil
416}
417
418// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
419// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
420// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
421// and the proceed with the request.
422func (dMgr *DeviceManager) load(deviceId string) error {
423 log.Debug("load...")
424 // First load the device - this may fail in case the device was deleted intentionally by the other core
425 var dAgent *DeviceAgent
426 var err error
427 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
428 log.Warnw("failure-loading-device", log.Fields{"deviceId": deviceId})
429 return err
430 }
431 // Get the loaded device details
432 var device *voltha.Device
433 if device, err = dAgent.getDevice(); err != nil {
434 return err
435 }
436
437 // If the device is in Pre-provisioning or deleted state stop here
438 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
439 return nil
440 }
441
442 // Now we face two scenarios
443 if device.Root {
444 // Load all children as well as the parent of this device (logical_device)
445 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
446 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
447 return err
448 }
449 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
450 } else {
451 // Scenario B - use the parentId of that device (root device) to trigger the loading
452 if device.ParentId != "" {
453 return dMgr.load(device.ParentId)
454 }
455 }
456 return nil
457}
458
khenaidoo7ccedd52018-12-14 16:48:54 -0500459// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
460func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
461 log.Debug("ListDeviceIDs")
462 // Report only device IDs that are in the device agent map
463 return dMgr.listDeviceIdsFromMap(), nil
464}
465
466//ReconcileDevices is a request to a voltha core to managed a list of devices based on their IDs
467func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
468 log.Debug("ReconcileDevices")
469 var res interface{}
470 if ids != nil {
471 toReconcile := len(ids.Items)
472 reconciled := 0
473 for _, id := range ids.Items {
474 // Act on the device only if its not present in the agent map
khenaidoo297cd252019-02-07 22:10:23 -0500475 if !dMgr.IsDeviceInCache(id.Id) {
khenaidoo7ccedd52018-12-14 16:48:54 -0500476 // Device Id not in memory
477 log.Debugw("reconciling-device", log.Fields{"id": id.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500478 // Load device from dB
khenaidoo2c6a0992019-04-29 13:46:56 -0400479 agent := newDeviceAgent(dMgr.adapterProxy, &voltha.Device{Id: id.Id}, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500480 if err := agent.start(nil, true); err != nil {
481 log.Warnw("failure-loading-device", log.Fields{"deviceId": id.Id})
482 agent.stop(nil)
khenaidoo7ccedd52018-12-14 16:48:54 -0500483 } else {
khenaidoo297cd252019-02-07 22:10:23 -0500484 dMgr.addDeviceAgentToMap(agent)
485 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500486 }
487 } else {
488 reconciled += 1
489 }
490 }
491 if toReconcile != reconciled {
492 res = status.Errorf(codes.DataLoss, "less-device-reconciled:%d/%d", reconciled, toReconcile)
493 }
494 } else {
495 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
496 }
497 sendResponse(ctx, ch, res)
498}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500499
khenaidoob9203542018-09-17 22:56:37 -0400500func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400501 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400502 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
503 return agent.updateDevice(device)
504 }
505 return status.Errorf(codes.NotFound, "%s", device.Id)
506}
507
508func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
509 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400510 if err := agent.addPort(port); err != nil {
511 return err
512 }
513 // Setup peer ports
514 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
515 for _, peerPort := range port.Peers {
516 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
517 if err := agent.addPeerPort(meAsPeer); err != nil {
518 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
519 return err
520 }
521 }
522 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400523 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
524 // then a logical port will be added to the logical device and the device graph generated. If the port is a
525 // PON port then only the device graph will be generated.
526 if device, err := dMgr.GetDevice(deviceId); err == nil {
527 go dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
528 } else {
529 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
530 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400531 }
khenaidoo92e62c52018-10-03 14:02:54 -0400532 return nil
533 } else {
534 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400535 }
khenaidoob9203542018-09-17 22:56:37 -0400536}
537
khenaidoo0a822f92019-05-08 15:15:57 -0400538func (dMgr *DeviceManager) deletePeerPorts(fromDeviceId string, deviceId string) error {
539 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceId, "deviceid": deviceId})
540 if agent := dMgr.getDeviceAgent(fromDeviceId); agent != nil {
541 return agent.deletePeerPorts(deviceId)
542 }
543 return status.Errorf(codes.NotFound, "%s", deviceId)
544}
545
khenaidoo2c6a0992019-04-29 13:46:56 -0400546func (dMgr *DeviceManager) addFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) error {
547 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400548 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400549 return agent.addFlowsAndGroups(flows, groups)
550 //go agent.addFlowsAndGroups(flows, groups)
551 //return nil
khenaidoo19d7b632018-10-30 10:49:50 -0400552 }
553 return status.Errorf(codes.NotFound, "%s", deviceId)
554}
555
khenaidoob9203542018-09-17 22:56:37 -0400556func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
557 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
558 return agent.updatePmConfigs(pmConfigs)
559 }
560 return status.Errorf(codes.NotFound, "%s", deviceId)
561}
562
khenaidoo79232702018-12-04 11:00:41 -0500563func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400564 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400565 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
566 return agent.getSwitchCapability(ctx)
567 }
568 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
569}
570
khenaidoo92e62c52018-10-03 14:02:54 -0400571func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
572 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400573 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400574 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400575 }
576 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400577
khenaidoob9203542018-09-17 22:56:37 -0400578}
579
khenaidoo79232702018-12-04 11:00:41 -0500580func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400581 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400582 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
583 return agent.getPortCapability(ctx, portNo)
584 }
585 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
586}
587
khenaidoo92e62c52018-10-03 14:02:54 -0400588func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
589 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400590 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400591 return agent.updateDeviceStatus(operStatus, connStatus)
592 }
593 return status.Errorf(codes.NotFound, "%s", deviceId)
594}
595
khenaidoo4d4802d2018-10-04 21:59:49 -0400596func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
597 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
598 var parentDevice *voltha.Device
599 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400600 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400601 return status.Errorf(codes.Aborted, "%s", err.Error())
602 }
603 var childDeviceIds []string
604 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
605 return status.Errorf(codes.Aborted, "%s", err.Error())
606 }
607 if len(childDeviceIds) == 0 {
608 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
609 }
610 for _, childDeviceId := range childDeviceIds {
611 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
612 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
613 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
614 }
615 }
616 }
617 return nil
618}
619
khenaidoo92e62c52018-10-03 14:02:54 -0400620func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
621 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
622 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
623 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400624 }
625 return status.Errorf(codes.NotFound, "%s", deviceId)
626}
627
khenaidoo0a822f92019-05-08 15:15:57 -0400628func (dMgr *DeviceManager) deleteAllPorts(deviceId string) error {
629 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceId})
630 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
631 if err := agent.deleteAllPorts(); err != nil {
632 return err
633 }
634 // Notify the logical device manager to remove all logical ports, if needed.
635 // At this stage the device itself may gave been deleted already at a deleteAllPorts
636 // typically is part of a device deletion phase.
637 if device, err := dMgr.GetDevice(deviceId); err == nil {
638 go dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
639 } else {
640 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
641 return err
642 }
643 return nil
644 }
645 return status.Errorf(codes.NotFound, "%s", deviceId)
646}
647
khenaidoo3ab34882019-05-02 21:33:30 -0400648//updatePortsState updates all ports on the device
649func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
650 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
651
652 var adminState voltha.AdminState_AdminState
653 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
654 switch state {
655 case voltha.OperStatus_ACTIVE:
656 adminState = voltha.AdminState_ENABLED
657 if err := agent.enablePorts(); err != nil {
658 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
659 return err
660 }
661 case voltha.OperStatus_UNKNOWN:
662 adminState = voltha.AdminState_DISABLED
663 if err := agent.disablePorts(); err != nil {
664 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
665 return err
666 }
667 default:
668 return status.Error(codes.Unimplemented, "state-change-not-implemented")
669 }
670 // Notify the logical device about the state change
671 if device, err := dMgr.GetDevice(deviceId); err != nil {
672 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
673 return err
674 } else {
675 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
676 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
677 return err
678 }
679 return nil
680 }
681 }
682 return status.Errorf(codes.NotFound, "%s", deviceId)
683}
684
Matt Jeanneret4e241952019-02-28 11:16:04 -0500685func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
686 channelId int64, vendorId string, serialNumber string, onuId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400687 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400688
689 // Create the ONU device
690 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400691 childDevice.Type = deviceType
692 childDevice.ParentId = parentDeviceId
693 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500694 childDevice.VendorId = vendorId
695 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400696 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400697
698 //Get parent device type
699 parent, err := dMgr.GetDevice(parentDeviceId)
700 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500701 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400702 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
703 }
704
Matt Jeanneret4e241952019-02-28 11:16:04 -0500705 if _, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
706 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
707 return status.Errorf(codes.AlreadyExists, "%s", serialNumber)
708 }
709
710 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400711
712 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400713 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400714 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500715 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400716
717 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400718 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500719 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400720 }
721
khenaidoo79232702018-12-04 11:00:41 -0500722 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500723 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500724
khenaidoob9203542018-09-17 22:56:37 -0400725 return nil
726}
727
728func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
729 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400730 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
731 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500732 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400733 return nil
khenaidoob9203542018-09-17 22:56:37 -0400734 }
khenaidoo0a822f92019-05-08 15:15:57 -0400735 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root})
khenaidoo92e62c52018-10-03 14:02:54 -0400736 for _, handler := range handlers {
737 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
738 if err := handler(current); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400739 log.Warnw("handler-falied", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400740 return err
741 }
742 }
khenaidoob9203542018-09-17 22:56:37 -0400743 return nil
744}
745
khenaidoofdbad6e2018-11-06 22:26:38 -0500746func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
747 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
748 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
749 return agent.packetOut(outPort, packet)
750 }
751 return status.Errorf(codes.NotFound, "%s", deviceId)
752}
753
khenaidoo297cd252019-02-07 22:10:23 -0500754func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500755 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
756 // Get the logical device Id based on the deviceId
757 var device *voltha.Device
758 var err error
759 if device, err = dMgr.GetDevice(deviceId); err != nil {
760 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
761 return err
762 }
khenaidoo43c82122018-11-22 18:38:28 -0500763 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500764 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
765 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
766 }
767
khenaidoo297cd252019-02-07 22:10:23 -0500768 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500769 return err
770 }
771 return nil
772}
773
khenaidoo0a822f92019-05-08 15:15:57 -0400774func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
775 log.Info("CreateLogicalDevice")
khenaidoob9203542018-09-17 22:56:37 -0400776 var logicalId *string
777 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400778 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400779 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
780 return err
781 }
782 // Update the parent device with the logical id
783 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
784 return nil
785}
786
khenaidoo0a822f92019-05-08 15:15:57 -0400787func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
788 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -0400789 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400790 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400791 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
792 return err
793 }
794 // Remove the logical device Id from the parent device
795 logicalId := ""
796 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
797 return nil
798}
799
khenaidoo0a822f92019-05-08 15:15:57 -0400800func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400801 log.Info("deleteLogicalPort")
802 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400803 // Get the logical port associated with this device
804 var lPortId *voltha.LogicalPortId
805 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400806 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400807 return err
808 }
809 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
810 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400811 return err
812 }
khenaidoo92e62c52018-10-03 14:02:54 -0400813 return nil
814}
815
khenaidoo0a822f92019-05-08 15:15:57 -0400816func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
817 log.Info("deleteLogicalPorts")
818 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
819 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
820 return err
821 }
822 return nil
823}
824
khenaidoo92e62c52018-10-03 14:02:54 -0400825func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
826 // Sanity check
827 if childDevice.Root {
828 // childDevice is the parent device
829 return childDevice
830 }
khenaidoo19d7b632018-10-30 10:49:50 -0400831 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400832 return parentDevice
833}
834
khenaidoo0a822f92019-05-08 15:15:57 -0400835//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
836//cannot manage the child devices. This will trigger the Core to disable all the child devices.
837func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
838 log.Debug("childDevicesLost")
839 var err error
840 var parentDevice *voltha.Device
841 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
842 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
843 return err
844 }
845 return dMgr.DisableAllChildDevices(parentDevice)
846}
847
848//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
849// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
850func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
851 log.Debug("childDevicesDetected")
852 var err error
853 var parentDevice *voltha.Device
854 var childDeviceIds []string
855
856 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
857 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
858 return err
859 }
860
861 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
862 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
863 }
864 if len(childDeviceIds) == 0 {
865 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
866 }
867 allChildDisable := true
868 for _, childDeviceId := range childDeviceIds {
869 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
870 if err = agent.enableDevice(nil); err != nil {
871 log.Errorw("failure-enable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
872 allChildDisable = false
873 }
874 }
875 }
876 if !allChildDisable {
877 return err
878 }
879 return nil
880}
881
khenaidoo4d4802d2018-10-04 21:59:49 -0400882/*
883All the functions below are callback functions where they are invoked with the latest and previous data. We can
884therefore use the data as is without trying to get the latest from the model.
885*/
886
khenaidoo0a822f92019-05-08 15:15:57 -0400887//DisableAllChildDevices is invoked as a callback when the parent device is disabled
888func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
889 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -0400890 var childDeviceIds []string
891 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400892 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
893 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400894 }
895 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400896 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400897 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400898 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400899 for _, childDeviceId := range childDeviceIds {
900 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
901 if err = agent.disableDevice(nil); err != nil {
902 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400903 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400904 }
905 }
906 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400907 if !allChildDisable {
908 return err
909 }
khenaidoo92e62c52018-10-03 14:02:54 -0400910 return nil
911}
912
khenaidoo0a822f92019-05-08 15:15:57 -0400913//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
914func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
915 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -0400916 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400917 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400918 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
919 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400920 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400921 if len(childDeviceIds) == 0 {
922 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
923 }
924 allChildDeleted := true
925 for _, childDeviceId := range childDeviceIds {
926 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
927 if err = agent.deleteDevice(nil); err != nil {
928 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
929 allChildDeleted = false
930 } else {
931 agent.stop(nil)
932 dMgr.deleteDeviceAgentToMap(agent)
933 }
934 }
935 }
936 if !allChildDeleted {
937 return err
938 }
939 return nil
940}
941
942//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
943func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
944 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400945 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400946 if parentDevice != nil {
947 for _, port := range parentDevice.Ports {
948 for _, peer := range port.Peers {
949 childDeviceIds = append(childDeviceIds, peer.DeviceId)
950 }
khenaidoo92e62c52018-10-03 14:02:54 -0400951 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400952 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -0400953 }
954 return childDeviceIds, nil
955}
956
khenaidoo297cd252019-02-07 22:10:23 -0500957//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
958func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
959 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
960 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
961 childDevices := make([]*voltha.Device, 0)
962 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
963 for _, deviceId := range childDeviceIds {
964 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
965 childDevices = append(childDevices, d)
966 }
967 }
968 }
969 return &voltha.Devices{Items: childDevices}, nil
970 }
971 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
972}
973
khenaidoo0a822f92019-05-08 15:15:57 -0400974func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400975 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -0400976 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400977 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
978 return err
979 }
980 return nil
981}
982
khenaidoof5a5bfa2019-01-23 22:20:29 -0500983func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
984 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
985 var res interface{}
986 var err error
987 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
988 if res, err = agent.downloadImage(ctx, img); err != nil {
989 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
990 res = err
991 }
992 } else {
993 res = status.Errorf(codes.NotFound, "%s", img.Id)
994 }
995 sendResponse(ctx, ch, res)
996}
997
998func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
999 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1000 var res interface{}
1001 var err error
1002 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1003 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1004 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1005 res = err
1006 }
1007 } else {
1008 res = status.Errorf(codes.NotFound, "%s", img.Id)
1009 }
1010 sendResponse(ctx, ch, res)
1011}
1012
1013func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1014 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1015 var res interface{}
1016 var err error
1017 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1018 if res, err = agent.activateImage(ctx, img); err != nil {
1019 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1020 res = err
1021 }
1022 } else {
1023 res = status.Errorf(codes.NotFound, "%s", img.Id)
1024 }
1025 sendResponse(ctx, ch, res)
1026}
1027
1028func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1029 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1030 var res interface{}
1031 var err error
1032 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1033 if res, err = agent.revertImage(ctx, img); err != nil {
1034 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1035 res = err
1036 }
1037 } else {
1038 res = status.Errorf(codes.NotFound, "%s", img.Id)
1039 }
1040 sendResponse(ctx, ch, res)
1041}
1042
1043func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1044 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1045 var res interface{}
1046 var err error
1047 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1048 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1049 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1050 res = err
1051 }
1052 } else {
1053 res = status.Errorf(codes.NotFound, "%s", img.Id)
1054 }
1055 sendResponse(ctx, ch, res)
1056}
1057
khenaidoof5a5bfa2019-01-23 22:20:29 -05001058func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1059 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1060 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1061 if err := agent.updateImageDownload(img); err != nil {
1062 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1063 return err
1064 }
1065 } else {
1066 return status.Errorf(codes.NotFound, "%s", img.Id)
1067 }
1068 return nil
1069}
1070
1071func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1072 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1073 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1074 return agent.getImageDownload(ctx, img)
1075 }
1076 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1077}
1078
1079func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1080 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1081 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1082 return agent.listImageDownloads(ctx, deviceId)
1083 }
1084 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1085}
1086
khenaidoo0a822f92019-05-08 15:15:57 -04001087func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1088 log.Info("SetAdminStateToEnable")
1089 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1090 return agent.updateAdminState(voltha.AdminState_ENABLED)
1091 }
1092 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1093}
1094
khenaidoo92e62c52018-10-03 14:02:54 -04001095func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001096 log.Info("activateDevice")
1097 return nil
1098}
1099
khenaidoo92e62c52018-10-03 14:02:54 -04001100func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1101 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001102 return nil
1103}
1104
khenaidoo92e62c52018-10-03 14:02:54 -04001105func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001106 log.Info("abandonDevice")
1107 return nil
1108}
1109
khenaidoo92e62c52018-10-03 14:02:54 -04001110func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001111 log.Info("reEnableDevice")
1112 return nil
1113}
1114
khenaidoo92e62c52018-10-03 14:02:54 -04001115func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001116 log.Info("noOp")
1117 return nil
1118}
1119
khenaidoo92e62c52018-10-03 14:02:54 -04001120func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001121 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001122 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001123}
1124
khenaidoo0a822f92019-05-08 15:15:57 -04001125func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
1126 log.Errorw("NotifyInvalidTransition", log.Fields{"device": pcDevice.Id, "adminState": pcDevice.AdminState})
1127 //TODO: notify over kafka?
1128 return nil
1129}
1130
khenaidoob9203542018-09-17 22:56:37 -04001131func funcName(f interface{}) string {
1132 p := reflect.ValueOf(f).Pointer()
1133 rf := runtime.FuncForPC(p)
1134 return rf.Name()
1135}
1136
1137func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
1138 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
1139 agent.updateDeviceAttribute(attribute, value)
1140 }
1141}
1142
1143func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -04001144 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001145 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -04001146 return &device.ParentId
1147 }
1148 return nil
1149}
serkant.uluderya334479d2019-04-10 08:26:15 -07001150
1151func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1152 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1153 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1154 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1155 var res interface{}
1156 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1157 res = agent.simulateAlarm(ctx, simulatereq)
1158 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1159 }
1160 //TODO CLI always get successful response
1161 sendResponse(ctx, ch, res)
1162}