blob: a876bbee658c412f4a408d5e69e6d3cfe422f98e [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 {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500272 return agent.getDevice(), nil
khenaidoo92e62c52018-10-03 14:02:54 -0400273 }
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
khenaidoo6e55d9e2019-12-12 18:26:26 -0500538 device := dAgent.getDevice()
khenaidoo297cd252019-02-07 22:10:23 -0500539
540 // If the device is in Pre-provisioning or deleted state stop here
541 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
542 return nil
543 }
544
545 // Now we face two scenarios
546 if device.Root {
547 // Load all children as well as the parent of this device (logical_device)
548 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530549 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500550 return err
551 }
npujar1d86a522019-11-14 17:11:16 +0530552 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500553 } else {
554 // Scenario B - use the parentId of that device (root device) to trigger the loading
555 if device.ParentId != "" {
556 return dMgr.load(device.ParentId)
557 }
558 }
559 return nil
560}
561
khenaidoo7ccedd52018-12-14 16:48:54 -0500562// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
563func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
564 log.Debug("ListDeviceIDs")
565 // Report only device IDs that are in the device agent map
566 return dMgr.listDeviceIdsFromMap(), nil
567}
568
khenaidoo4c9e5592019-09-09 16:20:41 -0400569//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
570//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500571func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400572 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500573 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400574 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500575 toReconcile := len(ids.Items)
576 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400577 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500578 for _, id := range ids.Items {
khenaidoo4c9e5592019-09-09 16:20:41 -0400579 if err = dMgr.load(id.Id); err != nil {
580 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
581 } else {
npujar1d86a522019-11-14 17:11:16 +0530582 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500583 }
584 }
585 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400586 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500587 }
588 } else {
589 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
590 }
591 sendResponse(ctx, ch, res)
592}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500593
khenaidooba6b6c42019-08-02 09:11:56 -0400594// isOkToReconcile validates whether a device is in the correct status to be reconciled
595func isOkToReconcile(device *voltha.Device) bool {
596 if device == nil {
597 return false
598 }
599 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
600}
601
602// adapterRestarted is invoked whenever an adapter is restarted
603func (dMgr *DeviceManager) adapterRestarted(adapter *voltha.Adapter) error {
604 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
605
606 // Let's reconcile the device managed by this Core only
607 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
608 if len(rootDeviceIds) == 0 {
609 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
610 return nil
611 }
612
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500613 responses := make([]utils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530614 for _, rootDeviceID := range rootDeviceIds {
615 if rootDevice, _ := dMgr.getDeviceFromModel(rootDeviceID); rootDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400616 if rootDevice.Adapter == adapter.Id {
617 if isOkToReconcile(rootDevice) {
618 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500619 responses = append(responses, dMgr.sendReconcileDeviceRequest(rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400620 } else {
621 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
622 }
623 } else { // Should we be reconciling the root's children instead?
624 childManagedByAdapter:
625 for _, port := range rootDevice.Ports {
626 for _, peer := range port.Peers {
627 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
628 if childDevice.Adapter == adapter.Id {
629 if isOkToReconcile(childDevice) {
630 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500631 responses = append(responses, dMgr.sendReconcileDeviceRequest(childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400632 } else {
633 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
634 }
635 } else {
636 // All child devices under a parent device are typically managed by the same adapter type.
637 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
638 break childManagedByAdapter
639 }
640 }
641 }
642 }
643 }
644 }
645 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500646 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400647 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500648 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400649 return status.Errorf(codes.Aborted, "errors-%s", res)
650 }
651 } else {
652 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
653 }
654 return nil
655}
656
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500657func (dMgr *DeviceManager) sendReconcileDeviceRequest(device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400658 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
659 // 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 +0530660 // 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 -0400661 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500662 response := utils.NewResponse()
khenaidooba6b6c42019-08-02 09:11:56 -0400663 go func(device *voltha.Device) {
664 if err := dMgr.adapterProxy.ReconcileDevice(context.Background(), device); err != nil {
665 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500666 response.Error(status.Errorf(codes.Internal, "device: %s", device.Id))
khenaidooba6b6c42019-08-02 09:11:56 -0400667 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500668 response.Done()
khenaidooba6b6c42019-08-02 09:11:56 -0400669 }(device)
670
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500671 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400672}
673
npujar1d86a522019-11-14 17:11:16 +0530674func (dMgr *DeviceManager) reconcileChildDevices(parentDeviceID string) error {
675 if parentDevice, _ := dMgr.getDeviceFromModel(parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500676 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400677 for _, port := range parentDevice.Ports {
678 for _, peer := range port.Peers {
679 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500680 responses = append(responses, dMgr.sendReconcileDeviceRequest(childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400681 }
682 }
683 }
684 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500685 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400686 return status.Errorf(codes.Aborted, "errors-%s", res)
687 }
688 }
689 return nil
690}
691
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700692func (dMgr *DeviceManager) updateDeviceUsingAdapterData(device *voltha.Device) error {
693 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400694 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700695 return agent.updateDeviceUsingAdapterData(device)
khenaidoob9203542018-09-17 22:56:37 -0400696 }
697 return status.Errorf(codes.NotFound, "%s", device.Id)
698}
699
npujar1d86a522019-11-14 17:11:16 +0530700func (dMgr *DeviceManager) addPort(deviceID string, port *voltha.Port) error {
701 agent := dMgr.getDeviceAgent(deviceID)
702 if agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400703 if err := agent.addPort(port); err != nil {
704 return err
705 }
706 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530707 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400708 for _, peerPort := range port.Peers {
709 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
710 if err := agent.addPeerPort(meAsPeer); err != nil {
711 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
712 return err
713 }
714 }
715 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400716 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
717 // then a logical port will be added to the logical device and the device graph generated. If the port is a
718 // PON port then only the device graph will be generated.
npujar1d86a522019-11-14 17:11:16 +0530719 if device, err := dMgr.GetDevice(deviceID); err == nil {
720 go func() {
721 err = dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
722 if err != nil {
723 log.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
724 }
725 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400726 } else {
npujar1d86a522019-11-14 17:11:16 +0530727 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400728 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400729 }
khenaidoo92e62c52018-10-03 14:02:54 -0400730 return nil
khenaidoob9203542018-09-17 22:56:37 -0400731 }
npujar1d86a522019-11-14 17:11:16 +0530732 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400733}
734
npujar1d86a522019-11-14 17:11:16 +0530735func (dMgr *DeviceManager) deletePeerPorts(fromDeviceID string, deviceID string) error {
736 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceID, "deviceid": deviceID})
737 if agent := dMgr.getDeviceAgent(fromDeviceID); agent != nil {
738 return agent.deletePeerPorts(deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400739 }
npujar1d86a522019-11-14 17:11:16 +0530740 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400741}
742
npujar1d86a522019-11-14 17:11:16 +0530743func (dMgr *DeviceManager) addFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
744 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "flowMetadata": flowMetadata})
745 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400746 return agent.addFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400747 }
npujar1d86a522019-11-14 17:11:16 +0530748 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400749}
750
npujar1d86a522019-11-14 17:11:16 +0530751func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
752 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
753 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400754 return agent.deleteFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400755 }
npujar1d86a522019-11-14 17:11:16 +0530756 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400757}
758
npujar1d86a522019-11-14 17:11:16 +0530759func (dMgr *DeviceManager) updateFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
760 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
761 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400762 return agent.updateFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400763 }
npujar1d86a522019-11-14 17:11:16 +0530764 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400765}
766
khenaidoob3127472019-07-24 21:04:55 -0400767// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
768// following a user action
769func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
770 var res interface{}
771 if pmConfigs.Id == "" {
772 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
773 } else if agent := dMgr.getDeviceAgent(pmConfigs.Id); agent != nil {
774 res = agent.updatePmConfigs(ctx, pmConfigs)
775 } else {
776 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
777 }
778 sendResponse(ctx, ch, res)
779}
780
781// initPmConfigs initialize the pm configs as defined by the adapter.
npujar1d86a522019-11-14 17:11:16 +0530782func (dMgr *DeviceManager) initPmConfigs(deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400783 if pmConfigs.Id == "" {
784 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
785 }
npujar1d86a522019-11-14 17:11:16 +0530786 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400787 return agent.initPmConfigs(pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400788 }
npujar1d86a522019-11-14 17:11:16 +0530789 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400790}
791
npujar1d86a522019-11-14 17:11:16 +0530792func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
793 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400794 return agent.listPmConfigs(ctx)
795 }
npujar1d86a522019-11-14 17:11:16 +0530796 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400797}
798
npujar1d86a522019-11-14 17:11:16 +0530799func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
800 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
801 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400802 return agent.getSwitchCapability(ctx)
803 }
npujar1d86a522019-11-14 17:11:16 +0530804 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400805}
806
npujar1d86a522019-11-14 17:11:16 +0530807func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
808 log.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
809 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400810 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400811 }
npujar1d86a522019-11-14 17:11:16 +0530812 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400813}
814
npujar1d86a522019-11-14 17:11:16 +0530815func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
816 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
817 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400818 return agent.getPortCapability(ctx, portNo)
819 }
npujar1d86a522019-11-14 17:11:16 +0530820 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400821}
822
npujar1d86a522019-11-14 17:11:16 +0530823func (dMgr *DeviceManager) updateDeviceStatus(deviceID string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
824 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
825 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400826 return agent.updateDeviceStatus(operStatus, connStatus)
827 }
npujar1d86a522019-11-14 17:11:16 +0530828 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400829}
830
npujar1d86a522019-11-14 17:11:16 +0530831func (dMgr *DeviceManager) updateChildrenStatus(deviceID string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
832 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400833 var parentDevice *voltha.Device
834 var err error
npujar1d86a522019-11-14 17:11:16 +0530835 if parentDevice, err = dMgr.GetDevice(deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400836 return status.Errorf(codes.Aborted, "%s", err.Error())
837 }
838 var childDeviceIds []string
839 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
840 return status.Errorf(codes.Aborted, "%s", err.Error())
841 }
842 if len(childDeviceIds) == 0 {
843 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
844 }
npujar1d86a522019-11-14 17:11:16 +0530845 for _, childDeviceID := range childDeviceIds {
846 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400847 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530848 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400849 }
850 }
851 }
852 return nil
853}
854
npujar1d86a522019-11-14 17:11:16 +0530855func (dMgr *DeviceManager) updatePortState(deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
856 log.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
857 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo171b98e2019-10-31 11:48:15 -0400858 if err := agent.updatePortState(portType, portNo, operStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530859 log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400860 return err
861 }
862 // Notify the logical device manager to change the port state
npujar1d86a522019-11-14 17:11:16 +0530863 go func() {
864 err := dMgr.logicalDeviceMgr.updatePortState(deviceID, portNo, operStatus)
865 if err != nil {
866 log.Errorw("unable-to-update-port-state", log.Fields{"error": err})
867 }
868 }()
khenaidoob9203542018-09-17 22:56:37 -0400869 }
npujar1d86a522019-11-14 17:11:16 +0530870 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400871}
872
npujar1d86a522019-11-14 17:11:16 +0530873func (dMgr *DeviceManager) deleteAllPorts(deviceID string) error {
874 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
875 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400876 if err := agent.deleteAllPorts(); err != nil {
877 return err
878 }
879 // Notify the logical device manager to remove all logical ports, if needed.
880 // At this stage the device itself may gave been deleted already at a deleteAllPorts
881 // typically is part of a device deletion phase.
npujar1d86a522019-11-14 17:11:16 +0530882 if device, err := dMgr.GetDevice(deviceID); err == nil {
883 go func() {
884 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
885 if err != nil {
886 log.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
887 }
888 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400889 } else {
npujar1d86a522019-11-14 17:11:16 +0530890 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400891 return err
892 }
893 return nil
894 }
npujar1d86a522019-11-14 17:11:16 +0530895 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400896}
897
khenaidoo3ab34882019-05-02 21:33:30 -0400898//updatePortsState updates all ports on the device
npujar1d86a522019-11-14 17:11:16 +0530899func (dMgr *DeviceManager) updatePortsState(deviceID string, state voltha.OperStatus_OperStatus) error {
900 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400901
902 var adminState voltha.AdminState_AdminState
npujar1d86a522019-11-14 17:11:16 +0530903 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400904 switch state {
905 case voltha.OperStatus_ACTIVE:
906 adminState = voltha.AdminState_ENABLED
907 if err := agent.enablePorts(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530908 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400909 return err
910 }
911 case voltha.OperStatus_UNKNOWN:
912 adminState = voltha.AdminState_DISABLED
913 if err := agent.disablePorts(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530914 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400915 return err
916 }
917 default:
918 return status.Error(codes.Unimplemented, "state-change-not-implemented")
919 }
920 // Notify the logical device about the state change
npujar1d86a522019-11-14 17:11:16 +0530921 device, err := dMgr.GetDevice(deviceID)
922 if err != nil {
923 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400924 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400925 }
npujar1d86a522019-11-14 17:11:16 +0530926 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
927 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
928 return err
929 }
930 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400931 }
npujar1d86a522019-11-14 17:11:16 +0530932 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400933}
934
npujar1d86a522019-11-14 17:11:16 +0530935func (dMgr *DeviceManager) childDeviceDetected(parentDeviceID string, parentPortNo int64, deviceType string,
936 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
937 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 -0700938
npujar1d86a522019-11-14 17:11:16 +0530939 if deviceType == "" && vendorID != "" {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700940 log.Debug("device-type-is-nil-fetching-device-type")
941 if deviceTypesIf := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, ""); deviceTypesIf != nil {
942 OLoop:
943 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
944 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
945 for _, v := range dType.VendorIds {
npujar1d86a522019-11-14 17:11:16 +0530946 if v == vendorID {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700947 deviceType = dType.Adapter
948 break OLoop
949 }
950 }
951 }
952 }
953 }
954 }
955 //if no match found for the vendorid,report adapter with the custom error message
956 if deviceType == "" {
npujar1d86a522019-11-14 17:11:16 +0530957 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
958 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700959 }
khenaidoob9203542018-09-17 22:56:37 -0400960
961 // Create the ONU device
962 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400963 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530964 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400965 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530966 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500967 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400968 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400969
970 //Get parent device type
npujar1d86a522019-11-14 17:11:16 +0530971 parent, err := dMgr.GetDevice(parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400972 if err != nil {
npujar1d86a522019-11-14 17:11:16 +0530973 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceID})
974 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400975 }
976
npujar1d86a522019-11-14 17:11:16 +0530977 if device, err := dMgr.GetChildDevice(parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
978 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700979 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500980 }
981
npujar1d86a522019-11-14 17:11:16 +0530982 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: parent.Type, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -0400983
984 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400985 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400986 dMgr.addDeviceAgentToMap(agent)
npujar1d86a522019-11-14 17:11:16 +0530987 childDevice, err = agent.start(context.TODO(), childDevice)
Scott Baker80678602019-11-14 16:57:36 -0800988 if err != nil {
989 log.Error("error-starting-child")
990 return nil, err
991 }
khenaidoob9203542018-09-17 22:56:37 -0400992
khenaidoo09771ef2019-10-11 14:25:02 -0400993 // Since this Core has handled this request then it therefore owns this child device. Set the
994 // ownership of this device to this Core
npujar1d86a522019-11-14 17:11:16 +0530995 _, err = dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{ID: agent.deviceID})
996 if err != nil {
997 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
998 }
khenaidoo09771ef2019-10-11 14:25:02 -0400999
khenaidoob9203542018-09-17 22:56:37 -04001000 // Activate the child device
npujar1d86a522019-11-14 17:11:16 +05301001 if agent = dMgr.getDeviceAgent(agent.deviceID); agent != nil {
1002 go func() {
1003 err := agent.enableDevice(context.TODO())
1004 if err != nil {
1005 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1006 }
1007 }()
khenaidoob9203542018-09-17 22:56:37 -04001008 }
1009
khenaidoo79232702018-12-04 11:00:41 -05001010 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301011 go func() {
1012 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1013 if err != nil {
1014 log.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
1015 }
1016 }()
khenaidoo79232702018-12-04 11:00:41 -05001017
Scott Baker80678602019-11-14 16:57:36 -08001018 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001019}
1020
1021func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
1022 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -04001023 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
1024 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -05001025 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001026 return nil
khenaidoob9203542018-09-17 22:56:37 -04001027 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001028 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -04001029 for _, handler := range handlers {
1030 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
1031 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -04001032 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001033 return err
1034 }
1035 }
khenaidoob9203542018-09-17 22:56:37 -04001036 return nil
1037}
1038
npujar1d86a522019-11-14 17:11:16 +05301039func (dMgr *DeviceManager) packetOut(deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
1040 log.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
1041 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001042 return agent.packetOut(outPort, packet)
1043 }
npujar1d86a522019-11-14 17:11:16 +05301044 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001045}
1046
npujar1d86a522019-11-14 17:11:16 +05301047// PacketIn receives packet from adapter
1048func (dMgr *DeviceManager) PacketIn(deviceID string, port uint32, transactionID string, packet []byte) error {
1049 log.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001050 // Get the logical device Id based on the deviceId
1051 var device *voltha.Device
1052 var err error
npujar1d86a522019-11-14 17:11:16 +05301053 if device, err = dMgr.GetDevice(deviceID); err != nil {
1054 log.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001055 return err
1056 }
khenaidoo43c82122018-11-22 18:38:28 -05001057 if !device.Root {
npujar1d86a522019-11-14 17:11:16 +05301058 log.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
1059 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001060 }
1061
npujar1d86a522019-11-14 17:11:16 +05301062 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001063 return err
1064 }
1065 return nil
1066}
1067
npujar1d86a522019-11-14 17:11:16 +05301068func (dMgr *DeviceManager) setParentID(device *voltha.Device, parentID string) error {
1069 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
khenaidooad06fd72019-10-28 12:26:05 -04001070 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301071 return agent.setParentID(device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001072 }
1073 return status.Errorf(codes.NotFound, "%s", device.Id)
1074}
1075
npujar1d86a522019-11-14 17:11:16 +05301076// CreateLogicalDevice creates logical device in core
khenaidoo0a822f92019-05-08 15:15:57 -04001077func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
1078 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001079 // Verify whether the logical device has already been created
1080 if cDevice.ParentId != "" {
1081 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1082 return nil
1083 }
khenaidoob9203542018-09-17 22:56:37 -04001084 var err error
npujar1d86a522019-11-14 17:11:16 +05301085 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(context.TODO(), cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001086 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1087 return err
1088 }
khenaidoob9203542018-09-17 22:56:37 -04001089 return nil
1090}
1091
npujar1d86a522019-11-14 17:11:16 +05301092// DeleteLogicalDevice deletes logical device from core
khenaidoo0a822f92019-05-08 15:15:57 -04001093func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
1094 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001095 var err error
npujar1d86a522019-11-14 17:11:16 +05301096 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(context.TODO(), cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001097 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1098 return err
1099 }
1100 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301101 logicalID := ""
1102 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001103 return nil
1104}
1105
npujar1d86a522019-11-14 17:11:16 +05301106// DeleteLogicalPort removes the logical port associated with a device
khenaidoo0a822f92019-05-08 15:15:57 -04001107func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001108 log.Info("deleteLogicalPort")
1109 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001110 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301111 var lPortID *voltha.LogicalPortId
1112 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001113 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001114 return err
1115 }
npujar1d86a522019-11-14 17:11:16 +05301116 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(context.TODO(), lPortID); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001117 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001118 return err
1119 }
khenaidoo92e62c52018-10-03 14:02:54 -04001120 return nil
1121}
1122
npujar1d86a522019-11-14 17:11:16 +05301123// DeleteLogicalPorts removes the logical ports associated with that deviceId
khenaidoo0a822f92019-05-08 15:15:57 -04001124func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1125 log.Info("deleteLogicalPorts")
1126 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1127 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1128 return err
1129 }
1130 return nil
1131}
1132
khenaidoo92e62c52018-10-03 14:02:54 -04001133func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1134 // Sanity check
1135 if childDevice.Root {
1136 // childDevice is the parent device
1137 return childDevice
1138 }
khenaidoo19d7b632018-10-30 10:49:50 -04001139 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001140 return parentDevice
1141}
1142
khenaidoo0a822f92019-05-08 15:15:57 -04001143//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1144//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar1d86a522019-11-14 17:11:16 +05301145func (dMgr *DeviceManager) childDevicesLost(parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001146 log.Debug("childDevicesLost")
1147 var err error
1148 var parentDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +05301149 if parentDevice, err = dMgr.GetDevice(parentDeviceID); err != nil {
1150 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001151 return err
1152 }
1153 return dMgr.DisableAllChildDevices(parentDevice)
1154}
1155
1156//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1157// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar1d86a522019-11-14 17:11:16 +05301158func (dMgr *DeviceManager) childDevicesDetected(parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001159 log.Debug("childDevicesDetected")
1160 var err error
1161 var parentDevice *voltha.Device
1162 var childDeviceIds []string
1163
npujar1d86a522019-11-14 17:11:16 +05301164 if parentDevice, err = dMgr.GetDevice(parentDeviceID); err != nil {
1165 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001166 return err
1167 }
1168
1169 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1170 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1171 }
1172 if len(childDeviceIds) == 0 {
1173 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1174 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001175 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301176 for _, childDeviceID := range childDeviceIds {
1177 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001178 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301179 go func() {
1180 err = agent.enableDevice(context.TODO())
1181 if err != nil {
1182 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1183 }
1184 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001185 } else {
npujar1d86a522019-11-14 17:11:16 +05301186 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
1187 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001188 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001189 }
1190 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001191 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001192 return err
1193 }
1194 return nil
1195}
1196
khenaidoo4d4802d2018-10-04 21:59:49 -04001197/*
1198All the functions below are callback functions where they are invoked with the latest and previous data. We can
1199therefore use the data as is without trying to get the latest from the model.
1200*/
1201
khenaidoo0a822f92019-05-08 15:15:57 -04001202//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1203func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1204 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001205 var childDeviceIds []string
1206 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001207 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1208 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001209 }
1210 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001211 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001212 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001213 allChildDisable := true
npujar1d86a522019-11-14 17:11:16 +05301214 for _, childDeviceID := range childDeviceIds {
1215 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
1216 if err = agent.disableDevice(context.TODO()); err != nil {
1217 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001218 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001219 }
1220 }
1221 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001222 if !allChildDisable {
1223 return err
1224 }
khenaidoo92e62c52018-10-03 14:02:54 -04001225 return nil
1226}
1227
khenaidoo0a822f92019-05-08 15:15:57 -04001228//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1229func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1230 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001231 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001232 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001233 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1234 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001235 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001236 if len(childDeviceIds) == 0 {
1237 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1238 }
1239 allChildDeleted := true
npujar1d86a522019-11-14 17:11:16 +05301240 for _, childDeviceID := range childDeviceIds {
1241 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
1242 if err = agent.deleteDevice(context.TODO()); err != nil {
1243 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001244 allChildDeleted = false
1245 } else {
npujar1d86a522019-11-14 17:11:16 +05301246 agent.stop(context.TODO())
khenaidoo4c9e5592019-09-09 16:20:41 -04001247 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo4d4802d2018-10-04 21:59:49 -04001248 }
1249 }
1250 }
1251 if !allChildDeleted {
1252 return err
1253 }
1254 return nil
1255}
1256
khenaidoo6d62c002019-05-15 21:57:03 -04001257//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1258// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1259// device during a delete device operation.
npujar1d86a522019-11-14 17:11:16 +05301260func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentID(id string) []string {
khenaidoo6d62c002019-05-15 21:57:03 -04001261 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1262 deviceIds := make([]string, 0)
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001263 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
1264 agent := value.(*DeviceAgent)
npujar1d86a522019-11-14 17:11:16 +05301265 if agent.parentID == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001266 deviceIds = append(deviceIds, key.(string))
khenaidoo6d62c002019-05-15 21:57:03 -04001267 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001268 return true
1269 })
khenaidoo6d62c002019-05-15 21:57:03 -04001270 return deviceIds
1271}
1272
khenaidoo4d4802d2018-10-04 21:59:49 -04001273//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1274func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1275 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001276 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001277 if parentDevice != nil {
1278 for _, port := range parentDevice.Ports {
1279 for _, peer := range port.Peers {
1280 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1281 }
khenaidoo92e62c52018-10-03 14:02:54 -04001282 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001283 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001284 }
1285 return childDeviceIds, nil
1286}
1287
khenaidoo297cd252019-02-07 22:10:23 -05001288//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar1d86a522019-11-14 17:11:16 +05301289func (dMgr *DeviceManager) getAllChildDevices(parentDeviceID string) (*voltha.Devices, error) {
1290 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
1291 if parentDevice, err := dMgr.GetDevice(parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001292 childDevices := make([]*voltha.Device, 0)
1293 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301294 for _, deviceID := range childDeviceIds {
1295 if d, e := dMgr.GetDevice(deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001296 childDevices = append(childDevices, d)
1297 }
1298 }
1299 }
1300 return &voltha.Devices{Items: childDevices}, nil
1301 }
npujar1d86a522019-11-14 17:11:16 +05301302 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001303}
1304
npujar1d86a522019-11-14 17:11:16 +05301305// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
khenaidoo0a822f92019-05-08 15:15:57 -04001306func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001307 log.Info("addUNILogicalPort")
npujar1d86a522019-11-14 17:11:16 +05301308 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(context.TODO(), cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001309 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1310 return err
1311 }
1312 return nil
1313}
1314
khenaidoof5a5bfa2019-01-23 22:20:29 -05001315func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1316 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1317 var res interface{}
1318 var err error
1319 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1320 if res, err = agent.downloadImage(ctx, img); err != nil {
1321 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1322 res = err
1323 }
1324 } else {
1325 res = status.Errorf(codes.NotFound, "%s", img.Id)
1326 }
1327 sendResponse(ctx, ch, res)
1328}
1329
1330func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1331 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1332 var res interface{}
1333 var err error
1334 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1335 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1336 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1337 res = err
1338 }
1339 } else {
1340 res = status.Errorf(codes.NotFound, "%s", img.Id)
1341 }
1342 sendResponse(ctx, ch, res)
1343}
1344
1345func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1346 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1347 var res interface{}
1348 var err error
1349 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1350 if res, err = agent.activateImage(ctx, img); err != nil {
1351 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1352 res = err
1353 }
1354 } else {
1355 res = status.Errorf(codes.NotFound, "%s", img.Id)
1356 }
1357 sendResponse(ctx, ch, res)
1358}
1359
1360func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1361 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1362 var res interface{}
1363 var err error
1364 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1365 if res, err = agent.revertImage(ctx, img); err != nil {
1366 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1367 res = err
1368 }
1369 } else {
1370 res = status.Errorf(codes.NotFound, "%s", img.Id)
1371 }
1372 sendResponse(ctx, ch, res)
1373}
1374
1375func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1376 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1377 var res interface{}
1378 var err error
1379 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1380 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1381 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1382 res = err
1383 }
1384 } else {
1385 res = status.Errorf(codes.NotFound, "%s", img.Id)
1386 }
1387 sendResponse(ctx, ch, res)
1388}
1389
npujar1d86a522019-11-14 17:11:16 +05301390func (dMgr *DeviceManager) updateImageDownload(deviceID string, img *voltha.ImageDownload) error {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001391 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar1d86a522019-11-14 17:11:16 +05301392 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001393 if err := agent.updateImageDownload(img); err != nil {
1394 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1395 return err
1396 }
1397 } else {
1398 return status.Errorf(codes.NotFound, "%s", img.Id)
1399 }
1400 return nil
1401}
1402
1403func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1404 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1405 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1406 return agent.getImageDownload(ctx, img)
1407 }
1408 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1409}
1410
npujar1d86a522019-11-14 17:11:16 +05301411func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
1412 log.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
1413 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
1414 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001415 }
npujar1d86a522019-11-14 17:11:16 +05301416 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001417}
1418
npujar1d86a522019-11-14 17:11:16 +05301419// SetAdminStateToEnable sets admin state of device to enabled
khenaidoo0a822f92019-05-08 15:15:57 -04001420func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1421 log.Info("SetAdminStateToEnable")
1422 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1423 return agent.updateAdminState(voltha.AdminState_ENABLED)
1424 }
1425 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1426}
1427
npujar1d86a522019-11-14 17:11:16 +05301428// NotifyInvalidTransition notifies about invalid transition
khenaidoo0a822f92019-05-08 15:15:57 -04001429func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001430 log.Errorw("NotifyInvalidTransition", log.Fields{
1431 "device": pcDevice.Id,
1432 "adminState": pcDevice.AdminState,
1433 "operState": pcDevice.OperStatus,
1434 "connState": pcDevice.ConnectStatus,
1435 })
khenaidoo0a822f92019-05-08 15:15:57 -04001436 //TODO: notify over kafka?
1437 return nil
1438}
1439
khenaidoob9203542018-09-17 22:56:37 -04001440func funcName(f interface{}) string {
1441 p := reflect.ValueOf(f).Pointer()
1442 rf := runtime.FuncForPC(p)
1443 return rf.Name()
1444}
1445
npujar1d86a522019-11-14 17:11:16 +05301446// UpdateDeviceAttribute updates value of particular device attribute
1447func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceID string, attribute string, value interface{}) {
1448 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001449 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001450 }
1451}
1452
npujar1d86a522019-11-14 17:11:16 +05301453// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
1454func (dMgr *DeviceManager) GetParentDeviceID(deviceID string) string {
1455 if device, _ := dMgr.GetDevice(deviceID); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001456 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001457 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001458 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001459 return ""
khenaidoob9203542018-09-17 22:56:37 -04001460}
serkant.uluderya334479d2019-04-10 08:26:15 -07001461
1462func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1463 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1464 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1465 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1466 var res interface{}
1467 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1468 res = agent.simulateAlarm(ctx, simulatereq)
1469 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1470 }
1471 //TODO CLI always get successful response
1472 sendResponse(ctx, ch, res)
1473}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001474
npujar1d86a522019-11-14 17:11:16 +05301475func (dMgr *DeviceManager) updateDeviceReason(deviceID string, reason string) error {
1476 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
1477 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001478 return agent.updateDeviceReason(reason)
1479 }
npujar1d86a522019-11-14 17:11:16 +05301480 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001481}