blob: a96166d5bd4225f51721c967631b90ebe034ec26 [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
khenaidoo6d62c002019-05-15 21:57:03 -0400209// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
210// This function is called only in the Core that does not own this device. In the Core that owns this device then a
211// deletion deletion also includes removal of any reference of this device.
212func (dMgr *DeviceManager) stopManagingDevice(id string) {
213 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
214 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
215 if root, _ := dMgr.IsRootDevice(id); root == true {
216 // stop managing the logical device
217 ldeviceId := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceId(id)
218 if ldeviceId != "" { // Can happen if logical device agent was already stopped
219 dMgr.core.deviceOwnership.AbandonDevice(ldeviceId)
220 }
221 // stop managing the child devices
222 childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentId(id)
223 for _, cId := range childDeviceIds {
224 dMgr.stopManagingDevice(cId)
225 }
226 }
227 if agent := dMgr.getDeviceAgent(id); agent != nil {
228 agent.stop(nil)
229 dMgr.deleteDeviceAgentToMap(agent)
230 // Abandon the device ownership
231 dMgr.core.deviceOwnership.AbandonDevice(id)
232 }
233 }
234}
235
khenaidoo0a822f92019-05-08 15:15:57 -0400236func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
237 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400238 dMgr.stopManagingDevice(cDevice.Id)
239 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400240}
241
khenaidoo297cd252019-02-07 22:10:23 -0500242// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400243func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
244 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400245 if agent := dMgr.getDeviceAgent(id); agent != nil {
246 return agent.getDevice()
247 }
248 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400249}
250
Matt Jeanneret4e241952019-02-28 11:16:04 -0500251func (dMgr *DeviceManager) GetChildDevice(parentDeviceId string, serialNumber string, onuId int64, parentPortNo int64) (*voltha.Device, error) {
Matt Jeanneret0c5088c2019-04-22 16:16:19 -0400252 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceId, "serialNumber": serialNumber,
253 "parentPortNo": parentPortNo, "onuId": onuId})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500254
255 var parentDevice *voltha.Device
256 var err error
257 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
258 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
259 }
260 var childDeviceIds []string
261 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
262 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
263 }
264 if len(childDeviceIds) == 0 {
265 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
266 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
267 }
268
269 var foundChildDevice *voltha.Device
270 for _, childDeviceId := range childDeviceIds {
271 found := false
272 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
273
274 foundOnuId := false
275 if searchDevice.ProxyAddress.OnuId == uint32(onuId) {
276 if searchDevice.ParentPortNo == uint32(parentPortNo) {
277 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuId})
278 foundOnuId = true
279 }
280 }
281
282 foundSerialNumber := false
283 if searchDevice.SerialNumber == serialNumber {
284 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
285 foundSerialNumber = true
286 }
287
288 // if both onuId and serialNumber are provided both must be true for the device to be found
289 // otherwise whichever one found a match is good enough
290 if onuId > 0 && serialNumber != "" {
291 found = foundOnuId && foundSerialNumber
292 } else {
293 found = foundOnuId || foundSerialNumber
294 }
295
296 if found == true {
297 foundChildDevice = searchDevice
298 break
299 }
300 }
301 }
302
303 if foundChildDevice != nil {
304 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
305 return foundChildDevice, nil
306 }
307
308 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
309 "serialNumber": serialNumber, "onuId": onuId, "parentPortNo": parentPortNo})
310 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
311}
312
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500313func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
314 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
315
316 var parentDevice *voltha.Device
317 var err error
318 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
319 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
320 }
321 var childDeviceIds []string
322 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
323 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
324 }
325 if len(childDeviceIds) == 0 {
326 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
327 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
328 }
329
330 var foundChildDevice *voltha.Device
331 for _, childDeviceId := range childDeviceIds {
332 if searchDevice, err := dMgr.GetDevice(childDeviceId); err == nil {
333 if searchDevice.ProxyAddress == proxyAddress {
334 foundChildDevice = searchDevice
335 break
336 }
337 }
338 }
339
340 if foundChildDevice != nil {
341 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
342 return foundChildDevice, nil
343 }
344
345 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
346 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
347}
348
khenaidoo297cd252019-02-07 22:10:23 -0500349func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400350 dMgr.lockDeviceAgentsMap.RLock()
351 defer dMgr.lockDeviceAgentsMap.RUnlock()
khenaidoo297cd252019-02-07 22:10:23 -0500352 _, exist := dMgr.deviceAgents[id]
353 return exist
354}
355
khenaidoo19d7b632018-10-30 10:49:50 -0400356func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400357 dMgr.lockRootDeviceMap.RLock()
358 defer dMgr.lockRootDeviceMap.RUnlock()
359 if exist := dMgr.rootDevices[id]; exist {
360 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400361 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400362 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400363}
364
Stephane Barbarieaa467942019-02-06 14:09:44 -0500365// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400366func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400367 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400368 result := &voltha.Devices{}
Stephane Barbarieaa467942019-02-06 14:09:44 -0500369 if devices := dMgr.clusterDataProxy.List("/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500370 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500371 // If device is not in memory then set it up
372 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400373 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400374 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo297cd252019-02-07 22:10:23 -0500375 if err := agent.start(nil, true); err != nil {
376 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
377 agent.stop(nil)
378 } else {
379 dMgr.addDeviceAgentToMap(agent)
380 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500381 }
382 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400383 }
384 }
khenaidoo6d62c002019-05-15 21:57:03 -0400385 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400386 return result, nil
387}
388
khenaidoo6d62c002019-05-15 21:57:03 -0400389//getDeviceFromModelretrieves the device data from the model.
390func (dMgr *DeviceManager) getDeviceFromModel(deviceId string) (*voltha.Device, error) {
391 if device := dMgr.clusterDataProxy.Get("/devices/"+deviceId, 0, false, ""); device != nil {
392 if d, ok := device.(*voltha.Device); ok {
393 return d, nil
394 }
395 }
396 return nil, status.Error(codes.NotFound, deviceId)
397}
398
khenaidoo297cd252019-02-07 22:10:23 -0500399// loadDevice loads the deviceId in memory, if not present
400func (dMgr *DeviceManager) loadDevice(deviceId string) (*DeviceAgent, error) {
401 log.Debugw("loading-device", log.Fields{"deviceId": deviceId})
402 // Sanity check
403 if deviceId == "" {
404 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
405 }
406 if !dMgr.IsDeviceInCache(deviceId) {
khenaidoo6d62c002019-05-15 21:57:03 -0400407 // Proceed with the loading only if the device exist in the Model (could have been deleted)
408 if device, err := dMgr.getDeviceFromModel(deviceId); err == nil {
409 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
410 if err := agent.start(nil, true); err != nil {
411 agent.stop(nil)
412 return nil, err
413 }
414 dMgr.addDeviceAgentToMap(agent)
415 } else {
416 return nil, status.Error(codes.NotFound, deviceId)
khenaidoo297cd252019-02-07 22:10:23 -0500417 }
khenaidoo297cd252019-02-07 22:10:23 -0500418 }
419 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
420 return agent, nil
421 }
Matt Jeanneret4e241952019-02-28 11:16:04 -0500422 return nil, status.Error(codes.NotFound, deviceId) // This should not happen
khenaidoo297cd252019-02-07 22:10:23 -0500423}
424
425// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
426func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
427 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
428 if device.Root {
429 // Scenario A
430 if device.ParentId != "" {
431 // Load logical device if needed.
432 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
433 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
434 }
435 } else {
436 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
437 }
438 // Load all child devices, if needed
439 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
440 for _, childDeviceId := range childDeviceIds {
441 if _, err := dMgr.loadDevice(childDeviceId); err != nil {
442 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceId})
443 return err
444 }
445 }
446 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
447 } else {
448 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
449 }
450 }
451 return nil
452}
453
454// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
455// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
456// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
457// and the proceed with the request.
458func (dMgr *DeviceManager) load(deviceId string) error {
459 log.Debug("load...")
460 // First load the device - this may fail in case the device was deleted intentionally by the other core
461 var dAgent *DeviceAgent
462 var err error
463 if dAgent, err = dMgr.loadDevice(deviceId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500464 return err
465 }
466 // Get the loaded device details
467 var device *voltha.Device
468 if device, err = dAgent.getDevice(); err != nil {
469 return err
470 }
471
472 // If the device is in Pre-provisioning or deleted state stop here
473 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
474 return nil
475 }
476
477 // Now we face two scenarios
478 if device.Root {
479 // Load all children as well as the parent of this device (logical_device)
480 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
481 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceId})
482 return err
483 }
484 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceId})
485 } else {
486 // Scenario B - use the parentId of that device (root device) to trigger the loading
487 if device.ParentId != "" {
488 return dMgr.load(device.ParentId)
489 }
490 }
491 return nil
492}
493
khenaidoo7ccedd52018-12-14 16:48:54 -0500494// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
495func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
496 log.Debug("ListDeviceIDs")
497 // Report only device IDs that are in the device agent map
498 return dMgr.listDeviceIdsFromMap(), nil
499}
500
501//ReconcileDevices is a request to a voltha core to managed a list of devices based on their IDs
502func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
503 log.Debug("ReconcileDevices")
504 var res interface{}
505 if ids != nil {
506 toReconcile := len(ids.Items)
507 reconciled := 0
508 for _, id := range ids.Items {
509 // Act on the device only if its not present in the agent map
khenaidoo297cd252019-02-07 22:10:23 -0500510 if !dMgr.IsDeviceInCache(id.Id) {
khenaidoo7ccedd52018-12-14 16:48:54 -0500511 // Device Id not in memory
512 log.Debugw("reconciling-device", log.Fields{"id": id.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400513 // Proceed with the loading only if the device exist in the Model (could have been deleted)
514 if device, err := dMgr.getDeviceFromModel(id.Id); err == nil {
515 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
516 if err := agent.start(nil, true); err != nil {
517 log.Warnw("failure-loading-device", log.Fields{"deviceId": id.Id})
518 agent.stop(nil)
519 } else {
520 dMgr.addDeviceAgentToMap(agent)
521 reconciled += 1
522 }
khenaidoo7ccedd52018-12-14 16:48:54 -0500523 } else {
khenaidoo297cd252019-02-07 22:10:23 -0500524 reconciled += 1
khenaidoo7ccedd52018-12-14 16:48:54 -0500525 }
khenaidoo7ccedd52018-12-14 16:48:54 -0500526 }
527 }
528 if toReconcile != reconciled {
529 res = status.Errorf(codes.DataLoss, "less-device-reconciled:%d/%d", reconciled, toReconcile)
530 }
531 } else {
532 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
533 }
534 sendResponse(ctx, ch, res)
535}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500536
khenaidoob9203542018-09-17 22:56:37 -0400537func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400538 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400539 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
540 return agent.updateDevice(device)
541 }
542 return status.Errorf(codes.NotFound, "%s", device.Id)
543}
544
545func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
546 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400547 if err := agent.addPort(port); err != nil {
548 return err
549 }
550 // Setup peer ports
551 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
552 for _, peerPort := range port.Peers {
553 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
554 if err := agent.addPeerPort(meAsPeer); err != nil {
555 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
556 return err
557 }
558 }
559 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400560 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
561 // then a logical port will be added to the logical device and the device graph generated. If the port is a
562 // PON port then only the device graph will be generated.
563 if device, err := dMgr.GetDevice(deviceId); err == nil {
564 go dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
565 } else {
566 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
567 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400568 }
khenaidoo92e62c52018-10-03 14:02:54 -0400569 return nil
570 } else {
571 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400572 }
khenaidoob9203542018-09-17 22:56:37 -0400573}
574
khenaidoo0a822f92019-05-08 15:15:57 -0400575func (dMgr *DeviceManager) deletePeerPorts(fromDeviceId string, deviceId string) error {
576 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceId, "deviceid": deviceId})
577 if agent := dMgr.getDeviceAgent(fromDeviceId); agent != nil {
578 return agent.deletePeerPorts(deviceId)
579 }
580 return status.Errorf(codes.NotFound, "%s", deviceId)
581}
582
khenaidoo2c6a0992019-04-29 13:46:56 -0400583func (dMgr *DeviceManager) addFlowsAndGroups(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) error {
584 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400585 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400586 return agent.addFlowsAndGroups(flows, groups)
587 //go agent.addFlowsAndGroups(flows, groups)
588 //return nil
khenaidoo19d7b632018-10-30 10:49:50 -0400589 }
590 return status.Errorf(codes.NotFound, "%s", deviceId)
591}
592
khenaidoob9203542018-09-17 22:56:37 -0400593func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
594 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
595 return agent.updatePmConfigs(pmConfigs)
596 }
597 return status.Errorf(codes.NotFound, "%s", deviceId)
598}
599
khenaidoo79232702018-12-04 11:00:41 -0500600func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400601 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400602 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
603 return agent.getSwitchCapability(ctx)
604 }
605 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
606}
607
khenaidoo92e62c52018-10-03 14:02:54 -0400608func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
609 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400610 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400611 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400612 }
613 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400614
khenaidoob9203542018-09-17 22:56:37 -0400615}
616
khenaidoo79232702018-12-04 11:00:41 -0500617func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400618 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400619 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
620 return agent.getPortCapability(ctx, portNo)
621 }
622 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
623}
624
khenaidoo92e62c52018-10-03 14:02:54 -0400625func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
626 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400627 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400628 return agent.updateDeviceStatus(operStatus, connStatus)
629 }
630 return status.Errorf(codes.NotFound, "%s", deviceId)
631}
632
khenaidoo4d4802d2018-10-04 21:59:49 -0400633func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
634 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
635 var parentDevice *voltha.Device
636 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400637 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400638 return status.Errorf(codes.Aborted, "%s", err.Error())
639 }
640 var childDeviceIds []string
641 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
642 return status.Errorf(codes.Aborted, "%s", err.Error())
643 }
644 if len(childDeviceIds) == 0 {
645 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
646 }
647 for _, childDeviceId := range childDeviceIds {
648 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
649 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
650 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
651 }
652 }
653 }
654 return nil
655}
656
khenaidoo92e62c52018-10-03 14:02:54 -0400657func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
658 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
659 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
660 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400661 }
662 return status.Errorf(codes.NotFound, "%s", deviceId)
663}
664
khenaidoo0a822f92019-05-08 15:15:57 -0400665func (dMgr *DeviceManager) deleteAllPorts(deviceId string) error {
666 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceId})
667 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
668 if err := agent.deleteAllPorts(); err != nil {
669 return err
670 }
671 // Notify the logical device manager to remove all logical ports, if needed.
672 // At this stage the device itself may gave been deleted already at a deleteAllPorts
673 // typically is part of a device deletion phase.
674 if device, err := dMgr.GetDevice(deviceId); err == nil {
675 go dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
676 } else {
677 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceId})
678 return err
679 }
680 return nil
681 }
682 return status.Errorf(codes.NotFound, "%s", deviceId)
683}
684
khenaidoo3ab34882019-05-02 21:33:30 -0400685//updatePortsState updates all ports on the device
686func (dMgr *DeviceManager) updatePortsState(deviceId string, state voltha.OperStatus_OperStatus) error {
687 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceId})
688
689 var adminState voltha.AdminState_AdminState
690 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
691 switch state {
692 case voltha.OperStatus_ACTIVE:
693 adminState = voltha.AdminState_ENABLED
694 if err := agent.enablePorts(); err != nil {
695 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
696 return err
697 }
698 case voltha.OperStatus_UNKNOWN:
699 adminState = voltha.AdminState_DISABLED
700 if err := agent.disablePorts(); err != nil {
701 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceId, "error": err})
702 return err
703 }
704 default:
705 return status.Error(codes.Unimplemented, "state-change-not-implemented")
706 }
707 // Notify the logical device about the state change
708 if device, err := dMgr.GetDevice(deviceId); err != nil {
709 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceId, "error": err})
710 return err
711 } else {
712 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
713 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceId, "error": err})
714 return err
715 }
716 return nil
717 }
718 }
719 return status.Errorf(codes.NotFound, "%s", deviceId)
720}
721
Matt Jeanneret4e241952019-02-28 11:16:04 -0500722func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string,
723 channelId int64, vendorId string, serialNumber string, onuId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400724 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400725
726 // Create the ONU device
727 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400728 childDevice.Type = deviceType
729 childDevice.ParentId = parentDeviceId
730 childDevice.ParentPortNo = uint32(parentPortNo)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500731 childDevice.VendorId = vendorId
732 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400733 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400734
735 //Get parent device type
736 parent, err := dMgr.GetDevice(parentDeviceId)
737 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500738 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400739 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
740 }
741
Matt Jeanneret4e241952019-02-28 11:16:04 -0500742 if _, err := dMgr.GetChildDevice(parentDeviceId, serialNumber, onuId, parentPortNo); err == nil {
743 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceId, "serialNumber": serialNumber})
744 return status.Errorf(codes.AlreadyExists, "%s", serialNumber)
745 }
746
747 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId), OnuId: uint32(onuId)}
khenaidoob9203542018-09-17 22:56:37 -0400748
749 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400750 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400751 dMgr.addDeviceAgentToMap(agent)
khenaidoo297cd252019-02-07 22:10:23 -0500752 agent.start(nil, false)
khenaidoob9203542018-09-17 22:56:37 -0400753
754 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400755 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500756 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400757 }
758
khenaidoo79232702018-12-04 11:00:41 -0500759 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500760 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500761
khenaidoob9203542018-09-17 22:56:37 -0400762 return nil
763}
764
765func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
766 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400767 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
768 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500769 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400770 return nil
khenaidoob9203542018-09-17 22:56:37 -0400771 }
khenaidoo0a822f92019-05-08 15:15:57 -0400772 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root})
khenaidoo92e62c52018-10-03 14:02:54 -0400773 for _, handler := range handlers {
774 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
775 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400776 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -0400777 return err
778 }
779 }
khenaidoob9203542018-09-17 22:56:37 -0400780 return nil
781}
782
khenaidoofdbad6e2018-11-06 22:26:38 -0500783func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
784 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
785 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
786 return agent.packetOut(outPort, packet)
787 }
788 return status.Errorf(codes.NotFound, "%s", deviceId)
789}
790
khenaidoo297cd252019-02-07 22:10:23 -0500791func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, transactionId string, packet []byte) error {
khenaidoofdbad6e2018-11-06 22:26:38 -0500792 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
793 // Get the logical device Id based on the deviceId
794 var device *voltha.Device
795 var err error
796 if device, err = dMgr.GetDevice(deviceId); err != nil {
797 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
798 return err
799 }
khenaidoo43c82122018-11-22 18:38:28 -0500800 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500801 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
802 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
803 }
804
khenaidoo297cd252019-02-07 22:10:23 -0500805 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionId, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -0500806 return err
807 }
808 return nil
809}
810
khenaidoo0a822f92019-05-08 15:15:57 -0400811func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
812 log.Info("CreateLogicalDevice")
khenaidoob9203542018-09-17 22:56:37 -0400813 var logicalId *string
814 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400815 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400816 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
817 return err
818 }
819 // Update the parent device with the logical id
820 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
821 return nil
822}
823
khenaidoo0a822f92019-05-08 15:15:57 -0400824func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
825 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -0400826 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400827 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400828 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
829 return err
830 }
831 // Remove the logical device Id from the parent device
832 logicalId := ""
833 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
834 return nil
835}
836
khenaidoo0a822f92019-05-08 15:15:57 -0400837func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400838 log.Info("deleteLogicalPort")
839 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400840 // Get the logical port associated with this device
841 var lPortId *voltha.LogicalPortId
842 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400843 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400844 return err
845 }
846 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
847 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400848 return err
849 }
khenaidoo92e62c52018-10-03 14:02:54 -0400850 return nil
851}
852
khenaidoo0a822f92019-05-08 15:15:57 -0400853func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
854 log.Info("deleteLogicalPorts")
855 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
856 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
857 return err
858 }
859 return nil
860}
861
khenaidoo92e62c52018-10-03 14:02:54 -0400862func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
863 // Sanity check
864 if childDevice.Root {
865 // childDevice is the parent device
866 return childDevice
867 }
khenaidoo19d7b632018-10-30 10:49:50 -0400868 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400869 return parentDevice
870}
871
khenaidoo0a822f92019-05-08 15:15:57 -0400872//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
873//cannot manage the child devices. This will trigger the Core to disable all the child devices.
874func (dMgr *DeviceManager) childDevicesLost(parentDeviceId string) error {
875 log.Debug("childDevicesLost")
876 var err error
877 var parentDevice *voltha.Device
878 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
879 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
880 return err
881 }
882 return dMgr.DisableAllChildDevices(parentDevice)
883}
884
885//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
886// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
887func (dMgr *DeviceManager) childDevicesDetected(parentDeviceId string) error {
888 log.Debug("childDevicesDetected")
889 var err error
890 var parentDevice *voltha.Device
891 var childDeviceIds []string
892
893 if parentDevice, err = dMgr.GetDevice(parentDeviceId); err != nil {
894 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceId, "error": err})
895 return err
896 }
897
898 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
899 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
900 }
901 if len(childDeviceIds) == 0 {
902 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
903 }
904 allChildDisable := true
905 for _, childDeviceId := range childDeviceIds {
906 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
907 if err = agent.enableDevice(nil); err != nil {
908 log.Errorw("failure-enable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
909 allChildDisable = false
910 }
911 }
912 }
913 if !allChildDisable {
914 return err
915 }
916 return nil
917}
918
khenaidoo4d4802d2018-10-04 21:59:49 -0400919/*
920All the functions below are callback functions where they are invoked with the latest and previous data. We can
921therefore use the data as is without trying to get the latest from the model.
922*/
923
khenaidoo0a822f92019-05-08 15:15:57 -0400924//DisableAllChildDevices is invoked as a callback when the parent device is disabled
925func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
926 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -0400927 var childDeviceIds []string
928 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400929 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
930 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400931 }
932 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400933 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400934 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400935 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400936 for _, childDeviceId := range childDeviceIds {
937 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
938 if err = agent.disableDevice(nil); err != nil {
939 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400940 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400941 }
942 }
943 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400944 if !allChildDisable {
945 return err
946 }
khenaidoo92e62c52018-10-03 14:02:54 -0400947 return nil
948}
949
khenaidoo0a822f92019-05-08 15:15:57 -0400950//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
951func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
952 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -0400953 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400954 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400955 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
956 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400957 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400958 if len(childDeviceIds) == 0 {
959 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
960 }
961 allChildDeleted := true
962 for _, childDeviceId := range childDeviceIds {
963 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
964 if err = agent.deleteDevice(nil); err != nil {
965 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
966 allChildDeleted = false
967 } else {
968 agent.stop(nil)
969 dMgr.deleteDeviceAgentToMap(agent)
970 }
971 }
972 }
973 if !allChildDeleted {
974 return err
975 }
976 return nil
977}
978
khenaidoo6d62c002019-05-15 21:57:03 -0400979//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
980// data from the agent instead of using the data from the parent device as that data would disappear from a parent
981// device during a delete device operation.
982func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentId(id string) []string {
983 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
984 deviceIds := make([]string, 0)
985 dMgr.lockDeviceAgentsMap.RLock()
986 defer dMgr.lockDeviceAgentsMap.RUnlock()
987 for deviceId, agent := range dMgr.deviceAgents {
988 if agent.parentId == id {
989 deviceIds = append(deviceIds, deviceId)
990 }
991 }
992 return deviceIds
993}
994
khenaidoo4d4802d2018-10-04 21:59:49 -0400995//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
996func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
997 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400998 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400999 if parentDevice != nil {
1000 for _, port := range parentDevice.Ports {
1001 for _, peer := range port.Peers {
1002 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1003 }
khenaidoo92e62c52018-10-03 14:02:54 -04001004 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001005 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001006 }
1007 return childDeviceIds, nil
1008}
1009
khenaidoo297cd252019-02-07 22:10:23 -05001010//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1011func (dMgr *DeviceManager) getAllChildDevices(parentDeviceId string) (*voltha.Devices, error) {
1012 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceId})
1013 if parentDevice, err := dMgr.GetDevice(parentDeviceId); err == nil {
1014 childDevices := make([]*voltha.Device, 0)
1015 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
1016 for _, deviceId := range childDeviceIds {
1017 if d, e := dMgr.GetDevice(deviceId); e == nil && d != nil {
1018 childDevices = append(childDevices, d)
1019 }
1020 }
1021 }
1022 return &voltha.Devices{Items: childDevices}, nil
1023 }
1024 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceId)
1025}
1026
khenaidoo0a822f92019-05-08 15:15:57 -04001027func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001028 log.Info("addUNILogicalPort")
khenaidoofc1314d2019-03-14 09:34:21 -04001029 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001030 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1031 return err
1032 }
1033 return nil
1034}
1035
khenaidoof5a5bfa2019-01-23 22:20:29 -05001036func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1037 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1038 var res interface{}
1039 var err error
1040 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1041 if res, err = agent.downloadImage(ctx, img); err != nil {
1042 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1043 res = err
1044 }
1045 } else {
1046 res = status.Errorf(codes.NotFound, "%s", img.Id)
1047 }
1048 sendResponse(ctx, ch, res)
1049}
1050
1051func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1052 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1053 var res interface{}
1054 var err error
1055 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1056 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1057 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1058 res = err
1059 }
1060 } else {
1061 res = status.Errorf(codes.NotFound, "%s", img.Id)
1062 }
1063 sendResponse(ctx, ch, res)
1064}
1065
1066func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1067 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1068 var res interface{}
1069 var err error
1070 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1071 if res, err = agent.activateImage(ctx, img); err != nil {
1072 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1073 res = err
1074 }
1075 } else {
1076 res = status.Errorf(codes.NotFound, "%s", img.Id)
1077 }
1078 sendResponse(ctx, ch, res)
1079}
1080
1081func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1082 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1083 var res interface{}
1084 var err error
1085 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1086 if res, err = agent.revertImage(ctx, img); err != nil {
1087 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1088 res = err
1089 }
1090 } else {
1091 res = status.Errorf(codes.NotFound, "%s", img.Id)
1092 }
1093 sendResponse(ctx, ch, res)
1094}
1095
1096func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1097 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1098 var res interface{}
1099 var err error
1100 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1101 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1102 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1103 res = err
1104 }
1105 } else {
1106 res = status.Errorf(codes.NotFound, "%s", img.Id)
1107 }
1108 sendResponse(ctx, ch, res)
1109}
1110
khenaidoof5a5bfa2019-01-23 22:20:29 -05001111func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
1112 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1113 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1114 if err := agent.updateImageDownload(img); err != nil {
1115 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1116 return err
1117 }
1118 } else {
1119 return status.Errorf(codes.NotFound, "%s", img.Id)
1120 }
1121 return nil
1122}
1123
1124func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1125 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1126 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1127 return agent.getImageDownload(ctx, img)
1128 }
1129 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1130}
1131
1132func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
1133 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
1134 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
1135 return agent.listImageDownloads(ctx, deviceId)
1136 }
1137 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
1138}
1139
khenaidoo0a822f92019-05-08 15:15:57 -04001140func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1141 log.Info("SetAdminStateToEnable")
1142 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1143 return agent.updateAdminState(voltha.AdminState_ENABLED)
1144 }
1145 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1146}
1147
khenaidoo92e62c52018-10-03 14:02:54 -04001148func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001149 log.Info("activateDevice")
1150 return nil
1151}
1152
khenaidoo92e62c52018-10-03 14:02:54 -04001153func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
1154 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -04001155 return nil
1156}
1157
khenaidoo92e62c52018-10-03 14:02:54 -04001158func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001159 log.Info("abandonDevice")
1160 return nil
1161}
1162
khenaidoo92e62c52018-10-03 14:02:54 -04001163func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001164 log.Info("reEnableDevice")
1165 return nil
1166}
1167
khenaidoo92e62c52018-10-03 14:02:54 -04001168func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001169 log.Info("noOp")
1170 return nil
1171}
1172
khenaidoo92e62c52018-10-03 14:02:54 -04001173func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001174 log.Info("notAllowed")
khenaidoo2c6a0992019-04-29 13:46:56 -04001175 return errors.New("transition-not-allowed")
khenaidoob9203542018-09-17 22:56:37 -04001176}
1177
khenaidoo0a822f92019-05-08 15:15:57 -04001178func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
1179 log.Errorw("NotifyInvalidTransition", log.Fields{"device": pcDevice.Id, "adminState": pcDevice.AdminState})
1180 //TODO: notify over kafka?
1181 return nil
1182}
1183
khenaidoob9203542018-09-17 22:56:37 -04001184func funcName(f interface{}) string {
1185 p := reflect.ValueOf(f).Pointer()
1186 rf := runtime.FuncForPC(p)
1187 return rf.Name()
1188}
1189
1190func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
1191 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
1192 agent.updateDeviceAttribute(attribute, value)
1193 }
1194}
1195
1196func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -04001197 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001198 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -04001199 return &device.ParentId
1200 }
1201 return nil
1202}
serkant.uluderya334479d2019-04-10 08:26:15 -07001203
1204func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1205 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1206 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1207 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1208 var res interface{}
1209 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1210 res = agent.simulateAlarm(ctx, simulatereq)
1211 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1212 }
1213 //TODO CLI always get successful response
1214 sendResponse(ctx, ch, res)
1215}