blob: 59cf0a478ee42fab10cdb1507f8fbbe89398271d [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 Se5a44012019-11-07 20:32:24 +0530158 deviceExist, err := dMgr.isParentDeviceExist(device)
159 if err != nil {
160 log.Errorf("Failed to fetch parent device info")
161 sendResponse(ctx, ch, err)
162 return
163 }
164 if deviceExist {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530165 log.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
166 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
167 return
168 }
khenaidoo92e62c52018-10-03 14:02:54 -0400169 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400170
khenaidoo5e677ae2019-02-28 17:26:29 -0500171 // Ensure this device is set as root
172 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400173 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400174 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400175 dMgr.addDeviceAgentToMap(agent)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530176 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800177 if err != nil {
178 log.Errorf("Failed to start device")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530179 sendResponse(ctx, ch, err)
Scott Baker80678602019-11-14 16:57:36 -0800180 return
181 }
khenaidoob9203542018-09-17 22:56:37 -0400182
Scott Baker80678602019-11-14 16:57:36 -0800183 sendResponse(ctx, ch, device)
khenaidoob9203542018-09-17 22:56:37 -0400184}
185
186func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400187 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400188 var res interface{}
189 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
190 res = agent.enableDevice(ctx)
191 log.Debugw("EnableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400192 }
193
194 sendResponse(ctx, ch, res)
195}
196
khenaidoo92e62c52018-10-03 14:02:54 -0400197func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
198 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400199 var res interface{}
200 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
201 res = agent.disableDevice(ctx)
202 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400203 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400204 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400205 }
khenaidoo92e62c52018-10-03 14:02:54 -0400206
207 sendResponse(ctx, ch, res)
208}
209
khenaidoo4d4802d2018-10-04 21:59:49 -0400210func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
211 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
212 var res interface{}
213 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
214 res = agent.rebootDevice(ctx)
215 log.Debugw("rebootDevice-result", log.Fields{"result": res})
216 } else {
217 res = status.Errorf(codes.NotFound, "%s", id.Id)
218 }
219 sendResponse(ctx, ch, res)
220}
221
222func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
223 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
224 var res interface{}
225 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
226 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400227 log.Debugw("deleteDevice-result", log.Fields{"result": res})
228 } else {
229 res = status.Errorf(codes.NotFound, "%s", id.Id)
230 }
231 sendResponse(ctx, ch, res)
232}
233
khenaidoo6d62c002019-05-15 21:57:03 -0400234// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
235// This function is called only in the Core that does not own this device. In the Core that owns this device then a
236// deletion deletion also includes removal of any reference of this device.
237func (dMgr *DeviceManager) stopManagingDevice(id string) {
238 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
239 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530240 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400241 // stop managing the logical device
npujar1d86a522019-11-14 17:11:16 +0530242 ldeviceID := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(id)
243 if ldeviceID != "" { // Can happen if logical device agent was already stopped
244 err := dMgr.core.deviceOwnership.AbandonDevice(ldeviceID)
245 if err != nil {
246 log.Errorw("unable-to-abandon-the-device", log.Fields{"error": err})
247 }
khenaidoo6d62c002019-05-15 21:57:03 -0400248 }
khenaidoo49085352020-01-13 19:15:43 -0500249 // We do not need to stop the child devices as this is taken care by the state machine.
khenaidoo6d62c002019-05-15 21:57:03 -0400250 }
251 if agent := dMgr.getDeviceAgent(id); agent != nil {
npujar1d86a522019-11-14 17:11:16 +0530252 agent.stop(context.TODO())
khenaidoo4c9e5592019-09-09 16:20:41 -0400253 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400254 // Abandon the device ownership
npujar1d86a522019-11-14 17:11:16 +0530255 err := dMgr.core.deviceOwnership.AbandonDevice(id)
256 if err != nil {
257 log.Errorw("unable-to-abandon-device", log.Fields{"error": err})
258 }
khenaidoo6d62c002019-05-15 21:57:03 -0400259 }
260 }
261}
262
npujar1d86a522019-11-14 17:11:16 +0530263// RunPostDeviceDelete removes any reference of this device
khenaidoo0a822f92019-05-08 15:15:57 -0400264func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
265 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400266 dMgr.stopManagingDevice(cDevice.Id)
267 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400268}
269
khenaidoo297cd252019-02-07 22:10:23 -0500270// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400271func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
272 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400273 if agent := dMgr.getDeviceAgent(id); agent != nil {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500274 return agent.getDevice(), nil
khenaidoo92e62c52018-10-03 14:02:54 -0400275 }
276 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400277}
278
npujar1d86a522019-11-14 17:11:16 +0530279// GetChildDevice will return a device, either from memory or from the dB, if present
280func (dMgr *DeviceManager) GetChildDevice(parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
281 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
282 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500283
284 var parentDevice *voltha.Device
285 var err error
npujar1d86a522019-11-14 17:11:16 +0530286 if parentDevice, err = dMgr.GetDevice(parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500287 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
288 }
289 var childDeviceIds []string
290 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
291 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
292 }
293 if len(childDeviceIds) == 0 {
npujar1d86a522019-11-14 17:11:16 +0530294 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
295 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500296 }
297
298 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530299 for _, childDeviceID := range childDeviceIds {
300 var found bool
301 if searchDevice, err := dMgr.GetDevice(childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500302
npujar1d86a522019-11-14 17:11:16 +0530303 foundOnuID := false
304 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500305 if searchDevice.ParentPortNo == uint32(parentPortNo) {
npujar1d86a522019-11-14 17:11:16 +0530306 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
307 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500308 }
309 }
310
311 foundSerialNumber := false
312 if searchDevice.SerialNumber == serialNumber {
313 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
314 foundSerialNumber = true
315 }
316
317 // if both onuId and serialNumber are provided both must be true for the device to be found
318 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530319 if onuID > 0 && serialNumber != "" {
320 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500321 } else {
npujar1d86a522019-11-14 17:11:16 +0530322 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500323 }
324
npujar1d86a522019-11-14 17:11:16 +0530325 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500326 foundChildDevice = searchDevice
327 break
328 }
329 }
330 }
331
332 if foundChildDevice != nil {
333 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
334 return foundChildDevice, nil
335 }
336
337 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530338 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
339 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500340}
341
npujar1d86a522019-11-14 17:11:16 +0530342// GetChildDeviceWithProxyAddress will return a device based on proxy address
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500343func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
344 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
345
346 var parentDevice *voltha.Device
347 var err error
348 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
349 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
350 }
351 var childDeviceIds []string
352 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
353 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
354 }
355 if len(childDeviceIds) == 0 {
356 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
357 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
358 }
359
360 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530361 for _, childDeviceID := range childDeviceIds {
362 if searchDevice, err := dMgr.GetDevice(childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500363 if searchDevice.ProxyAddress == proxyAddress {
364 foundChildDevice = searchDevice
365 break
366 }
367 }
368 }
369
370 if foundChildDevice != nil {
371 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
372 return foundChildDevice, nil
373 }
374
375 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
376 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
377}
378
npujar1d86a522019-11-14 17:11:16 +0530379// IsDeviceInCache returns true if device is found in the map
khenaidoo297cd252019-02-07 22:10:23 -0500380func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400381 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500382 return exist
383}
384
npujar1d86a522019-11-14 17:11:16 +0530385// IsRootDevice returns true if root device is found in the map
khenaidoo19d7b632018-10-30 10:49:50 -0400386func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400387 dMgr.lockRootDeviceMap.RLock()
388 defer dMgr.lockRootDeviceMap.RUnlock()
389 if exist := dMgr.rootDevices[id]; exist {
390 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400391 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400392 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400393}
394
Stephane Barbarieaa467942019-02-06 14:09:44 -0500395// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400396func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400397 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400398 result := &voltha.Devices{}
Thomas Lee Se5a44012019-11-07 20:32:24 +0530399 devices, err := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, "")
400 if err != nil {
401 log.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
402 return nil, err
403 }
404 if devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500405 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500406 // If device is not in memory then set it up
407 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400408 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400409 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar1d86a522019-11-14 17:11:16 +0530410 if _, err := agent.start(context.TODO(), nil); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500411 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
npujar1d86a522019-11-14 17:11:16 +0530412 agent.stop(context.TODO())
khenaidoo297cd252019-02-07 22:10:23 -0500413 } else {
414 dMgr.addDeviceAgentToMap(agent)
415 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500416 }
417 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400418 }
419 }
khenaidoo6d62c002019-05-15 21:57:03 -0400420 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400421 return result, nil
422}
423
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530424//isParentDeviceExist checks whether device is already preprovisioned.
Thomas Lee Se5a44012019-11-07 20:32:24 +0530425func (dMgr *DeviceManager) isParentDeviceExist(newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530426 hostPort := newDevice.GetHostAndPort()
Thomas Lee Se5a44012019-11-07 20:32:24 +0530427 devices, err := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, "")
428 if err != nil {
429 log.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
430 return false, err
431 }
432 if devices != nil {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530433 for _, device := range devices.([]interface{}) {
434 if !device.(*voltha.Device).Root {
435 continue
436 }
437 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530438 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530439 }
440 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530441 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530442 }
443 }
444 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530445 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530446}
447
khenaidoo6d62c002019-05-15 21:57:03 -0400448//getDeviceFromModelretrieves the device data from the model.
npujar1d86a522019-11-14 17:11:16 +0530449func (dMgr *DeviceManager) getDeviceFromModel(deviceID string) (*voltha.Device, error) {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530450 device, err := dMgr.clusterDataProxy.Get(context.Background(), "/devices/"+deviceID, 0, false, "")
451 if err != nil {
452 log.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
453 return nil, err
454 }
455 if device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400456 if d, ok := device.(*voltha.Device); ok {
457 return d, nil
458 }
459 }
npujar1d86a522019-11-14 17:11:16 +0530460 return nil, status.Error(codes.NotFound, deviceID)
khenaidoo6d62c002019-05-15 21:57:03 -0400461}
462
npujar1d86a522019-11-14 17:11:16 +0530463// loadDevice loads the deviceID in memory, if not present
464func (dMgr *DeviceManager) loadDevice(deviceID string) (*DeviceAgent, error) {
465 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500466 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
467 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400468 var err error
469 var device *voltha.Device
470 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530471 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
472 if !dMgr.IsDeviceInCache(deviceID) {
473 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400474 dMgr.devicesLoadingLock.Unlock()
475 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar1d86a522019-11-14 17:11:16 +0530476 if device, err = dMgr.getDeviceFromModel(deviceID); err == nil {
477 log.Debugw("loading-device", log.Fields{"deviceId": deviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400478 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar1d86a522019-11-14 17:11:16 +0530479 if _, err = agent.start(context.TODO(), nil); err != nil {
480 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
481 agent.stop(context.TODO())
khenaidoo4c9e5592019-09-09 16:20:41 -0400482 } else {
483 dMgr.addDeviceAgentToMap(agent)
484 }
485 } else {
npujar1d86a522019-11-14 17:11:16 +0530486 log.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400487 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400488 // announce completion of task to any number of waiting channels
489 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530490 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400491 for _, ch := range v {
492 close(ch)
493 }
npujar1d86a522019-11-14 17:11:16 +0530494 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400495 }
496 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400497 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400498 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500499 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400500 } else {
501 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530502 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400503 dMgr.devicesLoadingLock.Unlock()
504 // Wait for the channel to be closed, implying the process loading this device is done.
505 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500506 }
npujar1d86a522019-11-14 17:11:16 +0530507 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400508 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500509 }
npujar1d86a522019-11-14 17:11:16 +0530510 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500511}
512
513// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
514func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
515 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
516 if device.Root {
517 // Scenario A
518 if device.ParentId != "" {
519 // Load logical device if needed.
520 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
521 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
522 }
523 } else {
524 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
525 }
526 // Load all child devices, if needed
527 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530528 for _, childDeviceID := range childDeviceIds {
529 if _, err := dMgr.loadDevice(childDeviceID); err != nil {
530 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500531 return err
532 }
533 }
534 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
535 } else {
536 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
537 }
538 }
539 return nil
540}
541
542// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
543// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
544// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
545// and the proceed with the request.
npujar1d86a522019-11-14 17:11:16 +0530546func (dMgr *DeviceManager) load(deviceID string) error {
khenaidoo297cd252019-02-07 22:10:23 -0500547 log.Debug("load...")
548 // First load the device - this may fail in case the device was deleted intentionally by the other core
549 var dAgent *DeviceAgent
550 var err error
npujar1d86a522019-11-14 17:11:16 +0530551 if dAgent, err = dMgr.loadDevice(deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500552 return err
553 }
554 // Get the loaded device details
khenaidoo6e55d9e2019-12-12 18:26:26 -0500555 device := dAgent.getDevice()
khenaidoo297cd252019-02-07 22:10:23 -0500556
557 // If the device is in Pre-provisioning or deleted state stop here
558 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
559 return nil
560 }
561
562 // Now we face two scenarios
563 if device.Root {
564 // Load all children as well as the parent of this device (logical_device)
565 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530566 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500567 return err
568 }
npujar1d86a522019-11-14 17:11:16 +0530569 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500570 } else {
571 // Scenario B - use the parentId of that device (root device) to trigger the loading
572 if device.ParentId != "" {
573 return dMgr.load(device.ParentId)
574 }
575 }
576 return nil
577}
578
khenaidoo7ccedd52018-12-14 16:48:54 -0500579// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
580func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
581 log.Debug("ListDeviceIDs")
582 // Report only device IDs that are in the device agent map
583 return dMgr.listDeviceIdsFromMap(), nil
584}
585
khenaidoo4c9e5592019-09-09 16:20:41 -0400586//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
587//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500588func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400589 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500590 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400591 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500592 toReconcile := len(ids.Items)
593 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400594 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500595 for _, id := range ids.Items {
khenaidoo4c9e5592019-09-09 16:20:41 -0400596 if err = dMgr.load(id.Id); err != nil {
597 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
598 } else {
npujar1d86a522019-11-14 17:11:16 +0530599 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500600 }
601 }
602 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400603 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500604 }
605 } else {
606 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
607 }
608 sendResponse(ctx, ch, res)
609}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500610
khenaidooba6b6c42019-08-02 09:11:56 -0400611// isOkToReconcile validates whether a device is in the correct status to be reconciled
612func isOkToReconcile(device *voltha.Device) bool {
613 if device == nil {
614 return false
615 }
616 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
617}
618
619// adapterRestarted is invoked whenever an adapter is restarted
620func (dMgr *DeviceManager) adapterRestarted(adapter *voltha.Adapter) error {
621 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
622
623 // Let's reconcile the device managed by this Core only
624 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
625 if len(rootDeviceIds) == 0 {
626 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
627 return nil
628 }
629
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500630 responses := make([]utils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530631 for _, rootDeviceID := range rootDeviceIds {
632 if rootDevice, _ := dMgr.getDeviceFromModel(rootDeviceID); rootDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400633 if rootDevice.Adapter == adapter.Id {
634 if isOkToReconcile(rootDevice) {
635 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500636 responses = append(responses, dMgr.sendReconcileDeviceRequest(rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400637 } else {
638 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
639 }
640 } else { // Should we be reconciling the root's children instead?
641 childManagedByAdapter:
642 for _, port := range rootDevice.Ports {
643 for _, peer := range port.Peers {
644 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
645 if childDevice.Adapter == adapter.Id {
646 if isOkToReconcile(childDevice) {
647 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500648 responses = append(responses, dMgr.sendReconcileDeviceRequest(childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400649 } else {
650 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
651 }
652 } else {
653 // All child devices under a parent device are typically managed by the same adapter type.
654 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
655 break childManagedByAdapter
656 }
657 }
658 }
659 }
660 }
661 }
662 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500663 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400664 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500665 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400666 return status.Errorf(codes.Aborted, "errors-%s", res)
667 }
668 } else {
669 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
670 }
671 return nil
672}
673
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500674func (dMgr *DeviceManager) sendReconcileDeviceRequest(device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400675 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
676 // 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 +0530677 // 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 -0400678 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500679 response := utils.NewResponse()
khenaidooba6b6c42019-08-02 09:11:56 -0400680 go func(device *voltha.Device) {
681 if err := dMgr.adapterProxy.ReconcileDevice(context.Background(), device); err != nil {
682 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500683 response.Error(status.Errorf(codes.Internal, "device: %s", device.Id))
khenaidooba6b6c42019-08-02 09:11:56 -0400684 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500685 response.Done()
khenaidooba6b6c42019-08-02 09:11:56 -0400686 }(device)
687
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500688 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400689}
690
npujar1d86a522019-11-14 17:11:16 +0530691func (dMgr *DeviceManager) reconcileChildDevices(parentDeviceID string) error {
692 if parentDevice, _ := dMgr.getDeviceFromModel(parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500693 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400694 for _, port := range parentDevice.Ports {
695 for _, peer := range port.Peers {
696 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500697 responses = append(responses, dMgr.sendReconcileDeviceRequest(childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400698 }
699 }
700 }
701 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500702 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400703 return status.Errorf(codes.Aborted, "errors-%s", res)
704 }
705 }
706 return nil
707}
708
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700709func (dMgr *DeviceManager) updateDeviceUsingAdapterData(device *voltha.Device) error {
710 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400711 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700712 return agent.updateDeviceUsingAdapterData(device)
khenaidoob9203542018-09-17 22:56:37 -0400713 }
714 return status.Errorf(codes.NotFound, "%s", device.Id)
715}
716
npujar1d86a522019-11-14 17:11:16 +0530717func (dMgr *DeviceManager) addPort(deviceID string, port *voltha.Port) error {
718 agent := dMgr.getDeviceAgent(deviceID)
719 if agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400720 if err := agent.addPort(port); err != nil {
721 return err
722 }
723 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530724 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400725 for _, peerPort := range port.Peers {
726 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
727 if err := agent.addPeerPort(meAsPeer); err != nil {
728 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
729 return err
730 }
731 }
732 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400733 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
734 // then a logical port will be added to the logical device and the device graph generated. If the port is a
735 // PON port then only the device graph will be generated.
npujar1d86a522019-11-14 17:11:16 +0530736 if device, err := dMgr.GetDevice(deviceID); err == nil {
737 go func() {
738 err = dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
739 if err != nil {
740 log.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
741 }
742 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400743 } else {
npujar1d86a522019-11-14 17:11:16 +0530744 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400745 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400746 }
khenaidoo92e62c52018-10-03 14:02:54 -0400747 return nil
khenaidoob9203542018-09-17 22:56:37 -0400748 }
npujar1d86a522019-11-14 17:11:16 +0530749 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400750}
751
npujar1d86a522019-11-14 17:11:16 +0530752func (dMgr *DeviceManager) deletePeerPorts(fromDeviceID string, deviceID string) error {
753 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceID, "deviceid": deviceID})
754 if agent := dMgr.getDeviceAgent(fromDeviceID); agent != nil {
755 return agent.deletePeerPorts(deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400756 }
npujar1d86a522019-11-14 17:11:16 +0530757 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400758}
759
npujar1d86a522019-11-14 17:11:16 +0530760func (dMgr *DeviceManager) addFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Esin Karaman09959ae2019-11-29 13:59:58 +0000761 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar1d86a522019-11-14 17:11:16 +0530762 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400763 return agent.addFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400764 }
npujar1d86a522019-11-14 17:11:16 +0530765 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400766}
767
npujar1d86a522019-11-14 17:11:16 +0530768func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
769 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
770 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400771 return agent.deleteFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400772 }
npujar1d86a522019-11-14 17:11:16 +0530773 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400774}
775
npujar1d86a522019-11-14 17:11:16 +0530776func (dMgr *DeviceManager) updateFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
777 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
778 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400779 return agent.updateFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400780 }
npujar1d86a522019-11-14 17:11:16 +0530781 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400782}
783
khenaidoob3127472019-07-24 21:04:55 -0400784// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
785// following a user action
786func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
787 var res interface{}
788 if pmConfigs.Id == "" {
789 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
790 } else if agent := dMgr.getDeviceAgent(pmConfigs.Id); agent != nil {
791 res = agent.updatePmConfigs(ctx, pmConfigs)
792 } else {
793 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
794 }
795 sendResponse(ctx, ch, res)
796}
797
798// initPmConfigs initialize the pm configs as defined by the adapter.
npujar1d86a522019-11-14 17:11:16 +0530799func (dMgr *DeviceManager) initPmConfigs(deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400800 if pmConfigs.Id == "" {
801 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
802 }
npujar1d86a522019-11-14 17:11:16 +0530803 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400804 return agent.initPmConfigs(pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400805 }
npujar1d86a522019-11-14 17:11:16 +0530806 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400807}
808
npujar1d86a522019-11-14 17:11:16 +0530809func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
810 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400811 return agent.listPmConfigs(ctx)
812 }
npujar1d86a522019-11-14 17:11:16 +0530813 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400814}
815
npujar1d86a522019-11-14 17:11:16 +0530816func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
817 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
818 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400819 return agent.getSwitchCapability(ctx)
820 }
npujar1d86a522019-11-14 17:11:16 +0530821 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400822}
823
npujar1d86a522019-11-14 17:11:16 +0530824func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
825 log.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
826 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400827 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400828 }
npujar1d86a522019-11-14 17:11:16 +0530829 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400830}
831
npujar1d86a522019-11-14 17:11:16 +0530832func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
833 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
834 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400835 return agent.getPortCapability(ctx, portNo)
836 }
npujar1d86a522019-11-14 17:11:16 +0530837 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400838}
839
npujar1d86a522019-11-14 17:11:16 +0530840func (dMgr *DeviceManager) updateDeviceStatus(deviceID string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
841 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
842 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400843 return agent.updateDeviceStatus(operStatus, connStatus)
844 }
npujar1d86a522019-11-14 17:11:16 +0530845 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400846}
847
npujar1d86a522019-11-14 17:11:16 +0530848func (dMgr *DeviceManager) updateChildrenStatus(deviceID string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
849 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400850 var parentDevice *voltha.Device
851 var err error
npujar1d86a522019-11-14 17:11:16 +0530852 if parentDevice, err = dMgr.GetDevice(deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400853 return status.Errorf(codes.Aborted, "%s", err.Error())
854 }
855 var childDeviceIds []string
856 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
857 return status.Errorf(codes.Aborted, "%s", err.Error())
858 }
859 if len(childDeviceIds) == 0 {
860 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
861 }
npujar1d86a522019-11-14 17:11:16 +0530862 for _, childDeviceID := range childDeviceIds {
863 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400864 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530865 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400866 }
867 }
868 }
869 return nil
870}
871
npujar1d86a522019-11-14 17:11:16 +0530872func (dMgr *DeviceManager) updatePortState(deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
873 log.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
874 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo171b98e2019-10-31 11:48:15 -0400875 if err := agent.updatePortState(portType, portNo, operStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530876 log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400877 return err
878 }
879 // Notify the logical device manager to change the port state
npujar1d86a522019-11-14 17:11:16 +0530880 go func() {
881 err := dMgr.logicalDeviceMgr.updatePortState(deviceID, portNo, operStatus)
882 if err != nil {
883 log.Errorw("unable-to-update-port-state", log.Fields{"error": err})
884 }
885 }()
khenaidoob9203542018-09-17 22:56:37 -0400886 }
npujar1d86a522019-11-14 17:11:16 +0530887 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400888}
889
npujar1d86a522019-11-14 17:11:16 +0530890func (dMgr *DeviceManager) deleteAllPorts(deviceID string) error {
891 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
892 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400893 if err := agent.deleteAllPorts(); err != nil {
894 return err
895 }
896 // Notify the logical device manager to remove all logical ports, if needed.
897 // At this stage the device itself may gave been deleted already at a deleteAllPorts
898 // typically is part of a device deletion phase.
npujar1d86a522019-11-14 17:11:16 +0530899 if device, err := dMgr.GetDevice(deviceID); err == nil {
900 go func() {
901 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
902 if err != nil {
903 log.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
904 }
905 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400906 } else {
npujar1d86a522019-11-14 17:11:16 +0530907 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400908 return err
909 }
910 return nil
911 }
npujar1d86a522019-11-14 17:11:16 +0530912 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400913}
914
khenaidoo3ab34882019-05-02 21:33:30 -0400915//updatePortsState updates all ports on the device
npujar1d86a522019-11-14 17:11:16 +0530916func (dMgr *DeviceManager) updatePortsState(deviceID string, state voltha.OperStatus_OperStatus) error {
917 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400918
919 var adminState voltha.AdminState_AdminState
npujar1d86a522019-11-14 17:11:16 +0530920 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400921 switch state {
922 case voltha.OperStatus_ACTIVE:
923 adminState = voltha.AdminState_ENABLED
924 if err := agent.enablePorts(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530925 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400926 return err
927 }
928 case voltha.OperStatus_UNKNOWN:
929 adminState = voltha.AdminState_DISABLED
930 if err := agent.disablePorts(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530931 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400932 return err
933 }
934 default:
935 return status.Error(codes.Unimplemented, "state-change-not-implemented")
936 }
937 // Notify the logical device about the state change
npujar1d86a522019-11-14 17:11:16 +0530938 device, err := dMgr.GetDevice(deviceID)
939 if err != nil {
940 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400941 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400942 }
npujar1d86a522019-11-14 17:11:16 +0530943 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
944 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
945 return err
946 }
947 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400948 }
npujar1d86a522019-11-14 17:11:16 +0530949 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400950}
951
npujar1d86a522019-11-14 17:11:16 +0530952func (dMgr *DeviceManager) childDeviceDetected(parentDeviceID string, parentPortNo int64, deviceType string,
953 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
954 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 -0700955
npujar1d86a522019-11-14 17:11:16 +0530956 if deviceType == "" && vendorID != "" {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700957 log.Debug("device-type-is-nil-fetching-device-type")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530958 deviceTypesIf, err := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, "")
959 if err != nil {
960 log.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
961 return nil, err
962 }
963 if deviceTypesIf != nil {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700964 OLoop:
965 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
966 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
967 for _, v := range dType.VendorIds {
npujar1d86a522019-11-14 17:11:16 +0530968 if v == vendorID {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700969 deviceType = dType.Adapter
970 break OLoop
971 }
972 }
973 }
974 }
975 }
976 }
977 //if no match found for the vendorid,report adapter with the custom error message
978 if deviceType == "" {
npujar1d86a522019-11-14 17:11:16 +0530979 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
980 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700981 }
khenaidoob9203542018-09-17 22:56:37 -0400982
983 // Create the ONU device
984 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400985 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530986 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400987 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530988 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500989 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400990 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400991
992 //Get parent device type
npujar1d86a522019-11-14 17:11:16 +0530993 parent, err := dMgr.GetDevice(parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400994 if err != nil {
npujar1d86a522019-11-14 17:11:16 +0530995 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceID})
996 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400997 }
998
npujar1d86a522019-11-14 17:11:16 +0530999 if device, err := dMgr.GetChildDevice(parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
1000 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001001 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001002 }
1003
npujar1d86a522019-11-14 17:11:16 +05301004 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: parent.Type, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001005
1006 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -04001007 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -04001008 dMgr.addDeviceAgentToMap(agent)
npujar1d86a522019-11-14 17:11:16 +05301009 childDevice, err = agent.start(context.TODO(), childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001010 if err != nil {
1011 log.Error("error-starting-child")
1012 return nil, err
1013 }
khenaidoob9203542018-09-17 22:56:37 -04001014
khenaidoo09771ef2019-10-11 14:25:02 -04001015 // Since this Core has handled this request then it therefore owns this child device. Set the
1016 // ownership of this device to this Core
npujar1d86a522019-11-14 17:11:16 +05301017 _, err = dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{ID: agent.deviceID})
1018 if err != nil {
1019 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
1020 }
khenaidoo09771ef2019-10-11 14:25:02 -04001021
khenaidoob9203542018-09-17 22:56:37 -04001022 // Activate the child device
npujar1d86a522019-11-14 17:11:16 +05301023 if agent = dMgr.getDeviceAgent(agent.deviceID); agent != nil {
1024 go func() {
1025 err := agent.enableDevice(context.TODO())
1026 if err != nil {
1027 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1028 }
1029 }()
khenaidoob9203542018-09-17 22:56:37 -04001030 }
1031
khenaidoo79232702018-12-04 11:00:41 -05001032 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301033 go func() {
1034 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1035 if err != nil {
1036 log.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
1037 }
1038 }()
khenaidoo79232702018-12-04 11:00:41 -05001039
Scott Baker80678602019-11-14 16:57:36 -08001040 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001041}
1042
1043func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
1044 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -04001045 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
1046 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -05001047 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001048 return nil
khenaidoob9203542018-09-17 22:56:37 -04001049 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001050 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -04001051 for _, handler := range handlers {
1052 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
1053 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -04001054 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001055 return err
1056 }
1057 }
khenaidoob9203542018-09-17 22:56:37 -04001058 return nil
1059}
1060
npujar1d86a522019-11-14 17:11:16 +05301061func (dMgr *DeviceManager) packetOut(deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
1062 log.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
1063 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001064 return agent.packetOut(outPort, packet)
1065 }
npujar1d86a522019-11-14 17:11:16 +05301066 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001067}
1068
npujar1d86a522019-11-14 17:11:16 +05301069// PacketIn receives packet from adapter
1070func (dMgr *DeviceManager) PacketIn(deviceID string, port uint32, transactionID string, packet []byte) error {
1071 log.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001072 // Get the logical device Id based on the deviceId
1073 var device *voltha.Device
1074 var err error
npujar1d86a522019-11-14 17:11:16 +05301075 if device, err = dMgr.GetDevice(deviceID); err != nil {
1076 log.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001077 return err
1078 }
khenaidoo43c82122018-11-22 18:38:28 -05001079 if !device.Root {
npujar1d86a522019-11-14 17:11:16 +05301080 log.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
1081 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001082 }
1083
npujar1d86a522019-11-14 17:11:16 +05301084 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001085 return err
1086 }
1087 return nil
1088}
1089
npujar1d86a522019-11-14 17:11:16 +05301090func (dMgr *DeviceManager) setParentID(device *voltha.Device, parentID string) error {
1091 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
khenaidooad06fd72019-10-28 12:26:05 -04001092 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301093 return agent.setParentID(device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001094 }
1095 return status.Errorf(codes.NotFound, "%s", device.Id)
1096}
1097
npujar1d86a522019-11-14 17:11:16 +05301098// CreateLogicalDevice creates logical device in core
khenaidoo0a822f92019-05-08 15:15:57 -04001099func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
1100 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001101 // Verify whether the logical device has already been created
1102 if cDevice.ParentId != "" {
1103 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1104 return nil
1105 }
khenaidoob9203542018-09-17 22:56:37 -04001106 var err error
npujar1d86a522019-11-14 17:11:16 +05301107 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(context.TODO(), cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001108 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1109 return err
1110 }
khenaidoob9203542018-09-17 22:56:37 -04001111 return nil
1112}
1113
npujar1d86a522019-11-14 17:11:16 +05301114// DeleteLogicalDevice deletes logical device from core
khenaidoo0a822f92019-05-08 15:15:57 -04001115func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
1116 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001117 var err error
npujar1d86a522019-11-14 17:11:16 +05301118 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(context.TODO(), cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001119 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1120 return err
1121 }
1122 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301123 logicalID := ""
1124 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001125 return nil
1126}
1127
npujar1d86a522019-11-14 17:11:16 +05301128// DeleteLogicalPort removes the logical port associated with a device
khenaidoo0a822f92019-05-08 15:15:57 -04001129func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001130 log.Info("deleteLogicalPort")
1131 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001132 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301133 var lPortID *voltha.LogicalPortId
1134 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001135 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001136 return err
1137 }
npujar1d86a522019-11-14 17:11:16 +05301138 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(context.TODO(), lPortID); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001139 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001140 return err
1141 }
khenaidoo92e62c52018-10-03 14:02:54 -04001142 return nil
1143}
1144
npujar1d86a522019-11-14 17:11:16 +05301145// DeleteLogicalPorts removes the logical ports associated with that deviceId
khenaidoo0a822f92019-05-08 15:15:57 -04001146func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1147 log.Info("deleteLogicalPorts")
1148 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1149 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1150 return err
1151 }
1152 return nil
1153}
1154
khenaidoo92e62c52018-10-03 14:02:54 -04001155func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1156 // Sanity check
1157 if childDevice.Root {
1158 // childDevice is the parent device
1159 return childDevice
1160 }
khenaidoo19d7b632018-10-30 10:49:50 -04001161 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001162 return parentDevice
1163}
1164
khenaidoo0a822f92019-05-08 15:15:57 -04001165//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1166//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar1d86a522019-11-14 17:11:16 +05301167func (dMgr *DeviceManager) childDevicesLost(parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001168 log.Debug("childDevicesLost")
1169 var err error
1170 var parentDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +05301171 if parentDevice, err = dMgr.GetDevice(parentDeviceID); err != nil {
1172 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001173 return err
1174 }
1175 return dMgr.DisableAllChildDevices(parentDevice)
1176}
1177
1178//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1179// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar1d86a522019-11-14 17:11:16 +05301180func (dMgr *DeviceManager) childDevicesDetected(parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001181 log.Debug("childDevicesDetected")
1182 var err error
1183 var parentDevice *voltha.Device
1184 var childDeviceIds []string
1185
npujar1d86a522019-11-14 17:11:16 +05301186 if parentDevice, err = dMgr.GetDevice(parentDeviceID); err != nil {
1187 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001188 return err
1189 }
1190
1191 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1192 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1193 }
1194 if len(childDeviceIds) == 0 {
1195 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1196 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001197 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301198 for _, childDeviceID := range childDeviceIds {
1199 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001200 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301201 go func() {
1202 err = agent.enableDevice(context.TODO())
1203 if err != nil {
1204 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1205 }
1206 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001207 } else {
npujar1d86a522019-11-14 17:11:16 +05301208 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
1209 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001210 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001211 }
1212 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001213 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001214 return err
1215 }
1216 return nil
1217}
1218
khenaidoo4d4802d2018-10-04 21:59:49 -04001219/*
1220All the functions below are callback functions where they are invoked with the latest and previous data. We can
1221therefore use the data as is without trying to get the latest from the model.
1222*/
1223
khenaidoo0a822f92019-05-08 15:15:57 -04001224//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1225func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1226 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001227 var childDeviceIds []string
1228 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001229 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1230 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001231 }
1232 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001233 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001234 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001235 allChildDisable := true
npujar1d86a522019-11-14 17:11:16 +05301236 for _, childDeviceID := range childDeviceIds {
1237 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
1238 if err = agent.disableDevice(context.TODO()); err != nil {
1239 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001240 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001241 }
1242 }
1243 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001244 if !allChildDisable {
1245 return err
1246 }
khenaidoo92e62c52018-10-03 14:02:54 -04001247 return nil
1248}
1249
khenaidoo0a822f92019-05-08 15:15:57 -04001250//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1251func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1252 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001253 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001254 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001255 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1256 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001257 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001258 if len(childDeviceIds) == 0 {
1259 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1260 }
1261 allChildDeleted := true
npujar1d86a522019-11-14 17:11:16 +05301262 for _, childDeviceID := range childDeviceIds {
1263 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
1264 if err = agent.deleteDevice(context.TODO()); err != nil {
1265 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001266 allChildDeleted = false
khenaidoo4d4802d2018-10-04 21:59:49 -04001267 }
khenaidoo49085352020-01-13 19:15:43 -05001268 // No further action is required here. The deleteDevice will change the device state where the resulting
1269 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001270 }
1271 }
1272 if !allChildDeleted {
1273 return err
1274 }
1275 return nil
1276}
1277
1278//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1279func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1280 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001281 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001282 if parentDevice != nil {
1283 for _, port := range parentDevice.Ports {
1284 for _, peer := range port.Peers {
1285 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1286 }
khenaidoo92e62c52018-10-03 14:02:54 -04001287 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001288 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001289 }
1290 return childDeviceIds, nil
1291}
1292
khenaidoo297cd252019-02-07 22:10:23 -05001293//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar1d86a522019-11-14 17:11:16 +05301294func (dMgr *DeviceManager) getAllChildDevices(parentDeviceID string) (*voltha.Devices, error) {
1295 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
1296 if parentDevice, err := dMgr.GetDevice(parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001297 childDevices := make([]*voltha.Device, 0)
1298 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301299 for _, deviceID := range childDeviceIds {
1300 if d, e := dMgr.GetDevice(deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001301 childDevices = append(childDevices, d)
1302 }
1303 }
1304 }
1305 return &voltha.Devices{Items: childDevices}, nil
1306 }
npujar1d86a522019-11-14 17:11:16 +05301307 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001308}
1309
npujar1d86a522019-11-14 17:11:16 +05301310// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
khenaidoo0a822f92019-05-08 15:15:57 -04001311func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001312 log.Info("addUNILogicalPort")
npujar1d86a522019-11-14 17:11:16 +05301313 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(context.TODO(), cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001314 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1315 return err
1316 }
1317 return nil
1318}
1319
khenaidoof5a5bfa2019-01-23 22:20:29 -05001320func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1321 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1322 var res interface{}
1323 var err error
1324 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1325 if res, err = agent.downloadImage(ctx, img); err != nil {
1326 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1327 res = err
1328 }
1329 } else {
1330 res = status.Errorf(codes.NotFound, "%s", img.Id)
1331 }
1332 sendResponse(ctx, ch, res)
1333}
1334
1335func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1336 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1337 var res interface{}
1338 var err error
1339 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1340 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1341 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1342 res = err
1343 }
1344 } else {
1345 res = status.Errorf(codes.NotFound, "%s", img.Id)
1346 }
1347 sendResponse(ctx, ch, res)
1348}
1349
1350func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1351 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1352 var res interface{}
1353 var err error
1354 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1355 if res, err = agent.activateImage(ctx, img); err != nil {
1356 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1357 res = err
1358 }
1359 } else {
1360 res = status.Errorf(codes.NotFound, "%s", img.Id)
1361 }
1362 sendResponse(ctx, ch, res)
1363}
1364
1365func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1366 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1367 var res interface{}
1368 var err error
1369 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1370 if res, err = agent.revertImage(ctx, img); err != nil {
1371 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1372 res = err
1373 }
1374 } else {
1375 res = status.Errorf(codes.NotFound, "%s", img.Id)
1376 }
1377 sendResponse(ctx, ch, res)
1378}
1379
1380func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1381 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1382 var res interface{}
1383 var err error
1384 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1385 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1386 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1387 res = err
1388 }
1389 } else {
1390 res = status.Errorf(codes.NotFound, "%s", img.Id)
1391 }
1392 sendResponse(ctx, ch, res)
1393}
1394
npujar1d86a522019-11-14 17:11:16 +05301395func (dMgr *DeviceManager) updateImageDownload(deviceID string, img *voltha.ImageDownload) error {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001396 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar1d86a522019-11-14 17:11:16 +05301397 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001398 if err := agent.updateImageDownload(img); err != nil {
1399 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1400 return err
1401 }
1402 } else {
1403 return status.Errorf(codes.NotFound, "%s", img.Id)
1404 }
1405 return nil
1406}
1407
1408func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1409 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1410 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1411 return agent.getImageDownload(ctx, img)
1412 }
1413 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1414}
1415
npujar1d86a522019-11-14 17:11:16 +05301416func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
1417 log.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
1418 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
1419 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001420 }
npujar1d86a522019-11-14 17:11:16 +05301421 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001422}
1423
npujar1d86a522019-11-14 17:11:16 +05301424// SetAdminStateToEnable sets admin state of device to enabled
khenaidoo0a822f92019-05-08 15:15:57 -04001425func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1426 log.Info("SetAdminStateToEnable")
1427 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1428 return agent.updateAdminState(voltha.AdminState_ENABLED)
1429 }
1430 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1431}
1432
npujar1d86a522019-11-14 17:11:16 +05301433// NotifyInvalidTransition notifies about invalid transition
khenaidoo0a822f92019-05-08 15:15:57 -04001434func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001435 log.Errorw("NotifyInvalidTransition", log.Fields{
1436 "device": pcDevice.Id,
1437 "adminState": pcDevice.AdminState,
1438 "operState": pcDevice.OperStatus,
1439 "connState": pcDevice.ConnectStatus,
1440 })
khenaidoo0a822f92019-05-08 15:15:57 -04001441 //TODO: notify over kafka?
1442 return nil
1443}
1444
khenaidoob9203542018-09-17 22:56:37 -04001445func funcName(f interface{}) string {
1446 p := reflect.ValueOf(f).Pointer()
1447 rf := runtime.FuncForPC(p)
1448 return rf.Name()
1449}
1450
npujar1d86a522019-11-14 17:11:16 +05301451// UpdateDeviceAttribute updates value of particular device attribute
1452func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceID string, attribute string, value interface{}) {
1453 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001454 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001455 }
1456}
1457
npujar1d86a522019-11-14 17:11:16 +05301458// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
1459func (dMgr *DeviceManager) GetParentDeviceID(deviceID string) string {
1460 if device, _ := dMgr.GetDevice(deviceID); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001461 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001462 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001463 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001464 return ""
khenaidoob9203542018-09-17 22:56:37 -04001465}
serkant.uluderya334479d2019-04-10 08:26:15 -07001466
1467func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1468 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1469 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1470 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1471 var res interface{}
1472 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1473 res = agent.simulateAlarm(ctx, simulatereq)
1474 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1475 }
1476 //TODO CLI always get successful response
1477 sendResponse(ctx, ch, res)
1478}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001479
npujar1d86a522019-11-14 17:11:16 +05301480func (dMgr *DeviceManager) updateDeviceReason(deviceID string, reason string) error {
1481 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
1482 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001483 return agent.updateDeviceReason(reason)
1484 }
npujar1d86a522019-11-14 17:11:16 +05301485 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001486}