blob: 7bb869f5645068c1202da86e242b8d1f195292c4 [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 }
249 // stop managing the child devices
npujar1d86a522019-11-14 17:11:16 +0530250 childDeviceIds := dMgr.getAllDeviceIdsWithDeviceParentID(id)
251 for _, cID := range childDeviceIds {
252 dMgr.stopManagingDevice(cID)
khenaidoo6d62c002019-05-15 21:57:03 -0400253 }
254 }
255 if agent := dMgr.getDeviceAgent(id); agent != nil {
npujar1d86a522019-11-14 17:11:16 +0530256 agent.stop(context.TODO())
khenaidoo4c9e5592019-09-09 16:20:41 -0400257 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400258 // Abandon the device ownership
npujar1d86a522019-11-14 17:11:16 +0530259 err := dMgr.core.deviceOwnership.AbandonDevice(id)
260 if err != nil {
261 log.Errorw("unable-to-abandon-device", log.Fields{"error": err})
262 }
khenaidoo6d62c002019-05-15 21:57:03 -0400263 }
264 }
265}
266
npujar1d86a522019-11-14 17:11:16 +0530267// RunPostDeviceDelete removes any reference of this device
khenaidoo0a822f92019-05-08 15:15:57 -0400268func (dMgr *DeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
269 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
khenaidoo6d62c002019-05-15 21:57:03 -0400270 dMgr.stopManagingDevice(cDevice.Id)
271 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400272}
273
khenaidoo297cd252019-02-07 22:10:23 -0500274// GetDevice will returns a device, either from memory or from the dB, if present
khenaidoo19d7b632018-10-30 10:49:50 -0400275func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
276 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400277 if agent := dMgr.getDeviceAgent(id); agent != nil {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500278 return agent.getDevice(), nil
khenaidoo92e62c52018-10-03 14:02:54 -0400279 }
280 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400281}
282
npujar1d86a522019-11-14 17:11:16 +0530283// GetChildDevice will return a device, either from memory or from the dB, if present
284func (dMgr *DeviceManager) GetChildDevice(parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
285 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
286 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500287
288 var parentDevice *voltha.Device
289 var err error
npujar1d86a522019-11-14 17:11:16 +0530290 if parentDevice, err = dMgr.GetDevice(parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500291 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
292 }
293 var childDeviceIds []string
294 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
295 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
296 }
297 if len(childDeviceIds) == 0 {
npujar1d86a522019-11-14 17:11:16 +0530298 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
299 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500300 }
301
302 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530303 for _, childDeviceID := range childDeviceIds {
304 var found bool
305 if searchDevice, err := dMgr.GetDevice(childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500306
npujar1d86a522019-11-14 17:11:16 +0530307 foundOnuID := false
308 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500309 if searchDevice.ParentPortNo == uint32(parentPortNo) {
npujar1d86a522019-11-14 17:11:16 +0530310 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
311 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500312 }
313 }
314
315 foundSerialNumber := false
316 if searchDevice.SerialNumber == serialNumber {
317 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
318 foundSerialNumber = true
319 }
320
321 // if both onuId and serialNumber are provided both must be true for the device to be found
322 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530323 if onuID > 0 && serialNumber != "" {
324 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500325 } else {
npujar1d86a522019-11-14 17:11:16 +0530326 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500327 }
328
npujar1d86a522019-11-14 17:11:16 +0530329 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500330 foundChildDevice = searchDevice
331 break
332 }
333 }
334 }
335
336 if foundChildDevice != nil {
337 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
338 return foundChildDevice, nil
339 }
340
341 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530342 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
343 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500344}
345
npujar1d86a522019-11-14 17:11:16 +0530346// GetChildDeviceWithProxyAddress will return a device based on proxy address
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500347func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
348 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
349
350 var parentDevice *voltha.Device
351 var err error
352 if parentDevice, err = dMgr.GetDevice(proxyAddress.DeviceId); err != nil {
353 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
354 }
355 var childDeviceIds []string
356 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
357 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
358 }
359 if len(childDeviceIds) == 0 {
360 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
361 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
362 }
363
364 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530365 for _, childDeviceID := range childDeviceIds {
366 if searchDevice, err := dMgr.GetDevice(childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500367 if searchDevice.ProxyAddress == proxyAddress {
368 foundChildDevice = searchDevice
369 break
370 }
371 }
372 }
373
374 if foundChildDevice != nil {
375 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
376 return foundChildDevice, nil
377 }
378
379 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
380 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
381}
382
npujar1d86a522019-11-14 17:11:16 +0530383// IsDeviceInCache returns true if device is found in the map
khenaidoo297cd252019-02-07 22:10:23 -0500384func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400385 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500386 return exist
387}
388
npujar1d86a522019-11-14 17:11:16 +0530389// IsRootDevice returns true if root device is found in the map
khenaidoo19d7b632018-10-30 10:49:50 -0400390func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400391 dMgr.lockRootDeviceMap.RLock()
392 defer dMgr.lockRootDeviceMap.RUnlock()
393 if exist := dMgr.rootDevices[id]; exist {
394 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400395 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400396 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400397}
398
Stephane Barbarieaa467942019-02-06 14:09:44 -0500399// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400400func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400401 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400402 result := &voltha.Devices{}
Thomas Lee Se5a44012019-11-07 20:32:24 +0530403 devices, err := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, "")
404 if err != nil {
405 log.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
406 return nil, err
407 }
408 if devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500409 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500410 // If device is not in memory then set it up
411 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400412 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400413 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar1d86a522019-11-14 17:11:16 +0530414 if _, err := agent.start(context.TODO(), nil); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500415 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
npujar1d86a522019-11-14 17:11:16 +0530416 agent.stop(context.TODO())
khenaidoo297cd252019-02-07 22:10:23 -0500417 } else {
418 dMgr.addDeviceAgentToMap(agent)
419 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500420 }
421 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400422 }
423 }
khenaidoo6d62c002019-05-15 21:57:03 -0400424 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400425 return result, nil
426}
427
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530428//isParentDeviceExist checks whether device is already preprovisioned.
Thomas Lee Se5a44012019-11-07 20:32:24 +0530429func (dMgr *DeviceManager) isParentDeviceExist(newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530430 hostPort := newDevice.GetHostAndPort()
Thomas Lee Se5a44012019-11-07 20:32:24 +0530431 devices, err := dMgr.clusterDataProxy.List(context.Background(), "/devices", 0, false, "")
432 if err != nil {
433 log.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
434 return false, err
435 }
436 if devices != nil {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530437 for _, device := range devices.([]interface{}) {
438 if !device.(*voltha.Device).Root {
439 continue
440 }
441 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530442 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530443 }
444 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530445 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530446 }
447 }
448 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530449 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530450}
451
khenaidoo6d62c002019-05-15 21:57:03 -0400452//getDeviceFromModelretrieves the device data from the model.
npujar1d86a522019-11-14 17:11:16 +0530453func (dMgr *DeviceManager) getDeviceFromModel(deviceID string) (*voltha.Device, error) {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530454 device, err := dMgr.clusterDataProxy.Get(context.Background(), "/devices/"+deviceID, 0, false, "")
455 if err != nil {
456 log.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
457 return nil, err
458 }
459 if device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400460 if d, ok := device.(*voltha.Device); ok {
461 return d, nil
462 }
463 }
npujar1d86a522019-11-14 17:11:16 +0530464 return nil, status.Error(codes.NotFound, deviceID)
khenaidoo6d62c002019-05-15 21:57:03 -0400465}
466
npujar1d86a522019-11-14 17:11:16 +0530467// loadDevice loads the deviceID in memory, if not present
468func (dMgr *DeviceManager) loadDevice(deviceID string) (*DeviceAgent, error) {
469 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500470 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
471 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400472 var err error
473 var device *voltha.Device
474 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530475 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
476 if !dMgr.IsDeviceInCache(deviceID) {
477 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400478 dMgr.devicesLoadingLock.Unlock()
479 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar1d86a522019-11-14 17:11:16 +0530480 if device, err = dMgr.getDeviceFromModel(deviceID); err == nil {
481 log.Debugw("loading-device", log.Fields{"deviceId": deviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400482 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar1d86a522019-11-14 17:11:16 +0530483 if _, err = agent.start(context.TODO(), nil); err != nil {
484 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
485 agent.stop(context.TODO())
khenaidoo4c9e5592019-09-09 16:20:41 -0400486 } else {
487 dMgr.addDeviceAgentToMap(agent)
488 }
489 } else {
npujar1d86a522019-11-14 17:11:16 +0530490 log.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400491 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400492 // announce completion of task to any number of waiting channels
493 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530494 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400495 for _, ch := range v {
496 close(ch)
497 }
npujar1d86a522019-11-14 17:11:16 +0530498 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400499 }
500 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400501 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400502 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500503 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400504 } else {
505 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530506 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400507 dMgr.devicesLoadingLock.Unlock()
508 // Wait for the channel to be closed, implying the process loading this device is done.
509 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500510 }
npujar1d86a522019-11-14 17:11:16 +0530511 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400512 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500513 }
npujar1d86a522019-11-14 17:11:16 +0530514 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500515}
516
517// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
518func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(device *voltha.Device) error {
519 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
520 if device.Root {
521 // Scenario A
522 if device.ParentId != "" {
523 // Load logical device if needed.
524 if err := dMgr.logicalDeviceMgr.load(device.ParentId); err != nil {
525 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
526 }
527 } else {
528 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
529 }
530 // Load all child devices, if needed
531 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530532 for _, childDeviceID := range childDeviceIds {
533 if _, err := dMgr.loadDevice(childDeviceID); err != nil {
534 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500535 return err
536 }
537 }
538 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
539 } else {
540 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
541 }
542 }
543 return nil
544}
545
546// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
547// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
548// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
549// and the proceed with the request.
npujar1d86a522019-11-14 17:11:16 +0530550func (dMgr *DeviceManager) load(deviceID string) error {
khenaidoo297cd252019-02-07 22:10:23 -0500551 log.Debug("load...")
552 // First load the device - this may fail in case the device was deleted intentionally by the other core
553 var dAgent *DeviceAgent
554 var err error
npujar1d86a522019-11-14 17:11:16 +0530555 if dAgent, err = dMgr.loadDevice(deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500556 return err
557 }
558 // Get the loaded device details
khenaidoo6e55d9e2019-12-12 18:26:26 -0500559 device := dAgent.getDevice()
khenaidoo297cd252019-02-07 22:10:23 -0500560
561 // If the device is in Pre-provisioning or deleted state stop here
562 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
563 return nil
564 }
565
566 // Now we face two scenarios
567 if device.Root {
568 // Load all children as well as the parent of this device (logical_device)
569 if err := dMgr.loadRootDeviceParentAndChildren(device); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530570 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500571 return err
572 }
npujar1d86a522019-11-14 17:11:16 +0530573 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500574 } else {
575 // Scenario B - use the parentId of that device (root device) to trigger the loading
576 if device.ParentId != "" {
577 return dMgr.load(device.ParentId)
578 }
579 }
580 return nil
581}
582
khenaidoo7ccedd52018-12-14 16:48:54 -0500583// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
584func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
585 log.Debug("ListDeviceIDs")
586 // Report only device IDs that are in the device agent map
587 return dMgr.listDeviceIdsFromMap(), nil
588}
589
khenaidoo4c9e5592019-09-09 16:20:41 -0400590//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
591//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500592func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400593 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500594 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400595 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500596 toReconcile := len(ids.Items)
597 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400598 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500599 for _, id := range ids.Items {
khenaidoo4c9e5592019-09-09 16:20:41 -0400600 if err = dMgr.load(id.Id); err != nil {
601 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
602 } else {
npujar1d86a522019-11-14 17:11:16 +0530603 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500604 }
605 }
606 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400607 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500608 }
609 } else {
610 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
611 }
612 sendResponse(ctx, ch, res)
613}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500614
khenaidooba6b6c42019-08-02 09:11:56 -0400615// isOkToReconcile validates whether a device is in the correct status to be reconciled
616func isOkToReconcile(device *voltha.Device) bool {
617 if device == nil {
618 return false
619 }
620 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
621}
622
623// adapterRestarted is invoked whenever an adapter is restarted
624func (dMgr *DeviceManager) adapterRestarted(adapter *voltha.Adapter) error {
625 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
626
627 // Let's reconcile the device managed by this Core only
628 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
629 if len(rootDeviceIds) == 0 {
630 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
631 return nil
632 }
633
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500634 responses := make([]utils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530635 for _, rootDeviceID := range rootDeviceIds {
636 if rootDevice, _ := dMgr.getDeviceFromModel(rootDeviceID); rootDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400637 if rootDevice.Adapter == adapter.Id {
638 if isOkToReconcile(rootDevice) {
639 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500640 responses = append(responses, dMgr.sendReconcileDeviceRequest(rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400641 } else {
642 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
643 }
644 } else { // Should we be reconciling the root's children instead?
645 childManagedByAdapter:
646 for _, port := range rootDevice.Ports {
647 for _, peer := range port.Peers {
648 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
649 if childDevice.Adapter == adapter.Id {
650 if isOkToReconcile(childDevice) {
651 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500652 responses = append(responses, dMgr.sendReconcileDeviceRequest(childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400653 } else {
654 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
655 }
656 } else {
657 // All child devices under a parent device are typically managed by the same adapter type.
658 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
659 break childManagedByAdapter
660 }
661 }
662 }
663 }
664 }
665 }
666 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500667 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400668 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500669 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400670 return status.Errorf(codes.Aborted, "errors-%s", res)
671 }
672 } else {
673 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
674 }
675 return nil
676}
677
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500678func (dMgr *DeviceManager) sendReconcileDeviceRequest(device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400679 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
680 // 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 +0530681 // 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 -0400682 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500683 response := utils.NewResponse()
khenaidooba6b6c42019-08-02 09:11:56 -0400684 go func(device *voltha.Device) {
685 if err := dMgr.adapterProxy.ReconcileDevice(context.Background(), device); err != nil {
686 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500687 response.Error(status.Errorf(codes.Internal, "device: %s", device.Id))
khenaidooba6b6c42019-08-02 09:11:56 -0400688 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500689 response.Done()
khenaidooba6b6c42019-08-02 09:11:56 -0400690 }(device)
691
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500692 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400693}
694
npujar1d86a522019-11-14 17:11:16 +0530695func (dMgr *DeviceManager) reconcileChildDevices(parentDeviceID string) error {
696 if parentDevice, _ := dMgr.getDeviceFromModel(parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500697 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400698 for _, port := range parentDevice.Ports {
699 for _, peer := range port.Peers {
700 if childDevice, _ := dMgr.getDeviceFromModel(peer.DeviceId); childDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500701 responses = append(responses, dMgr.sendReconcileDeviceRequest(childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400702 }
703 }
704 }
705 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500706 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400707 return status.Errorf(codes.Aborted, "errors-%s", res)
708 }
709 }
710 return nil
711}
712
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700713func (dMgr *DeviceManager) updateDeviceUsingAdapterData(device *voltha.Device) error {
714 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400715 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700716 return agent.updateDeviceUsingAdapterData(device)
khenaidoob9203542018-09-17 22:56:37 -0400717 }
718 return status.Errorf(codes.NotFound, "%s", device.Id)
719}
720
npujar1d86a522019-11-14 17:11:16 +0530721func (dMgr *DeviceManager) addPort(deviceID string, port *voltha.Port) error {
722 agent := dMgr.getDeviceAgent(deviceID)
723 if agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400724 if err := agent.addPort(port); err != nil {
725 return err
726 }
727 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530728 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400729 for _, peerPort := range port.Peers {
730 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
731 if err := agent.addPeerPort(meAsPeer); err != nil {
732 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
733 return err
734 }
735 }
736 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400737 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
738 // then a logical port will be added to the logical device and the device graph generated. If the port is a
739 // PON port then only the device graph will be generated.
npujar1d86a522019-11-14 17:11:16 +0530740 if device, err := dMgr.GetDevice(deviceID); err == nil {
741 go func() {
742 err = dMgr.logicalDeviceMgr.updateLogicalPort(device, port)
743 if err != nil {
744 log.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
745 }
746 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400747 } else {
npujar1d86a522019-11-14 17:11:16 +0530748 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400749 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400750 }
khenaidoo92e62c52018-10-03 14:02:54 -0400751 return nil
khenaidoob9203542018-09-17 22:56:37 -0400752 }
npujar1d86a522019-11-14 17:11:16 +0530753 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400754}
755
npujar1d86a522019-11-14 17:11:16 +0530756func (dMgr *DeviceManager) deletePeerPorts(fromDeviceID string, deviceID string) error {
757 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceID, "deviceid": deviceID})
758 if agent := dMgr.getDeviceAgent(fromDeviceID); agent != nil {
759 return agent.deletePeerPorts(deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400760 }
npujar1d86a522019-11-14 17:11:16 +0530761 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400762}
763
npujar1d86a522019-11-14 17:11:16 +0530764func (dMgr *DeviceManager) addFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
765 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "flowMetadata": flowMetadata})
766 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400767 return agent.addFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400768 }
npujar1d86a522019-11-14 17:11:16 +0530769 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400770}
771
npujar1d86a522019-11-14 17:11:16 +0530772func (dMgr *DeviceManager) deleteFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
773 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
774 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400775 return agent.deleteFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400776 }
npujar1d86a522019-11-14 17:11:16 +0530777 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400778}
779
npujar1d86a522019-11-14 17:11:16 +0530780func (dMgr *DeviceManager) updateFlowsAndGroups(deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
781 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
782 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400783 return agent.updateFlowsAndGroups(flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400784 }
npujar1d86a522019-11-14 17:11:16 +0530785 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400786}
787
khenaidoob3127472019-07-24 21:04:55 -0400788// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
789// following a user action
790func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
791 var res interface{}
792 if pmConfigs.Id == "" {
793 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
794 } else if agent := dMgr.getDeviceAgent(pmConfigs.Id); agent != nil {
795 res = agent.updatePmConfigs(ctx, pmConfigs)
796 } else {
797 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
798 }
799 sendResponse(ctx, ch, res)
800}
801
802// initPmConfigs initialize the pm configs as defined by the adapter.
npujar1d86a522019-11-14 17:11:16 +0530803func (dMgr *DeviceManager) initPmConfigs(deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400804 if pmConfigs.Id == "" {
805 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
806 }
npujar1d86a522019-11-14 17:11:16 +0530807 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400808 return agent.initPmConfigs(pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400809 }
npujar1d86a522019-11-14 17:11:16 +0530810 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400811}
812
npujar1d86a522019-11-14 17:11:16 +0530813func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
814 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400815 return agent.listPmConfigs(ctx)
816 }
npujar1d86a522019-11-14 17:11:16 +0530817 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400818}
819
npujar1d86a522019-11-14 17:11:16 +0530820func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
821 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
822 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400823 return agent.getSwitchCapability(ctx)
824 }
npujar1d86a522019-11-14 17:11:16 +0530825 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400826}
827
npujar1d86a522019-11-14 17:11:16 +0530828func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
829 log.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
830 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400831 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400832 }
npujar1d86a522019-11-14 17:11:16 +0530833 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400834}
835
npujar1d86a522019-11-14 17:11:16 +0530836func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
837 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
838 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400839 return agent.getPortCapability(ctx, portNo)
840 }
npujar1d86a522019-11-14 17:11:16 +0530841 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400842}
843
npujar1d86a522019-11-14 17:11:16 +0530844func (dMgr *DeviceManager) updateDeviceStatus(deviceID string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
845 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
846 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400847 return agent.updateDeviceStatus(operStatus, connStatus)
848 }
npujar1d86a522019-11-14 17:11:16 +0530849 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400850}
851
npujar1d86a522019-11-14 17:11:16 +0530852func (dMgr *DeviceManager) updateChildrenStatus(deviceID string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
853 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400854 var parentDevice *voltha.Device
855 var err error
npujar1d86a522019-11-14 17:11:16 +0530856 if parentDevice, err = dMgr.GetDevice(deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400857 return status.Errorf(codes.Aborted, "%s", err.Error())
858 }
859 var childDeviceIds []string
860 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
861 return status.Errorf(codes.Aborted, "%s", err.Error())
862 }
863 if len(childDeviceIds) == 0 {
864 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
865 }
npujar1d86a522019-11-14 17:11:16 +0530866 for _, childDeviceID := range childDeviceIds {
867 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400868 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530869 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400870 }
871 }
872 }
873 return nil
874}
875
npujar1d86a522019-11-14 17:11:16 +0530876func (dMgr *DeviceManager) updatePortState(deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
877 log.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
878 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo171b98e2019-10-31 11:48:15 -0400879 if err := agent.updatePortState(portType, portNo, operStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530880 log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400881 return err
882 }
883 // Notify the logical device manager to change the port state
npujar1d86a522019-11-14 17:11:16 +0530884 go func() {
885 err := dMgr.logicalDeviceMgr.updatePortState(deviceID, portNo, operStatus)
886 if err != nil {
887 log.Errorw("unable-to-update-port-state", log.Fields{"error": err})
888 }
889 }()
khenaidoob9203542018-09-17 22:56:37 -0400890 }
npujar1d86a522019-11-14 17:11:16 +0530891 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400892}
893
npujar1d86a522019-11-14 17:11:16 +0530894func (dMgr *DeviceManager) deleteAllPorts(deviceID string) error {
895 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
896 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400897 if err := agent.deleteAllPorts(); err != nil {
898 return err
899 }
900 // Notify the logical device manager to remove all logical ports, if needed.
901 // At this stage the device itself may gave been deleted already at a deleteAllPorts
902 // typically is part of a device deletion phase.
npujar1d86a522019-11-14 17:11:16 +0530903 if device, err := dMgr.GetDevice(deviceID); err == nil {
904 go func() {
905 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(device)
906 if err != nil {
907 log.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
908 }
909 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400910 } else {
npujar1d86a522019-11-14 17:11:16 +0530911 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400912 return err
913 }
914 return nil
915 }
npujar1d86a522019-11-14 17:11:16 +0530916 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400917}
918
khenaidoo3ab34882019-05-02 21:33:30 -0400919//updatePortsState updates all ports on the device
npujar1d86a522019-11-14 17:11:16 +0530920func (dMgr *DeviceManager) updatePortsState(deviceID string, state voltha.OperStatus_OperStatus) error {
921 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400922
923 var adminState voltha.AdminState_AdminState
npujar1d86a522019-11-14 17:11:16 +0530924 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400925 switch state {
926 case voltha.OperStatus_ACTIVE:
927 adminState = voltha.AdminState_ENABLED
928 if err := agent.enablePorts(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530929 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400930 return err
931 }
932 case voltha.OperStatus_UNKNOWN:
933 adminState = voltha.AdminState_DISABLED
934 if err := agent.disablePorts(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530935 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400936 return err
937 }
938 default:
939 return status.Error(codes.Unimplemented, "state-change-not-implemented")
940 }
941 // Notify the logical device about the state change
npujar1d86a522019-11-14 17:11:16 +0530942 device, err := dMgr.GetDevice(deviceID)
943 if err != nil {
944 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400945 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400946 }
npujar1d86a522019-11-14 17:11:16 +0530947 if err := dMgr.logicalDeviceMgr.updatePortsState(device, adminState); err != nil {
948 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
949 return err
950 }
951 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400952 }
npujar1d86a522019-11-14 17:11:16 +0530953 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400954}
955
npujar1d86a522019-11-14 17:11:16 +0530956func (dMgr *DeviceManager) childDeviceDetected(parentDeviceID string, parentPortNo int64, deviceType string,
957 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
958 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 -0700959
npujar1d86a522019-11-14 17:11:16 +0530960 if deviceType == "" && vendorID != "" {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700961 log.Debug("device-type-is-nil-fetching-device-type")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530962 deviceTypesIf, err := dMgr.adapterMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, "")
963 if err != nil {
964 log.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
965 return nil, err
966 }
967 if deviceTypesIf != nil {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700968 OLoop:
969 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
970 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
971 for _, v := range dType.VendorIds {
npujar1d86a522019-11-14 17:11:16 +0530972 if v == vendorID {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700973 deviceType = dType.Adapter
974 break OLoop
975 }
976 }
977 }
978 }
979 }
980 }
981 //if no match found for the vendorid,report adapter with the custom error message
982 if deviceType == "" {
npujar1d86a522019-11-14 17:11:16 +0530983 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
984 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700985 }
khenaidoob9203542018-09-17 22:56:37 -0400986
987 // Create the ONU device
988 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400989 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530990 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400991 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530992 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500993 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400994 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400995
996 //Get parent device type
npujar1d86a522019-11-14 17:11:16 +0530997 parent, err := dMgr.GetDevice(parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400998 if err != nil {
npujar1d86a522019-11-14 17:11:16 +0530999 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceID})
1000 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001001 }
1002
npujar1d86a522019-11-14 17:11:16 +05301003 if device, err := dMgr.GetChildDevice(parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
1004 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001005 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001006 }
1007
npujar1d86a522019-11-14 17:11:16 +05301008 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: parent.Type, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001009
1010 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -04001011 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -04001012 dMgr.addDeviceAgentToMap(agent)
npujar1d86a522019-11-14 17:11:16 +05301013 childDevice, err = agent.start(context.TODO(), childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001014 if err != nil {
1015 log.Error("error-starting-child")
1016 return nil, err
1017 }
khenaidoob9203542018-09-17 22:56:37 -04001018
khenaidoo09771ef2019-10-11 14:25:02 -04001019 // Since this Core has handled this request then it therefore owns this child device. Set the
1020 // ownership of this device to this Core
npujar1d86a522019-11-14 17:11:16 +05301021 _, err = dMgr.core.deviceOwnership.OwnedByMe(&utils.DeviceID{ID: agent.deviceID})
1022 if err != nil {
1023 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
1024 }
khenaidoo09771ef2019-10-11 14:25:02 -04001025
khenaidoob9203542018-09-17 22:56:37 -04001026 // Activate the child device
npujar1d86a522019-11-14 17:11:16 +05301027 if agent = dMgr.getDeviceAgent(agent.deviceID); agent != nil {
1028 go func() {
1029 err := agent.enableDevice(context.TODO())
1030 if err != nil {
1031 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1032 }
1033 }()
khenaidoob9203542018-09-17 22:56:37 -04001034 }
1035
khenaidoo79232702018-12-04 11:00:41 -05001036 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301037 go func() {
1038 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1039 if err != nil {
1040 log.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
1041 }
1042 }()
khenaidoo79232702018-12-04 11:00:41 -05001043
Scott Baker80678602019-11-14 16:57:36 -08001044 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001045}
1046
1047func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
1048 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -04001049 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
1050 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -05001051 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001052 return nil
khenaidoob9203542018-09-17 22:56:37 -04001053 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001054 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -04001055 for _, handler := range handlers {
1056 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
1057 if err := handler(current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -04001058 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001059 return err
1060 }
1061 }
khenaidoob9203542018-09-17 22:56:37 -04001062 return nil
1063}
1064
npujar1d86a522019-11-14 17:11:16 +05301065func (dMgr *DeviceManager) packetOut(deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
1066 log.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
1067 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001068 return agent.packetOut(outPort, packet)
1069 }
npujar1d86a522019-11-14 17:11:16 +05301070 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001071}
1072
npujar1d86a522019-11-14 17:11:16 +05301073// PacketIn receives packet from adapter
1074func (dMgr *DeviceManager) PacketIn(deviceID string, port uint32, transactionID string, packet []byte) error {
1075 log.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001076 // Get the logical device Id based on the deviceId
1077 var device *voltha.Device
1078 var err error
npujar1d86a522019-11-14 17:11:16 +05301079 if device, err = dMgr.GetDevice(deviceID); err != nil {
1080 log.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001081 return err
1082 }
khenaidoo43c82122018-11-22 18:38:28 -05001083 if !device.Root {
npujar1d86a522019-11-14 17:11:16 +05301084 log.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
1085 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001086 }
1087
npujar1d86a522019-11-14 17:11:16 +05301088 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001089 return err
1090 }
1091 return nil
1092}
1093
npujar1d86a522019-11-14 17:11:16 +05301094func (dMgr *DeviceManager) setParentID(device *voltha.Device, parentID string) error {
1095 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
khenaidooad06fd72019-10-28 12:26:05 -04001096 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301097 return agent.setParentID(device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001098 }
1099 return status.Errorf(codes.NotFound, "%s", device.Id)
1100}
1101
npujar1d86a522019-11-14 17:11:16 +05301102// CreateLogicalDevice creates logical device in core
khenaidoo0a822f92019-05-08 15:15:57 -04001103func (dMgr *DeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
1104 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001105 // Verify whether the logical device has already been created
1106 if cDevice.ParentId != "" {
1107 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1108 return nil
1109 }
khenaidoob9203542018-09-17 22:56:37 -04001110 var err error
npujar1d86a522019-11-14 17:11:16 +05301111 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(context.TODO(), cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001112 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1113 return err
1114 }
khenaidoob9203542018-09-17 22:56:37 -04001115 return nil
1116}
1117
npujar1d86a522019-11-14 17:11:16 +05301118// DeleteLogicalDevice deletes logical device from core
khenaidoo0a822f92019-05-08 15:15:57 -04001119func (dMgr *DeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
1120 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001121 var err error
npujar1d86a522019-11-14 17:11:16 +05301122 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(context.TODO(), cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001123 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1124 return err
1125 }
1126 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301127 logicalID := ""
1128 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001129 return nil
1130}
1131
npujar1d86a522019-11-14 17:11:16 +05301132// DeleteLogicalPort removes the logical port associated with a device
khenaidoo0a822f92019-05-08 15:15:57 -04001133func (dMgr *DeviceManager) DeleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001134 log.Info("deleteLogicalPort")
1135 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001136 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301137 var lPortID *voltha.LogicalPortId
1138 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001139 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001140 return err
1141 }
npujar1d86a522019-11-14 17:11:16 +05301142 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(context.TODO(), lPortID); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001143 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001144 return err
1145 }
khenaidoo92e62c52018-10-03 14:02:54 -04001146 return nil
1147}
1148
npujar1d86a522019-11-14 17:11:16 +05301149// DeleteLogicalPorts removes the logical ports associated with that deviceId
khenaidoo0a822f92019-05-08 15:15:57 -04001150func (dMgr *DeviceManager) DeleteLogicalPorts(device *voltha.Device) error {
1151 log.Info("deleteLogicalPorts")
1152 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(device.Id); err != nil {
1153 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1154 return err
1155 }
1156 return nil
1157}
1158
khenaidoo92e62c52018-10-03 14:02:54 -04001159func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
1160 // Sanity check
1161 if childDevice.Root {
1162 // childDevice is the parent device
1163 return childDevice
1164 }
khenaidoo19d7b632018-10-30 10:49:50 -04001165 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001166 return parentDevice
1167}
1168
khenaidoo0a822f92019-05-08 15:15:57 -04001169//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1170//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar1d86a522019-11-14 17:11:16 +05301171func (dMgr *DeviceManager) childDevicesLost(parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001172 log.Debug("childDevicesLost")
1173 var err error
1174 var parentDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +05301175 if parentDevice, err = dMgr.GetDevice(parentDeviceID); err != nil {
1176 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001177 return err
1178 }
1179 return dMgr.DisableAllChildDevices(parentDevice)
1180}
1181
1182//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1183// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar1d86a522019-11-14 17:11:16 +05301184func (dMgr *DeviceManager) childDevicesDetected(parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001185 log.Debug("childDevicesDetected")
1186 var err error
1187 var parentDevice *voltha.Device
1188 var childDeviceIds []string
1189
npujar1d86a522019-11-14 17:11:16 +05301190 if parentDevice, err = dMgr.GetDevice(parentDeviceID); err != nil {
1191 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001192 return err
1193 }
1194
1195 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1196 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1197 }
1198 if len(childDeviceIds) == 0 {
1199 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1200 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001201 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301202 for _, childDeviceID := range childDeviceIds {
1203 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001204 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301205 go func() {
1206 err = agent.enableDevice(context.TODO())
1207 if err != nil {
1208 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1209 }
1210 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001211 } else {
npujar1d86a522019-11-14 17:11:16 +05301212 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
1213 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001214 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001215 }
1216 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001217 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001218 return err
1219 }
1220 return nil
1221}
1222
khenaidoo4d4802d2018-10-04 21:59:49 -04001223/*
1224All the functions below are callback functions where they are invoked with the latest and previous data. We can
1225therefore use the data as is without trying to get the latest from the model.
1226*/
1227
khenaidoo0a822f92019-05-08 15:15:57 -04001228//DisableAllChildDevices is invoked as a callback when the parent device is disabled
1229func (dMgr *DeviceManager) DisableAllChildDevices(parentDevice *voltha.Device) error {
1230 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001231 var childDeviceIds []string
1232 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 }
1236 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001237 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001238 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001239 allChildDisable := true
npujar1d86a522019-11-14 17:11:16 +05301240 for _, childDeviceID := range childDeviceIds {
1241 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
1242 if err = agent.disableDevice(context.TODO()); err != nil {
1243 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001244 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001245 }
1246 }
1247 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001248 if !allChildDisable {
1249 return err
1250 }
khenaidoo92e62c52018-10-03 14:02:54 -04001251 return nil
1252}
1253
khenaidoo0a822f92019-05-08 15:15:57 -04001254//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
1255func (dMgr *DeviceManager) DeleteAllChildDevices(parentDevice *voltha.Device) error {
1256 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001257 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001258 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001259 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1260 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001261 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001262 if len(childDeviceIds) == 0 {
1263 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1264 }
1265 allChildDeleted := true
npujar1d86a522019-11-14 17:11:16 +05301266 for _, childDeviceID := range childDeviceIds {
1267 if agent := dMgr.getDeviceAgent(childDeviceID); agent != nil {
1268 if err = agent.deleteDevice(context.TODO()); err != nil {
1269 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001270 allChildDeleted = false
1271 } else {
npujar1d86a522019-11-14 17:11:16 +05301272 agent.stop(context.TODO())
khenaidoo4c9e5592019-09-09 16:20:41 -04001273 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo4d4802d2018-10-04 21:59:49 -04001274 }
1275 }
1276 }
1277 if !allChildDeleted {
1278 return err
1279 }
1280 return nil
1281}
1282
khenaidoo6d62c002019-05-15 21:57:03 -04001283//getAllDeviceIdsWithDeviceParentId returns the list of device Ids which has id as parent Id. This function uses the
1284// data from the agent instead of using the data from the parent device as that data would disappear from a parent
1285// device during a delete device operation.
npujar1d86a522019-11-14 17:11:16 +05301286func (dMgr *DeviceManager) getAllDeviceIdsWithDeviceParentID(id string) []string {
khenaidoo6d62c002019-05-15 21:57:03 -04001287 log.Debugw("getAllAgentsWithDeviceParentId", log.Fields{"parentDeviceId": id})
1288 deviceIds := make([]string, 0)
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001289 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
1290 agent := value.(*DeviceAgent)
npujar1d86a522019-11-14 17:11:16 +05301291 if agent.parentID == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001292 deviceIds = append(deviceIds, key.(string))
khenaidoo6d62c002019-05-15 21:57:03 -04001293 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001294 return true
1295 })
khenaidoo6d62c002019-05-15 21:57:03 -04001296 return deviceIds
1297}
1298
khenaidoo4d4802d2018-10-04 21:59:49 -04001299//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1300func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1301 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001302 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001303 if parentDevice != nil {
1304 for _, port := range parentDevice.Ports {
1305 for _, peer := range port.Peers {
1306 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1307 }
khenaidoo92e62c52018-10-03 14:02:54 -04001308 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001309 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001310 }
1311 return childDeviceIds, nil
1312}
1313
khenaidoo297cd252019-02-07 22:10:23 -05001314//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar1d86a522019-11-14 17:11:16 +05301315func (dMgr *DeviceManager) getAllChildDevices(parentDeviceID string) (*voltha.Devices, error) {
1316 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
1317 if parentDevice, err := dMgr.GetDevice(parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001318 childDevices := make([]*voltha.Device, 0)
1319 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301320 for _, deviceID := range childDeviceIds {
1321 if d, e := dMgr.GetDevice(deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001322 childDevices = append(childDevices, d)
1323 }
1324 }
1325 }
1326 return &voltha.Devices{Items: childDevices}, nil
1327 }
npujar1d86a522019-11-14 17:11:16 +05301328 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001329}
1330
npujar1d86a522019-11-14 17:11:16 +05301331// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
khenaidoo0a822f92019-05-08 15:15:57 -04001332func (dMgr *DeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001333 log.Info("addUNILogicalPort")
npujar1d86a522019-11-14 17:11:16 +05301334 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(context.TODO(), cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001335 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1336 return err
1337 }
1338 return nil
1339}
1340
khenaidoof5a5bfa2019-01-23 22:20:29 -05001341func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1342 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1343 var res interface{}
1344 var err error
1345 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1346 if res, err = agent.downloadImage(ctx, img); err != nil {
1347 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1348 res = err
1349 }
1350 } else {
1351 res = status.Errorf(codes.NotFound, "%s", img.Id)
1352 }
1353 sendResponse(ctx, ch, res)
1354}
1355
1356func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1357 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1358 var res interface{}
1359 var err error
1360 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1361 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1362 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1363 res = err
1364 }
1365 } else {
1366 res = status.Errorf(codes.NotFound, "%s", img.Id)
1367 }
1368 sendResponse(ctx, ch, res)
1369}
1370
1371func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1372 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1373 var res interface{}
1374 var err error
1375 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1376 if res, err = agent.activateImage(ctx, img); err != nil {
1377 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1378 res = err
1379 }
1380 } else {
1381 res = status.Errorf(codes.NotFound, "%s", img.Id)
1382 }
1383 sendResponse(ctx, ch, res)
1384}
1385
1386func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1387 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1388 var res interface{}
1389 var err error
1390 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1391 if res, err = agent.revertImage(ctx, img); err != nil {
1392 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1393 res = err
1394 }
1395 } else {
1396 res = status.Errorf(codes.NotFound, "%s", img.Id)
1397 }
1398 sendResponse(ctx, ch, res)
1399}
1400
1401func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1402 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1403 var res interface{}
1404 var err error
1405 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1406 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1407 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1408 res = err
1409 }
1410 } else {
1411 res = status.Errorf(codes.NotFound, "%s", img.Id)
1412 }
1413 sendResponse(ctx, ch, res)
1414}
1415
npujar1d86a522019-11-14 17:11:16 +05301416func (dMgr *DeviceManager) updateImageDownload(deviceID string, img *voltha.ImageDownload) error {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001417 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar1d86a522019-11-14 17:11:16 +05301418 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001419 if err := agent.updateImageDownload(img); err != nil {
1420 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1421 return err
1422 }
1423 } else {
1424 return status.Errorf(codes.NotFound, "%s", img.Id)
1425 }
1426 return nil
1427}
1428
1429func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1430 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1431 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
1432 return agent.getImageDownload(ctx, img)
1433 }
1434 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1435}
1436
npujar1d86a522019-11-14 17:11:16 +05301437func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
1438 log.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
1439 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
1440 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001441 }
npujar1d86a522019-11-14 17:11:16 +05301442 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001443}
1444
npujar1d86a522019-11-14 17:11:16 +05301445// SetAdminStateToEnable sets admin state of device to enabled
khenaidoo0a822f92019-05-08 15:15:57 -04001446func (dMgr *DeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
1447 log.Info("SetAdminStateToEnable")
1448 if agent := dMgr.getDeviceAgent(cDevice.Id); agent != nil {
1449 return agent.updateAdminState(voltha.AdminState_ENABLED)
1450 }
1451 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1452}
1453
npujar1d86a522019-11-14 17:11:16 +05301454// NotifyInvalidTransition notifies about invalid transition
khenaidoo0a822f92019-05-08 15:15:57 -04001455func (dMgr *DeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001456 log.Errorw("NotifyInvalidTransition", log.Fields{
1457 "device": pcDevice.Id,
1458 "adminState": pcDevice.AdminState,
1459 "operState": pcDevice.OperStatus,
1460 "connState": pcDevice.ConnectStatus,
1461 })
khenaidoo0a822f92019-05-08 15:15:57 -04001462 //TODO: notify over kafka?
1463 return nil
1464}
1465
khenaidoob9203542018-09-17 22:56:37 -04001466func funcName(f interface{}) string {
1467 p := reflect.ValueOf(f).Pointer()
1468 rf := runtime.FuncForPC(p)
1469 return rf.Name()
1470}
1471
npujar1d86a522019-11-14 17:11:16 +05301472// UpdateDeviceAttribute updates value of particular device attribute
1473func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceID string, attribute string, value interface{}) {
1474 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001475 agent.(*DeviceAgent).updateDeviceAttribute(attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001476 }
1477}
1478
npujar1d86a522019-11-14 17:11:16 +05301479// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
1480func (dMgr *DeviceManager) GetParentDeviceID(deviceID string) string {
1481 if device, _ := dMgr.GetDevice(deviceID); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001482 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001483 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001484 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001485 return ""
khenaidoob9203542018-09-17 22:56:37 -04001486}
serkant.uluderya334479d2019-04-10 08:26:15 -07001487
1488func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1489 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1490 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1491 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1492 var res interface{}
1493 if agent := dMgr.getDeviceAgent(simulatereq.Id); agent != nil {
1494 res = agent.simulateAlarm(ctx, simulatereq)
1495 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1496 }
1497 //TODO CLI always get successful response
1498 sendResponse(ctx, ch, res)
1499}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001500
npujar1d86a522019-11-14 17:11:16 +05301501func (dMgr *DeviceManager) updateDeviceReason(deviceID string, reason string) error {
1502 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
1503 if agent := dMgr.getDeviceAgent(deviceID); agent != nil {
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001504 return agent.updateDeviceReason(reason)
1505 }
npujar1d86a522019-11-14 17:11:16 +05301506 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001507}