blob: 9e4956ece7e0f7bcddfd215afccb78f676316552 [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 */
npujar1d86a522019-11-14 17:11:16 +053016
khenaidoob9203542018-09-17 22:56:37 -040017package core
18
19import (
20 "context"
21 "errors"
npujar1d86a522019-11-14 17:11:16 +053022 "reflect"
23 "runtime"
24 "sync"
25
sbarbari17d7e222019-11-05 10:02:29 -050026 "github.com/opencord/voltha-go/db/model"
khenaidoo3d3b8c22019-05-22 18:10:39 -040027 "github.com/opencord/voltha-go/rw_core/utils"
Scott Baker807addd2019-10-24 15:16:21 -070028 "github.com/opencord/voltha-lib-go/v2/pkg/kafka"
29 "github.com/opencord/voltha-lib-go/v2/pkg/log"
30 "github.com/opencord/voltha-lib-go/v2/pkg/probe"
Scott Baker555307d2019-11-04 08:58:01 -080031 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
32 ofp "github.com/opencord/voltha-protos/v2/go/openflow_13"
33 "github.com/opencord/voltha-protos/v2/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040034 "google.golang.org/grpc/codes"
35 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040036)
37
npujar1d86a522019-11-14 17:11:16 +053038// DeviceManager represent device manager attributes
khenaidoob9203542018-09-17 22:56:37 -040039type DeviceManager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040040 deviceAgents sync.Map
41 rootDevices map[string]bool
42 lockRootDeviceMap sync.RWMutex
43 core *Core
44 adapterProxy *AdapterProxy
45 adapterMgr *AdapterManager
46 logicalDeviceMgr *LogicalDeviceManager
47 kafkaICProxy *kafka.InterContainerProxy
48 stateTransitions *TransitionMap
49 clusterDataProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053050 coreInstanceID string
khenaidoo4c9e5592019-09-09 16:20:41 -040051 exitChannel chan int
52 defaultTimeout int64
53 devicesLoadingLock sync.RWMutex
54 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040055}
56
Richard Jankowski199fd862019-03-18 14:49:51 -040057func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040058 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040059 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040060 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040061 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040062 deviceMgr.kafkaICProxy = core.kmp
Kent Hagermana6d0c362019-07-30 12:50:21 -040063 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic)
npujar1d86a522019-11-14 17:11:16 +053064 deviceMgr.coreInstanceID = core.instanceID
Richard Jankowski199fd862019-03-18 14:49:51 -040065 deviceMgr.clusterDataProxy = core.clusterDataProxy
66 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040067 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
68 deviceMgr.defaultTimeout = core.config.DefaultCoreTimeout
khenaidoo4c9e5592019-09-09 16:20:41 -040069 deviceMgr.devicesLoadingLock = sync.RWMutex{}
70 deviceMgr.deviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040071 return &deviceMgr
72}
73
khenaidoo4d4802d2018-10-04 21:59:49 -040074func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040075 log.Info("starting-device-manager")
76 dMgr.logicalDeviceMgr = logicalDeviceMgr
77 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070078 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
khenaidoob9203542018-09-17 22:56:37 -040079 log.Info("device-manager-started")
80}
81
khenaidoo4d4802d2018-10-04 21:59:49 -040082func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040083 log.Info("stopping-device-manager")
84 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070085 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
khenaidoob9203542018-09-17 22:56:37 -040086 log.Info("device-manager-stopped")
87}
88
89func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
90 if ctx.Err() == nil {
91 // Returned response only of the ctx has not been cancelled/timeout/etc
92 // Channel is automatically closed when a context is Done
93 ch <- result
94 log.Debugw("sendResponse", log.Fields{"result": result})
95 } else {
96 // Should the transaction be reverted back?
97 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
98 }
99}
100
101func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530102 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
103 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -0400104 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400105 dMgr.lockRootDeviceMap.Lock()
106 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530107 dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400108
khenaidoob9203542018-09-17 22:56:37 -0400109}
110
khenaidoo4c9e5592019-09-09 16:20:41 -0400111func (dMgr *DeviceManager) deleteDeviceAgentFromMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530112 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400113 dMgr.lockRootDeviceMap.Lock()
114 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530115 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400116}
117
khenaidoo297cd252019-02-07 22:10:23 -0500118// getDeviceAgent returns the agent managing the device. If the device is not in memory, it will loads it, if it exists
npujar1d86a522019-11-14 17:11:16 +0530119func (dMgr *DeviceManager) getDeviceAgent(deviceID string) *DeviceAgent {
120 agent, ok := dMgr.deviceAgents.Load(deviceID)
121 if ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400122 return agent.(*DeviceAgent)
khenaidoob9203542018-09-17 22:56:37 -0400123 }
npujar1d86a522019-11-14 17:11:16 +0530124 // Try to load into memory - loading will also create the device agent and set the device ownership
125 err := dMgr.load(deviceID)
126 if err == nil {
127 agent, ok = dMgr.deviceAgents.Load(deviceID)
128 if !ok {
129 return nil
130 }
131 // Register this device for ownership tracking
132 go func() {
133 _, err = dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{ID: deviceID})
134 if err != nil {
135 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
136 }
137 }()
138 return agent.(*DeviceAgent)
139 }
140 //TODO: Change the return params to return an error as well
141 log.Errorw("loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400142 return nil
143}
144
khenaidoo297cd252019-02-07 22:10:23 -0500145// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500146func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500147 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400148
149 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
150 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
151 return true
152 })
153
khenaidoo7ccedd52018-12-14 16:48:54 -0500154 return result
155}
156
khenaidoob9203542018-09-17 22:56:37 -0400157func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530158 if dMgr.isParentDeviceExist(device) {
159 log.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
160 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
161 return
162 }
khenaidoo92e62c52018-10-03 14:02:54 -0400163 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400164
khenaidoo5e677ae2019-02-28 17:26:29 -0500165 // Ensure this device is set as root
166 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400167 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400168 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400169 dMgr.addDeviceAgentToMap(agent)
Scott Baker80678602019-11-14 16:57:36 -0800170 device, err := agent.start(ctx, device)
171 if err != nil {
172 log.Errorf("Failed to start device")
173 sendResponse(ctx, ch, errors.New("Failed to start device"))
174 return
175 }
khenaidoob9203542018-09-17 22:56:37 -0400176
Scott Baker80678602019-11-14 16:57:36 -0800177 sendResponse(ctx, ch, device)
khenaidoob9203542018-09-17 22:56:37 -0400178}
179
180func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400181 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400182 var res interface{}
183 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
184 res = agent.enableDevice(ctx)
185 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400186 }
187
188 sendResponse(ctx, ch, res)
189}
190
khenaidoo92e62c52018-10-03 14:02:54 -0400191func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
192 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400193 var res interface{}
194 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
195 res = agent.disableDevice(ctx)
196 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400197 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400198 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400199 }
khenaidoo92e62c52018-10-03 14:02:54 -0400200
201 sendResponse(ctx, ch, res)
202}
203
khenaidoo4d4802d2018-10-04 21:59:49 -0400204func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
205 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
206 var res interface{}
207 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
208 res = agent.rebootDevice(ctx)
209 log.Debugw("rebootDevice-result", log.Fields{"result": res})
210 } else {
211 res = status.Errorf(codes.NotFound, "%s", id.Id)
212 }
213 sendResponse(ctx, ch, res)
214}
215
216func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
217 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
218 var res interface{}
219 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
220 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400221 log.Debugw("deleteDevice-result", log.Fields{"result": res})
222 } else {
223 res = status.Errorf(codes.NotFound, "%s", id.Id)
224 }
225 sendResponse(ctx, ch, res)
226}
227
khenaidoo6d62c002019-05-15 21:57:03 -0400228// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
229// This function is called only in the Core that does not own this device. In the Core that owns this device then a
230// deletion deletion also includes removal of any reference of this device.
231func (dMgr *DeviceManager) stopManagingDevice(id string) {
232 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
233 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530234 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400235 // stop managing the logical device
npujar1d86a522019-11-14 17:11:16 +0530236 ldeviceID := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(id)
237 if ldeviceID != "" { // Can happen if logical device agent was already stopped
238 err := dMgr.core.deviceOwnership.AbandonDevice(ldeviceID)
239 if err != nil {
240 log.Errorw("unable-to-abandon-the-device", log.Fields{"error": err})
241 }
khenaidoo6d62c002019-05-15 21:57:03 -0400242 }
243 // stop managing the child devices
npujar1d86a522019-11-14 17:11:16 +0530244 childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentID(id)
245 for _, cID := range childDeviceIds {
246 dMgr.stopManagingDevice(cID)
khenaidoo6d62c002019-05-15 21:57:03 -0400247 }
248 }
249 if agent := dMgr.getDeviceAgent(id); agent != nil {
npujar1d86a522019-11-14 17:11:16 +0530250 agent.stop(context.TODO())
khenaidoo4c9e5592019-09-09 16:20:41 -0400251 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400252 // Abandon the device ownership
npujar1d86a522019-11-14 17:11:16 +0530253 err := dMgr.core.deviceOwnership.AbandonDevice(id)
254 if err != nil {
255 log.Errorw("unable-to-abandon-device", log.Fields{"error": err})
256 }
khenaidoo6d62c002019-05-15 21:57:03 -0400257 }
258 }
259}
260
npujar1d86a522019-11-14 17:11:16 +0530261// RunPostDeviceDelete removes any reference of this device
khenaidoo0a822f92019-05-08 15:15:57 -0400262func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
263 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400264 dMgr.stopManagingDevice(cDevice.Id)
265 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400266}
267
khenaidoo297cd252019-02-07 22:10:23 -0500268// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400269func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
270 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400271 if agent := dMgr.getDeviceAgent(id); agent != nil {
272 return agent.getDevice()
273 }
274 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400275}
276
npujar1d86a522019-11-14 17:11:16 +0530277// GetChildDevice will return a device, either from memory or from the dB, if present
278func (dMgr *DeviceManager) GetChildDevice(parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
279 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
280 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500281
282 var parentDevice *voltha.Device
283 var err error
npujar1d86a522019-11-14 17:11:16 +0530284 if parentDevice, err = dMgr.GetDevice(parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500285 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
286 }
287 var childDeviceIds []string
288 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
289 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
290 }
291 if len(childDeviceIds) == 0 {
npujar1d86a522019-11-14 17:11:16 +0530292 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
293 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500294 }
295
296 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530297 for _, childDeviceID := range childDeviceIds {
298 var found bool
299 if searchDevice, err := dMgr.GetDevice(childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500300
npujar1d86a522019-11-14 17:11:16 +0530301 foundOnuID := false
302 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500303 if searchDevice.ParentPortNo == uint32(parentPortNo) {
npujar1d86a522019-11-14 17:11:16 +0530304 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
305 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500306 }
307 }
308
309 foundSerialNumber := false
310 if searchDevice.SerialNumber == serialNumber {
311 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
312 foundSerialNumber = true
313 }
314
315 // if both onuId and serialNumber are provided both must be true for the device to be found
316 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530317 if onuID > 0 && serialNumber != "" {
318 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500319 } else {
npujar1d86a522019-11-14 17:11:16 +0530320 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500321 }
322
npujar1d86a522019-11-14 17:11:16 +0530323 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500324 foundChildDevice = searchDevice
325 break
326 }
327 }
328 }
329
330 if foundChildDevice != nil {
331 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
332 return foundChildDevice, nil
333 }
334
335 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530336 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
337 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500338}
339
npujar1d86a522019-11-14 17:11:16 +0530340// GetChildDeviceWithProxyAddress will return a device based on proxy address
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500341func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
342 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
343
344 var parentDevice *voltha.Device
345 var err error
346 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
347 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
348 }
349 var childDeviceIds []string
350 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
351 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
352 }
353 if len(childDeviceIds) == 0 {
354 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
355 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
356 }
357
358 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530359 for _, childDeviceID := range childDeviceIds {
360 if searchDevice, err := dMgr.GetDevice(childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500361 if searchDevice.ProxyAddress == proxyAddress {
362 foundChildDevice = searchDevice
363 break
364 }
365 }
366 }
367
368 if foundChildDevice != nil {
369 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
370 return foundChildDevice, nil
371 }
372
373 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
374 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
375}
376
npujar1d86a522019-11-14 17:11:16 +0530377// IsDeviceInCache returns true if device is found in the map
khenaidoo297cd252019-02-07 22:10:23 -0500378func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400379 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500380 return exist
381}
382
npujar1d86a522019-11-14 17:11:16 +0530383// IsRootDevice returns true if root device is found in the map
khenaidoo19d7b632018-10-30 10:49:50 -0400384func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400385 dMgr.lockRootDeviceMap.RLock()
386 defer dMgr.lockRootDeviceMap.RUnlock()
387 if exist := dMgr.rootDevices[id]; exist {
388 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400389 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400390 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400391}
392
Stephane Barbarieaa467942019-02-06 14:09:44 -0500393// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400394func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400395 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400396 result := &voltha.Devices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400397 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500398 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500399 // If device is not in memory then set it up
400 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400401 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400402 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar1d86a522019-11-14 17:11:16 +0530403 if _, err := agent.start(context.TODO(), nil); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500404 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
npujar1d86a522019-11-14 17:11:16 +0530405 agent.stop(context.TODO())
khenaidoo297cd252019-02-07 22:10:23 -0500406 } else {
407 dMgr.addDeviceAgentToMap(agent)
408 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500409 }
410 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400411 }
412 }
khenaidoo6d62c002019-05-15 21:57:03 -0400413 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400414 return result, nil
415}
416
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530417//isParentDeviceExist checks whether device is already preprovisioned.
418func (dMgr *DeviceManager) isParentDeviceExist(newDevice *voltha.Device) bool {
419 hostPort := newDevice.GetHostAndPort()
420 if devices := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, ""); devices != nil {
421 for _, device := range devices.([]interface{}) {
422 if !device.(*voltha.Device).Root {
423 continue
424 }
425 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() {
426 return true
427 }
428 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress {
429 return true
430 }
431 }
432 }
433 return false
434}
435
khenaidoo6d62c002019-05-15 21:57:03 -0400436//getDeviceFromModelretrieves the device data from the model.
npujar1d86a522019-11-14 17:11:16 +0530437func (dMgr *DeviceManager) getDeviceFromModel(deviceID string) (*voltha.Device, error) {
438 if device := dMgr.clusterDataProxy.Get(context.Background(), "/devices/"+deviceID, 0, false, ""); device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400439 if d, ok := device.(*voltha.Device); ok {
440 return d, nil
441 }
442 }
npujar1d86a522019-11-14 17:11:16 +0530443 return nil, status.Error(codes.NotFound, deviceID)
khenaidoo6d62c002019-05-15 21:57:03 -0400444}
445
npujar1d86a522019-11-14 17:11:16 +0530446// loadDevice loads the deviceID in memory, if not present
447func (dMgr *DeviceManager) loadDevice(deviceID string) (*DeviceAgent, error) {
448 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500449 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
450 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400451 var err error
452 var device *voltha.Device
453 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530454 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
455 if !dMgr.IsDeviceInCache(deviceID) {
456 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400457 dMgr.devicesLoadingLock.Unlock()
458 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar1d86a522019-11-14 17:11:16 +0530459 if device, err = dMgr.getDeviceFromModel(deviceID); err == nil {
460 log.Debugw("loading-device", log.Fields{"deviceId": deviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400461 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar1d86a522019-11-14 17:11:16 +0530462 if _, err = agent.start(context.TODO(), nil); err != nil {
463 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
464 agent.stop(context.TODO())
khenaidoo4c9e5592019-09-09 16:20:41 -0400465 } else {
466 dMgr.addDeviceAgentToMap(agent)
467 }
468 } else {
npujar1d86a522019-11-14 17:11:16 +0530469 log.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400470 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400471 // announce completion of task to any number of waiting channels
472 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530473 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400474 for _, ch := range v {
475 close(ch)
476 }
npujar1d86a522019-11-14 17:11:16 +0530477 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400478 }
479 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400480 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400481 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500482 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400483 } else {
484 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530485 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400486 dMgr.devicesLoadingLock.Unlock()
487 // Wait for the channel to be closed, implying the process loading this device is done.
488 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500489 }
npujar1d86a522019-11-14 17:11:16 +0530490 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400491 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500492 }
npujar1d86a522019-11-14 17:11:16 +0530493 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500494}
495
496// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
497func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
498 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
499 if device.Root {
500 // Scenario A
501 if device.ParentId != "" {
502 // Load logical device if needed.
503 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
504 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
505 }
506 } else {
507 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
508 }
509 // Load all child devices, if needed
510 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530511 for _, childDeviceID := range childDeviceIds {
512 if _, err := dMgr.loadDevice(childDeviceID); err != nil {
513 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500514 return err
515 }
516 }
517 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
518 } else {
519 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
520 }
521 }
522 return nil
523}
524
525// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
526// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
527// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
528// and the proceed with the request.
npujar1d86a522019-11-14 17:11:16 +0530529func (dMgr *DeviceManager) load(deviceID string) error {
khenaidoo297cd252019-02-07 22:10:23 -0500530 log.Debug("load...")
531 // First load the device - this may fail in case the device was deleted intentionally by the other core
532 var dAgent *DeviceAgent
533 var err error
npujar1d86a522019-11-14 17:11:16 +0530534 if dAgent, err = dMgr.loadDevice(deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500535 return err
536 }
537 // Get the loaded device details
538 var device *voltha.Device
539 if device, err = dAgent.getDevice(); err != nil {
540 return err
541 }
542
543 // If the device is in Pre-provisioning or deleted state stop here
544 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
545 return nil
546 }
547
548 // Now we face two scenarios
549 if device.Root {
550 // Load all children as well as the parent of this device (logical_device)
551 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530552 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500553 return err
554 }
npujar1d86a522019-11-14 17:11:16 +0530555 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500556 } else {
557 // Scenario B - use the parentId of that device (root device) to trigger the loading
558 if device.ParentId != "" {
559 return dMgr.load(device.ParentId)
560 }
561 }
562 return nil
563}
564
khenaidoo7ccedd52018-12-14 16:48:54 -0500565// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
566func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
567 log.Debug("ListDeviceIDs")
568 // Report only device IDs that are in the device agent map
569 return dMgr.listDeviceIdsFromMap(), nil
570}
571
khenaidoo4c9e5592019-09-09 16:20:41 -0400572//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
573//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500574func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400575 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500576 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400577 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500578 toReconcile := len(ids.Items)
579 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400580 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500581 for _, id := range ids.Items {
khenaidoo4c9e5592019-09-09 16:20:41 -0400582 if err = dMgr.load(id.Id); err != nil {
583 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
584 } else {
npujar1d86a522019-11-14 17:11:16 +0530585 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500586 }
587 }
588 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400589 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500590 }
591 } else {
592 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
593 }
594 sendResponse(ctx, ch, res)
595}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500596
khenaidooba6b6c42019-08-02 09:11:56 -0400597// isOkToReconcile validates whether a device is in the correct status to be reconciled
598func isOkToReconcile(device *voltha.Device) bool {
599 if device == nil {
600 return false
601 }
602 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
603}
604
605// adapterRestarted is invoked whenever an adapter is restarted
606func (dMgr *DeviceManager) adapterRestarted(adapter *voltha.Adapter) error {
607 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
608
609 // Let's reconcile the device managed by this Core only
610 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
611 if len(rootDeviceIds) == 0 {
612 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
613 return nil
614 }
615
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500616 responses := make([]utils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530617 for _, rootDeviceID := range rootDeviceIds {
618 if rootDevice, _ := dMgr.getDeviceFromModel(rootDeviceID); rootDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400619 if rootDevice.Adapter == adapter.Id {
620 if isOkToReconcile(rootDevice) {
621 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500622 responses = append(responses, dMgr.sendReconcileDeviceRequest(rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400623 } else {
624 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
625 }
626 } else { // Should we be reconciling the root's children instead?
627 childManagedByAdapter:
628 for _, port := range rootDevice.Ports {
629 for _, peer := range port.Peers {
630 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
631 if childDevice.Adapter == adapter.Id {
632 if isOkToReconcile(childDevice) {
633 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500634 responses = append(responses, dMgr.sendReconcileDeviceRequest(childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400635 } else {
636 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
637 }
638 } else {
639 // All child devices under a parent device are typically managed by the same adapter type.
640 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
641 break childManagedByAdapter
642 }
643 }
644 }
645 }
646 }
647 }
648 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500649 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400650 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500651 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400652 return status.Errorf(codes.Aborted, "errors-%s", res)
653 }
654 } else {
655 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
656 }
657 return nil
658}
659
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500660func (dMgr *DeviceManager) sendReconcileDeviceRequest(device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400661 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
662 // point of creating a device agent (if the device is not being managed by this Core) before sending the request
npujar1d86a522019-11-14 17:11:16 +0530663 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to the adapter via
khenaidooba6b6c42019-08-02 09:11:56 -0400664 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500665 response := utils.NewResponse()
khenaidooba6b6c42019-08-02 09:11:56 -0400666 go func(device *voltha.Device) {
667 if err := dMgr.adapterProxy.ReconcileDevice(context.Background(), device); err != nil {
668 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500669 response.Error(status.Errorf(codes.Internal, "device: %s", device.Id))
khenaidooba6b6c42019-08-02 09:11:56 -0400670 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500671 response.Done()
khenaidooba6b6c42019-08-02 09:11:56 -0400672 }(device)
673
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500674 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400675}
676
npujar1d86a522019-11-14 17:11:16 +0530677func (dMgr *DeviceManager) reconcileChildDevices(parentDeviceID string) error {
678 if parentDevice, _ := dMgr.getDeviceFromModel(parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500679 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400680 for _, port := range parentDevice.Ports {
681 for _, peer := range port.Peers {
682 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500683 responses = append(responses, dMgr.sendReconcileDeviceRequest(childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400684 }
685 }
686 }
687 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500688 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400689 return status.Errorf(codes.Aborted, "errors-%s", res)
690 }
691 }
692 return nil
693}
694
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700695func (dMgr *DeviceManager) updateDeviceUsingAdapterData(device *voltha.Device) error {
696 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400697 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700698 return agent.updateDeviceUsingAdapterData(device)
khenaidoob9203542018-09-17 22:56:37 -0400699 }
700 return status.Errorf(codes.NotFound, "%s", device.Id)
701}
702
npujar1d86a522019-11-14 17:11:16 +0530703func (dMgr *DeviceManager) addPort(deviceID string, port *voltha.Port) error {
704 agent := dMgr.getDeviceAgent(deviceID)
705 if agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400706 if err := agent.addPort(port); err != nil {
707 return err
708 }
709 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530710 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400711 for _, peerPort := range port.Peers {
712 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
713 if err := agent.addPeerPort(meAsPeer); err != nil {
714 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
715 return err
716 }
717 }
718 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400719 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
720 // then a logical port will be added to the logical device and the device graph generated. If the port is a
721 // PON port then only the device graph will be generated.
npujar1d86a522019-11-14 17:11:16 +0530722 if device, err := dMgr.GetDevice(deviceID); err == nil {
723 go func() {
724 err = dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
725 if err != nil {
726 log.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
727 }
728 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400729 } else {
npujar1d86a522019-11-14 17:11:16 +0530730 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400731 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400732 }
khenaidoo92e62c52018-10-03 14:02:54 -0400733 return nil
khenaidoob9203542018-09-17 22:56:37 -0400734 }
npujar1d86a522019-11-14 17:11:16 +0530735 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400736}
737
npujar1d86a522019-11-14 17:11:16 +0530738func (dMgr *DeviceManager) deletePeerPorts(fromDeviceID string, deviceID string) error {
739 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceID, "deviceid": deviceID})
740 if agent := dMgr.getDeviceAgent(fromDeviceID); agent != nil {
741 return agent.deletePeerPorts(deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400742 }
npujar1d86a522019-11-14 17:11:16 +0530743 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400744}
745
npujar1d86a522019-11-14 17:11:16 +0530746func (dMgr *DeviceManager) addFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
747 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "flowMetadata": flowMetadata})
748 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400749 return agent.addFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400750 }
npujar1d86a522019-11-14 17:11:16 +0530751 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400752}
753
npujar1d86a522019-11-14 17:11:16 +0530754func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
755 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
756 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400757 return agent.deleteFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400758 }
npujar1d86a522019-11-14 17:11:16 +0530759 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400760}
761
npujar1d86a522019-11-14 17:11:16 +0530762func (dMgr *DeviceManager) updateFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
763 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
764 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400765 return agent.updateFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400766 }
npujar1d86a522019-11-14 17:11:16 +0530767 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400768}
769
khenaidoob3127472019-07-24 21:04:55 -0400770// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
771// following a user action
772func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
773 var res interface{}
774 if pmConfigs.Id == "" {
775 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
776 } else if agent := dMgr.getDeviceAgent(pmConfigs.Id); agent != nil {
777 res = agent.updatePmConfigs(ctx, pmConfigs)
778 } else {
779 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
780 }
781 sendResponse(ctx, ch, res)
782}
783
784// initPmConfigs initialize the pm configs as defined by the adapter.
npujar1d86a522019-11-14 17:11:16 +0530785func (dMgr *DeviceManager) initPmConfigs(deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400786 if pmConfigs.Id == "" {
787 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
788 }
npujar1d86a522019-11-14 17:11:16 +0530789 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400790 return agent.initPmConfigs(pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400791 }
npujar1d86a522019-11-14 17:11:16 +0530792 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400793}
794
npujar1d86a522019-11-14 17:11:16 +0530795func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
796 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400797 return agent.listPmConfigs(ctx)
798 }
npujar1d86a522019-11-14 17:11:16 +0530799 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400800}
801
npujar1d86a522019-11-14 17:11:16 +0530802func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
803 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
804 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400805 return agent.getSwitchCapability(ctx)
806 }
npujar1d86a522019-11-14 17:11:16 +0530807 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400808}
809
npujar1d86a522019-11-14 17:11:16 +0530810func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
811 log.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
812 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400813 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400814 }
npujar1d86a522019-11-14 17:11:16 +0530815 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400816}
817
npujar1d86a522019-11-14 17:11:16 +0530818func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
819 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
820 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400821 return agent.getPortCapability(ctx, portNo)
822 }
npujar1d86a522019-11-14 17:11:16 +0530823 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400824}
825
npujar1d86a522019-11-14 17:11:16 +0530826func (dMgr *DeviceManager) updateDeviceStatus(deviceID string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
827 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
828 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400829 return agent.updateDeviceStatus(operStatus, connStatus)
830 }
npujar1d86a522019-11-14 17:11:16 +0530831 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400832}
833
npujar1d86a522019-11-14 17:11:16 +0530834func (dMgr *DeviceManager) updateChildrenStatus(deviceID string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
835 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400836 var parentDevice *voltha.Device
837 var err error
npujar1d86a522019-11-14 17:11:16 +0530838 if parentDevice, err = dMgr.GetDevice(deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400839 return status.Errorf(codes.Aborted, "%s", err.Error())
840 }
841 var childDeviceIds []string
842 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
843 return status.Errorf(codes.Aborted, "%s", err.Error())
844 }
845 if len(childDeviceIds) == 0 {
846 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
847 }
npujar1d86a522019-11-14 17:11:16 +0530848 for _, childDeviceID := range childDeviceIds {
849 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400850 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530851 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400852 }
853 }
854 }
855 return nil
856}
857
npujar1d86a522019-11-14 17:11:16 +0530858func (dMgr *DeviceManager) updatePortState(deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
859 log.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
860 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo171b98e2019-10-31 11:48:15 -0400861 if err := agent.updatePortState(portType, portNo, operStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530862 log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400863 return err
864 }
865 // Notify the logical device manager to change the port state
npujar1d86a522019-11-14 17:11:16 +0530866 go func() {
867 err := dMgr.logicalDeviceMgr.updatePortState(deviceID, portNo, operStatus)
868 if err != nil {
869 log.Errorw("unable-to-update-port-state", log.Fields{"error": err})
870 }
871 }()
khenaidoob9203542018-09-17 22:56:37 -0400872 }
npujar1d86a522019-11-14 17:11:16 +0530873 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400874}
875
npujar1d86a522019-11-14 17:11:16 +0530876func (dMgr *DeviceManager) deleteAllPorts(deviceID string) error {
877 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
878 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400879 if err := agent.deleteAllPorts(); err != nil {
880 return err
881 }
882 // Notify the logical device manager to remove all logical ports, if needed.
883 // At this stage the device itself may gave been deleted already at a deleteAllPorts
884 // typically is part of a device deletion phase.
npujar1d86a522019-11-14 17:11:16 +0530885 if device, err := dMgr.GetDevice(deviceID); err == nil {
886 go func() {
887 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
888 if err != nil {
889 log.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
890 }
891 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400892 } else {
npujar1d86a522019-11-14 17:11:16 +0530893 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400894 return err
895 }
896 return nil
897 }
npujar1d86a522019-11-14 17:11:16 +0530898 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400899}
900
khenaidoo3ab34882019-05-02 21:33:30 -0400901//updatePortsState updates all ports on the device
npujar1d86a522019-11-14 17:11:16 +0530902func (dMgr *DeviceManager) updatePortsState(deviceID string, state voltha.OperStatus_OperStatus) error {
903 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400904
905 var adminState voltha.AdminState_AdminState
npujar1d86a522019-11-14 17:11:16 +0530906 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400907 switch state {
908 case voltha.OperStatus_ACTIVE:
909 adminState = voltha.AdminState_ENABLED
910 if err := agent.enablePorts(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530911 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400912 return err
913 }
914 case voltha.OperStatus_UNKNOWN:
915 adminState = voltha.AdminState_DISABLED
916 if err := agent.disablePorts(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530917 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400918 return err
919 }
920 default:
921 return status.Error(codes.Unimplemented, "state-change-not-implemented")
922 }
923 // Notify the logical device about the state change
npujar1d86a522019-11-14 17:11:16 +0530924 device, err := dMgr.GetDevice(deviceID)
925 if err != nil {
926 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400927 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400928 }
npujar1d86a522019-11-14 17:11:16 +0530929 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
930 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
931 return err
932 }
933 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400934 }
npujar1d86a522019-11-14 17:11:16 +0530935 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400936}
937
npujar1d86a522019-11-14 17:11:16 +0530938func (dMgr *DeviceManager) childDeviceDetected(parentDeviceID string, parentPortNo int64, deviceType string,
939 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
940 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceID, "parentPortNo": parentPortNo, "deviceType": deviceType, "channelId": channelID, "vendorId": vendorID, "serialNumber": serialNumber, "onuId": onuID})
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700941
npujar1d86a522019-11-14 17:11:16 +0530942 if deviceType == "" && vendorID != "" {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700943 log.Debug("device-type-is-nil-fetching-device-type")
944 if deviceTypesIf := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, ""); deviceTypesIf != nil {
945 OLoop:
946 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
947 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
948 for _, v := range dType.VendorIds {
npujar1d86a522019-11-14 17:11:16 +0530949 if v == vendorID {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700950 deviceType = dType.Adapter
951 break OLoop
952 }
953 }
954 }
955 }
956 }
957 }
958 //if no match found for the vendorid,report adapter with the custom error message
959 if deviceType == "" {
npujar1d86a522019-11-14 17:11:16 +0530960 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
961 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700962 }
khenaidoob9203542018-09-17 22:56:37 -0400963
964 // Create the ONU device
965 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400966 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530967 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400968 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530969 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500970 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400971 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400972
973 //Get parent device type
npujar1d86a522019-11-14 17:11:16 +0530974 parent, err := dMgr.GetDevice(parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400975 if err != nil {
npujar1d86a522019-11-14 17:11:16 +0530976 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceID})
977 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400978 }
979
npujar1d86a522019-11-14 17:11:16 +0530980 if device, err := dMgr.GetChildDevice(parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
981 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700982 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500983 }
984
npujar1d86a522019-11-14 17:11:16 +0530985 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: parent.Type, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -0400986
987 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400988 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400989 dMgr.addDeviceAgentToMap(agent)
npujar1d86a522019-11-14 17:11:16 +0530990 childDevice, err = agent.start(context.TODO(), childDevice)
Scott Baker80678602019-11-14 16:57:36 -0800991 if err != nil {
992 log.Error("error-starting-child")
993 return nil, err
994 }
khenaidoob9203542018-09-17 22:56:37 -0400995
khenaidoo09771ef2019-10-11 14:25:02 -0400996 // Since this Core has handled this request then it therefore owns this child device. Set the
997 // ownership of this device to this Core
npujar1d86a522019-11-14 17:11:16 +0530998 _, err = dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{ID: agent.deviceID})
999 if err != nil {
1000 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
1001 }
khenaidoo09771ef2019-10-11 14:25:02 -04001002
khenaidoob9203542018-09-17 22:56:37 -04001003 // Activate the child device
npujar1d86a522019-11-14 17:11:16 +05301004 if agent = dMgr.getDeviceAgent(agent.deviceID); agent != nil {
1005 go func() {
1006 err := agent.enableDevice(context.TODO())
1007 if err != nil {
1008 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1009 }
1010 }()
khenaidoob9203542018-09-17 22:56:37 -04001011 }
1012
khenaidoo79232702018-12-04 11:00:41 -05001013 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301014 go func() {
1015 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1016 if err != nil {
1017 log.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
1018 }
1019 }()
khenaidoo79232702018-12-04 11:00:41 -05001020
Scott Baker80678602019-11-14 16:57:36 -08001021 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001022}
1023
1024func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
1025 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -04001026 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
1027 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -05001028 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001029 return nil
khenaidoob9203542018-09-17 22:56:37 -04001030 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001031 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -04001032 for _, handler := range handlers {
1033 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
1034 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -04001035 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001036 return err
1037 }
1038 }
khenaidoob9203542018-09-17 22:56:37 -04001039 return nil
1040}
1041
npujar1d86a522019-11-14 17:11:16 +05301042func (dMgr *DeviceManager) packetOut(deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
1043 log.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
1044 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001045 return agent.packetOut(outPort, packet)
1046 }
npujar1d86a522019-11-14 17:11:16 +05301047 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001048}
1049
npujar1d86a522019-11-14 17:11:16 +05301050// PacketIn receives packet from adapter
1051func (dMgr *DeviceManager) PacketIn(deviceID string, port uint32, transactionID string, packet []byte) error {
1052 log.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001053 // Get the logical device Id based on the deviceId
1054 var device *voltha.Device
1055 var err error
npujar1d86a522019-11-14 17:11:16 +05301056 if device, err = dMgr.GetDevice(deviceID); err != nil {
1057 log.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001058 return err
1059 }
khenaidoo43c82122018-11-22 18:38:28 -05001060 if !device.Root {
npujar1d86a522019-11-14 17:11:16 +05301061 log.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
1062 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001063 }
1064
npujar1d86a522019-11-14 17:11:16 +05301065 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001066 return err
1067 }
1068 return nil
1069}
1070
npujar1d86a522019-11-14 17:11:16 +05301071func (dMgr *DeviceManager) setParentID(device *voltha.Device, parentID string) error {
1072 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
khenaidooad06fd72019-10-28 12:26:05 -04001073 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301074 return agent.setParentID(device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001075 }
1076 return status.Errorf(codes.NotFound, "%s", device.Id)
1077}
1078
npujar1d86a522019-11-14 17:11:16 +05301079// CreateLogicalDevice creates logical device in core
khenaidoo0a822f92019-05-08 15:15:57 -04001080func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
1081 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001082 // Verify whether the logical device has already been created
1083 if cDevice.ParentId != "" {
1084 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1085 return nil
1086 }
khenaidoob9203542018-09-17 22:56:37 -04001087 var err error
npujar1d86a522019-11-14 17:11:16 +05301088 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(context.TODO(), cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001089 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1090 return err
1091 }
khenaidoob9203542018-09-17 22:56:37 -04001092 return nil
1093}
1094
npujar1d86a522019-11-14 17:11:16 +05301095// DeleteLogicalDevice deletes logical device from core
khenaidoo0a822f92019-05-08 15:15:57 -04001096func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
1097 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001098 var err error
npujar1d86a522019-11-14 17:11:16 +05301099 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(context.TODO(), cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001100 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1101 return err
1102 }
1103 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301104 logicalID := ""
1105 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001106 return nil
1107}
1108
npujar1d86a522019-11-14 17:11:16 +05301109// DeleteLogicalPort removes the logical port associated with a device
khenaidoo0a822f92019-05-08 15:15:57 -04001110func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001111 log.Info("deleteLogicalPort")
1112 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001113 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301114 var lPortID *voltha.LogicalPortId
1115 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001116 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001117 return err
1118 }
npujar1d86a522019-11-14 17:11:16 +05301119 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(context.TODO(), lPortID); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001120 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001121 return err
1122 }
khenaidoo92e62c52018-10-03 14:02:54 -04001123 return nil
1124}
1125
npujar1d86a522019-11-14 17:11:16 +05301126// DeleteLogicalPorts removes the logical ports associated with that deviceId
khenaidoo0a822f92019-05-08 15:15:57 -04001127func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1128 log.Info("deleteLogicalPorts")
1129 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1130 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1131 return err
1132 }
1133 return nil
1134}
1135
khenaidoo92e62c52018-10-03 14:02:54 -04001136func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1137 // Sanity check
1138 if childDevice.Root {
1139 // childDevice is the parent device
1140 return childDevice
1141 }
khenaidoo19d7b632018-10-30 10:49:50 -04001142 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001143 return parentDevice
1144}
1145
khenaidoo0a822f92019-05-08 15:15:57 -04001146//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1147//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar1d86a522019-11-14 17:11:16 +05301148func (dMgr *DeviceManager) childDevicesLost(parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001149 log.Debug("childDevicesLost")
1150 var err error
1151 var parentDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +05301152 if parentDevice, err = dMgr.GetDevice(parentDeviceID); err != nil {
1153 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001154 return err
1155 }
1156 return dMgr.DisableAllChildDevices(parentDevice)
1157}
1158
1159//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1160// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar1d86a522019-11-14 17:11:16 +05301161func (dMgr *DeviceManager) childDevicesDetected(parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001162 log.Debug("childDevicesDetected")
1163 var err error
1164 var parentDevice *voltha.Device
1165 var childDeviceIds []string
1166
npujar1d86a522019-11-14 17:11:16 +05301167 if parentDevice, err = dMgr.GetDevice(parentDeviceID); err != nil {
1168 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001169 return err
1170 }
1171
1172 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1173 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1174 }
1175 if len(childDeviceIds) == 0 {
1176 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1177 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001178 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301179 for _, childDeviceID := range childDeviceIds {
1180 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001181 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301182 go func() {
1183 err = agent.enableDevice(context.TODO())
1184 if err != nil {
1185 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1186 }
1187 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001188 } else {
npujar1d86a522019-11-14 17:11:16 +05301189 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
1190 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001191 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001192 }
1193 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001194 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001195 return err
1196 }
1197 return nil
1198}
1199
khenaidoo4d4802d2018-10-04 21:59:49 -04001200/*
1201All the functions below are callback functions where they are invoked with the latest and previous data. We can
1202therefore use the data as is without trying to get the latest from the model.
1203*/
1204
khenaidoo0a822f92019-05-08 15:15:57 -04001205//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1206func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1207 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001208 var childDeviceIds []string
1209 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001210 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1211 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001212 }
1213 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001214 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001215 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001216 allChildDisable := true
npujar1d86a522019-11-14 17:11:16 +05301217 for _, childDeviceID := range childDeviceIds {
1218 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
1219 if err = agent.disableDevice(context.TODO()); err != nil {
1220 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001221 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001222 }
1223 }
1224 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001225 if !allChildDisable {
1226 return err
1227 }
khenaidoo92e62c52018-10-03 14:02:54 -04001228 return nil
1229}
1230
khenaidoo0a822f92019-05-08 15:15:57 -04001231//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1232func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1233 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001234 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001235 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001236 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1237 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001238 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001239 if len(childDeviceIds) == 0 {
1240 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1241 }
1242 allChildDeleted := true
npujar1d86a522019-11-14 17:11:16 +05301243 for _, childDeviceID := range childDeviceIds {
1244 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
1245 if err = agent.deleteDevice(context.TODO()); err != nil {
1246 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001247 allChildDeleted = false
1248 } else {
npujar1d86a522019-11-14 17:11:16 +05301249 agent.stop(context.TODO())
khenaidoo4c9e5592019-09-09 16:20:41 -04001250 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo4d4802d2018-10-04 21:59:49 -04001251 }
1252 }
1253 }
1254 if !allChildDeleted {
1255 return err
1256 }
1257 return nil
1258}
1259
khenaidoo6d62c002019-05-15 21:57:03 -04001260//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1261// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1262// device during a delete device operation.
npujar1d86a522019-11-14 17:11:16 +05301263func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentID(id string) []string {
khenaidoo6d62c002019-05-15 21:57:03 -04001264 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1265 deviceIds := make([]string, 0)
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001266 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
1267 agent := value.(*DeviceAgent)
npujar1d86a522019-11-14 17:11:16 +05301268 if agent.parentID == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001269 deviceIds = append(deviceIds, key.(string))
khenaidoo6d62c002019-05-15 21:57:03 -04001270 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001271 return true
1272 })
khenaidoo6d62c002019-05-15 21:57:03 -04001273 return deviceIds
1274}
1275
khenaidoo4d4802d2018-10-04 21:59:49 -04001276//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1277func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1278 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001279 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001280 if parentDevice != nil {
1281 for _, port := range parentDevice.Ports {
1282 for _, peer := range port.Peers {
1283 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1284 }
khenaidoo92e62c52018-10-03 14:02:54 -04001285 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001286 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001287 }
1288 return childDeviceIds, nil
1289}
1290
khenaidoo297cd252019-02-07 22:10:23 -05001291//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar1d86a522019-11-14 17:11:16 +05301292func (dMgr *DeviceManager) getAllChildDevices(parentDeviceID string) (*voltha.Devices, error) {
1293 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
1294 if parentDevice, err := dMgr.GetDevice(parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001295 childDevices := make([]*voltha.Device, 0)
1296 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301297 for _, deviceID := range childDeviceIds {
1298 if d, e := dMgr.GetDevice(deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001299 childDevices = append(childDevices, d)
1300 }
1301 }
1302 }
1303 return &voltha.Devices{Items: childDevices}, nil
1304 }
npujar1d86a522019-11-14 17:11:16 +05301305 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001306}
1307
npujar1d86a522019-11-14 17:11:16 +05301308// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
khenaidoo0a822f92019-05-08 15:15:57 -04001309func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001310 log.Info("addUNILogicalPort")
npujar1d86a522019-11-14 17:11:16 +05301311 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(context.TODO(), cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001312 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1313 return err
1314 }
1315 return nil
1316}
1317
khenaidoof5a5bfa2019-01-23 22:20:29 -05001318func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1319 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1320 var res interface{}
1321 var err error
1322 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1323 if res, err = agent.downloadImage(ctx, img); err != nil {
1324 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1325 res = err
1326 }
1327 } else {
1328 res = status.Errorf(codes.NotFound, "%s", img.Id)
1329 }
1330 sendResponse(ctx, ch, res)
1331}
1332
1333func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1334 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1335 var res interface{}
1336 var err error
1337 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1338 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1339 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1340 res = err
1341 }
1342 } else {
1343 res = status.Errorf(codes.NotFound, "%s", img.Id)
1344 }
1345 sendResponse(ctx, ch, res)
1346}
1347
1348func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1349 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1350 var res interface{}
1351 var err error
1352 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1353 if res, err = agent.activateImage(ctx, img); err != nil {
1354 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1355 res = err
1356 }
1357 } else {
1358 res = status.Errorf(codes.NotFound, "%s", img.Id)
1359 }
1360 sendResponse(ctx, ch, res)
1361}
1362
1363func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1364 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1365 var res interface{}
1366 var err error
1367 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1368 if res, err = agent.revertImage(ctx, img); err != nil {
1369 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1370 res = err
1371 }
1372 } else {
1373 res = status.Errorf(codes.NotFound, "%s", img.Id)
1374 }
1375 sendResponse(ctx, ch, res)
1376}
1377
1378func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1379 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1380 var res interface{}
1381 var err error
1382 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1383 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1384 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1385 res = err
1386 }
1387 } else {
1388 res = status.Errorf(codes.NotFound, "%s", img.Id)
1389 }
1390 sendResponse(ctx, ch, res)
1391}
1392
npujar1d86a522019-11-14 17:11:16 +05301393func (dMgr *DeviceManager) updateImageDownload(deviceID string, img *voltha.ImageDownload) error {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001394 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar1d86a522019-11-14 17:11:16 +05301395 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001396 if err := agent.updateImageDownload(img); err != nil {
1397 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1398 return err
1399 }
1400 } else {
1401 return status.Errorf(codes.NotFound, "%s", img.Id)
1402 }
1403 return nil
1404}
1405
1406func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1407 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1408 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1409 return agent.getImageDownload(ctx, img)
1410 }
1411 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1412}
1413
npujar1d86a522019-11-14 17:11:16 +05301414func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
1415 log.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
1416 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
1417 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001418 }
npujar1d86a522019-11-14 17:11:16 +05301419 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001420}
1421
npujar1d86a522019-11-14 17:11:16 +05301422// SetAdminStateToEnable sets admin state of device to enabled
khenaidoo0a822f92019-05-08 15:15:57 -04001423func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1424 log.Info("SetAdminStateToEnable")
1425 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1426 return agent.updateAdminState(voltha.AdminState_ENABLED)
1427 }
1428 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1429}
1430
npujar1d86a522019-11-14 17:11:16 +05301431// NotifyInvalidTransition notifies about invalid transition
khenaidoo0a822f92019-05-08 15:15:57 -04001432func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001433 log.Errorw("NotifyInvalidTransition", log.Fields{
1434 "device": pcDevice.Id,
1435 "adminState": pcDevice.AdminState,
1436 "operState": pcDevice.OperStatus,
1437 "connState": pcDevice.ConnectStatus,
1438 })
khenaidoo0a822f92019-05-08 15:15:57 -04001439 //TODO: notify over kafka?
1440 return nil
1441}
1442
khenaidoob9203542018-09-17 22:56:37 -04001443func funcName(f interface{}) string {
1444 p := reflect.ValueOf(f).Pointer()
1445 rf := runtime.FuncForPC(p)
1446 return rf.Name()
1447}
1448
npujar1d86a522019-11-14 17:11:16 +05301449// UpdateDeviceAttribute updates value of particular device attribute
1450func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceID string, attribute string, value interface{}) {
1451 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001452 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001453 }
1454}
1455
npujar1d86a522019-11-14 17:11:16 +05301456// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
1457func (dMgr *DeviceManager) GetParentDeviceID(deviceID string) string {
1458 if device, _ := dMgr.GetDevice(deviceID); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001459 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001460 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001461 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001462 return ""
khenaidoob9203542018-09-17 22:56:37 -04001463}
serkant.uluderya334479d2019-04-10 08:26:15 -07001464
1465func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1466 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1467 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1468 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1469 var res interface{}
1470 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1471 res = agent.simulateAlarm(ctx, simulatereq)
1472 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1473 }
1474 //TODO CLI always get successful response
1475 sendResponse(ctx, ch, res)
1476}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001477
npujar1d86a522019-11-14 17:11:16 +05301478func (dMgr *DeviceManager) updateDeviceReason(deviceID string, reason string) error {
1479 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
1480 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001481 return agent.updateDeviceReason(reason)
1482 }
npujar1d86a522019-11-14 17:11:16 +05301483 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001484}