blob: 6d871434954c95d9843038f36c537e8975e21dd0 [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"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080028 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
29 "github.com/opencord/voltha-lib-go/v3/pkg/log"
30 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
31 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
32 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
33 "github.com/opencord/voltha-protos/v3/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
npujar467fe752020-01-16 20:17:45 +053047 kafkaICProxy kafka.InterContainerProxy
khenaidoo4c9e5592019-09-09 16:20:41 -040048 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
npujar467fe752020-01-16 20:17:45 +0530119func (dMgr *DeviceManager) getDeviceAgent(ctx context.Context, deviceID string) *DeviceAgent {
npujar1d86a522019-11-14 17:11:16 +0530120 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
npujar467fe752020-01-16 20:17:45 +0530125 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530126 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() {
npujar467fe752020-01-16 20:17:45 +0530133 _, err = dMgr.core.deviceOwnership.OwnedByMe(ctx, &utils.DeviceID{ID: deviceID})
npujar1d86a522019-11-14 17:11:16 +0530134 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{}) {
npujar467fe752020-01-16 20:17:45 +0530158 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530159 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{}
npujar467fe752020-01-16 20:17:45 +0530189 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400190 res = agent.enableDevice(ctx)
191 log.Debugw("EnableDevice-result", log.Fields{"result": res})
Hardik Windlassb9cfcb12020-02-03 15:59:46 +0000192 } else {
193 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400194 }
195
196 sendResponse(ctx, ch, res)
197}
198
khenaidoo92e62c52018-10-03 14:02:54 -0400199func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
200 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400201 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530202 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400203 res = agent.disableDevice(ctx)
204 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400205 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400206 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400207 }
khenaidoo92e62c52018-10-03 14:02:54 -0400208
209 sendResponse(ctx, ch, res)
210}
211
khenaidoo4d4802d2018-10-04 21:59:49 -0400212func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
213 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
214 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530215 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400216 res = agent.rebootDevice(ctx)
217 log.Debugw("rebootDevice-result", log.Fields{"result": res})
218 } else {
219 res = status.Errorf(codes.NotFound, "%s", id.Id)
220 }
221 sendResponse(ctx, ch, res)
222}
223
224func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
225 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
226 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530227 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400228 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400229 log.Debugw("deleteDevice-result", log.Fields{"result": res})
230 } else {
231 res = status.Errorf(codes.NotFound, "%s", id.Id)
232 }
233 sendResponse(ctx, ch, res)
234}
235
khenaidoo6d62c002019-05-15 21:57:03 -0400236// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
237// This function is called only in the Core that does not own this device. In the Core that owns this device then a
238// deletion deletion also includes removal of any reference of this device.
npujar467fe752020-01-16 20:17:45 +0530239func (dMgr *DeviceManager) stopManagingDevice(ctx context.Context, id string) {
khenaidoo6d62c002019-05-15 21:57:03 -0400240 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
241 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530242 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400243 // stop managing the logical device
npujar467fe752020-01-16 20:17:45 +0530244 ldeviceID := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
npujar1d86a522019-11-14 17:11:16 +0530245 if ldeviceID != "" { // Can happen if logical device agent was already stopped
246 err := dMgr.core.deviceOwnership.AbandonDevice(ldeviceID)
247 if err != nil {
248 log.Errorw("unable-to-abandon-the-device", log.Fields{"error": err})
249 }
khenaidoo6d62c002019-05-15 21:57:03 -0400250 }
khenaidoo49085352020-01-13 19:15:43 -0500251 // We do not need to stop the child devices as this is taken care by the state machine.
khenaidoo6d62c002019-05-15 21:57:03 -0400252 }
npujar467fe752020-01-16 20:17:45 +0530253 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
254 agent.stop(ctx)
khenaidoo4c9e5592019-09-09 16:20:41 -0400255 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400256 // Abandon the device ownership
npujar1d86a522019-11-14 17:11:16 +0530257 err := dMgr.core.deviceOwnership.AbandonDevice(id)
258 if err != nil {
259 log.Errorw("unable-to-abandon-device", log.Fields{"error": err})
260 }
khenaidoo6d62c002019-05-15 21:57:03 -0400261 }
262 }
263}
264
npujar1d86a522019-11-14 17:11:16 +0530265// RunPostDeviceDelete removes any reference of this device
npujar467fe752020-01-16 20:17:45 +0530266func (dMgr *DeviceManager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -0400267 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530268 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400269 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400270}
271
khenaidoo297cd252019-02-07 22:10:23 -0500272// GetDevice will returns a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530273func (dMgr *DeviceManager) GetDevice(ctx context.Context, id string) (*voltha.Device, error) {
khenaidoo19d7b632018-10-30 10:49:50 -0400274 log.Debugw("GetDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530275 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500276 return agent.getDevice(), nil
khenaidoo92e62c52018-10-03 14:02:54 -0400277 }
278 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400279}
280
npujar1d86a522019-11-14 17:11:16 +0530281// GetChildDevice will return a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530282func (dMgr *DeviceManager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
npujar1d86a522019-11-14 17:11:16 +0530283 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
284 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500285
286 var parentDevice *voltha.Device
287 var err error
npujar467fe752020-01-16 20:17:45 +0530288 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500289 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
290 }
291 var childDeviceIds []string
292 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
293 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
294 }
295 if len(childDeviceIds) == 0 {
npujar1d86a522019-11-14 17:11:16 +0530296 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
297 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500298 }
299
300 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530301 for _, childDeviceID := range childDeviceIds {
302 var found bool
npujar467fe752020-01-16 20:17:45 +0530303 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500304
npujar1d86a522019-11-14 17:11:16 +0530305 foundOnuID := false
306 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500307 if searchDevice.ParentPortNo == uint32(parentPortNo) {
npujar1d86a522019-11-14 17:11:16 +0530308 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
309 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500310 }
311 }
312
313 foundSerialNumber := false
314 if searchDevice.SerialNumber == serialNumber {
315 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
316 foundSerialNumber = true
317 }
318
319 // if both onuId and serialNumber are provided both must be true for the device to be found
320 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530321 if onuID > 0 && serialNumber != "" {
322 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500323 } else {
npujar1d86a522019-11-14 17:11:16 +0530324 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500325 }
326
npujar1d86a522019-11-14 17:11:16 +0530327 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500328 foundChildDevice = searchDevice
329 break
330 }
331 }
332 }
333
334 if foundChildDevice != nil {
335 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
336 return foundChildDevice, nil
337 }
338
339 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530340 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
341 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500342}
343
npujar1d86a522019-11-14 17:11:16 +0530344// GetChildDeviceWithProxyAddress will return a device based on proxy address
npujar467fe752020-01-16 20:17:45 +0530345func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500346 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
347
348 var parentDevice *voltha.Device
349 var err error
npujar467fe752020-01-16 20:17:45 +0530350 if parentDevice, err = dMgr.GetDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500351 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
352 }
353 var childDeviceIds []string
354 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
355 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
356 }
357 if len(childDeviceIds) == 0 {
358 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
359 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
360 }
361
362 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530363 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530364 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500365 if searchDevice.ProxyAddress == proxyAddress {
366 foundChildDevice = searchDevice
367 break
368 }
369 }
370 }
371
372 if foundChildDevice != nil {
373 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
374 return foundChildDevice, nil
375 }
376
377 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
378 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
379}
380
npujar1d86a522019-11-14 17:11:16 +0530381// IsDeviceInCache returns true if device is found in the map
khenaidoo297cd252019-02-07 22:10:23 -0500382func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400383 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500384 return exist
385}
386
npujar1d86a522019-11-14 17:11:16 +0530387// IsRootDevice returns true if root device is found in the map
khenaidoo19d7b632018-10-30 10:49:50 -0400388func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400389 dMgr.lockRootDeviceMap.RLock()
390 defer dMgr.lockRootDeviceMap.RUnlock()
391 if exist := dMgr.rootDevices[id]; exist {
392 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400393 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400394 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400395}
396
Stephane Barbarieaa467942019-02-06 14:09:44 -0500397// ListDevices retrieves the latest devices from the data model
npujar467fe752020-01-16 20:17:45 +0530398func (dMgr *DeviceManager) ListDevices(ctx context.Context) (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400399 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400400 result := &voltha.Devices{}
npujar467fe752020-01-16 20:17:45 +0530401 devices, err := dMgr.clusterDataProxy.List(ctx, "/devices", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530402 if err != nil {
403 log.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
404 return nil, err
405 }
406 if devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500407 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500408 // If device is not in memory then set it up
409 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400410 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400411 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530412 if _, err := agent.start(ctx, nil); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500413 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
npujar467fe752020-01-16 20:17:45 +0530414 agent.stop(ctx)
khenaidoo297cd252019-02-07 22:10:23 -0500415 } else {
416 dMgr.addDeviceAgentToMap(agent)
417 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500418 }
419 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400420 }
421 }
khenaidoo6d62c002019-05-15 21:57:03 -0400422 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400423 return result, nil
424}
425
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530426//isParentDeviceExist checks whether device is already preprovisioned.
npujar467fe752020-01-16 20:17:45 +0530427func (dMgr *DeviceManager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530428 hostPort := newDevice.GetHostAndPort()
npujar467fe752020-01-16 20:17:45 +0530429 devices, err := dMgr.clusterDataProxy.List(ctx, "/devices", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530430 if err != nil {
431 log.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
432 return false, err
433 }
434 if devices != nil {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530435 for _, device := range devices.([]interface{}) {
436 if !device.(*voltha.Device).Root {
437 continue
438 }
439 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530440 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530441 }
442 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530443 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530444 }
445 }
446 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530447 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530448}
449
khenaidoo6d62c002019-05-15 21:57:03 -0400450//getDeviceFromModelretrieves the device data from the model.
npujar467fe752020-01-16 20:17:45 +0530451func (dMgr *DeviceManager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
452 device, err := dMgr.clusterDataProxy.Get(ctx, "/devices/"+deviceID, 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530453 if err != nil {
454 log.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
455 return nil, err
456 }
457 if device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400458 if d, ok := device.(*voltha.Device); ok {
459 return d, nil
460 }
461 }
npujar1d86a522019-11-14 17:11:16 +0530462 return nil, status.Error(codes.NotFound, deviceID)
khenaidoo6d62c002019-05-15 21:57:03 -0400463}
464
npujar1d86a522019-11-14 17:11:16 +0530465// loadDevice loads the deviceID in memory, if not present
npujar467fe752020-01-16 20:17:45 +0530466func (dMgr *DeviceManager) loadDevice(ctx context.Context, deviceID string) (*DeviceAgent, error) {
npujar1d86a522019-11-14 17:11:16 +0530467 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500468 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
469 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400470 var err error
471 var device *voltha.Device
472 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530473 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
474 if !dMgr.IsDeviceInCache(deviceID) {
475 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400476 dMgr.devicesLoadingLock.Unlock()
477 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530478 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530479 log.Debugw("loading-device", log.Fields{"deviceId": deviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400480 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530481 if _, err = agent.start(ctx, nil); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530482 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
npujar467fe752020-01-16 20:17:45 +0530483 agent.stop(ctx)
khenaidoo4c9e5592019-09-09 16:20:41 -0400484 } else {
485 dMgr.addDeviceAgentToMap(agent)
486 }
487 } else {
npujar1d86a522019-11-14 17:11:16 +0530488 log.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400489 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400490 // announce completion of task to any number of waiting channels
491 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530492 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400493 for _, ch := range v {
494 close(ch)
495 }
npujar1d86a522019-11-14 17:11:16 +0530496 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400497 }
498 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400499 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400500 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500501 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400502 } else {
503 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530504 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400505 dMgr.devicesLoadingLock.Unlock()
506 // Wait for the channel to be closed, implying the process loading this device is done.
507 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500508 }
npujar1d86a522019-11-14 17:11:16 +0530509 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400510 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500511 }
npujar1d86a522019-11-14 17:11:16 +0530512 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500513}
514
515// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
npujar467fe752020-01-16 20:17:45 +0530516func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
khenaidoo297cd252019-02-07 22:10:23 -0500517 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
518 if device.Root {
519 // Scenario A
520 if device.ParentId != "" {
521 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530522 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500523 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
524 }
525 } else {
526 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
527 }
528 // Load all child devices, if needed
529 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530530 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530531 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530532 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500533 return err
534 }
535 }
536 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
537 } else {
538 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
539 }
540 }
541 return nil
542}
543
544// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
545// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
546// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
547// and the proceed with the request.
npujar467fe752020-01-16 20:17:45 +0530548func (dMgr *DeviceManager) load(ctx context.Context, deviceID string) error {
khenaidoo297cd252019-02-07 22:10:23 -0500549 log.Debug("load...")
550 // First load the device - this may fail in case the device was deleted intentionally by the other core
551 var dAgent *DeviceAgent
552 var err error
npujar467fe752020-01-16 20:17:45 +0530553 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500554 return err
555 }
556 // Get the loaded device details
khenaidoo6e55d9e2019-12-12 18:26:26 -0500557 device := dAgent.getDevice()
khenaidoo297cd252019-02-07 22:10:23 -0500558
559 // If the device is in Pre-provisioning or deleted state stop here
560 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
561 return nil
562 }
563
564 // Now we face two scenarios
565 if device.Root {
566 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530567 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530568 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500569 return err
570 }
npujar1d86a522019-11-14 17:11:16 +0530571 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500572 } else {
573 // Scenario B - use the parentId of that device (root device) to trigger the loading
574 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530575 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500576 }
577 }
578 return nil
579}
580
khenaidoo7ccedd52018-12-14 16:48:54 -0500581// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
582func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
583 log.Debug("ListDeviceIDs")
584 // Report only device IDs that are in the device agent map
585 return dMgr.listDeviceIdsFromMap(), nil
586}
587
khenaidoo4c9e5592019-09-09 16:20:41 -0400588//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
589//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500590func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400591 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500592 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400593 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500594 toReconcile := len(ids.Items)
595 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400596 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500597 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530598 if err = dMgr.load(ctx, id.Id); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400599 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
600 } else {
npujar1d86a522019-11-14 17:11:16 +0530601 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500602 }
603 }
604 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400605 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500606 }
607 } else {
608 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
609 }
610 sendResponse(ctx, ch, res)
611}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500612
khenaidooba6b6c42019-08-02 09:11:56 -0400613// isOkToReconcile validates whether a device is in the correct status to be reconciled
614func isOkToReconcile(device *voltha.Device) bool {
615 if device == nil {
616 return false
617 }
618 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
619}
620
621// adapterRestarted is invoked whenever an adapter is restarted
npujar467fe752020-01-16 20:17:45 +0530622func (dMgr *DeviceManager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
khenaidooba6b6c42019-08-02 09:11:56 -0400623 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
624
625 // Let's reconcile the device managed by this Core only
626 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
627 if len(rootDeviceIds) == 0 {
628 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
629 return nil
630 }
631
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500632 responses := make([]utils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530633 for _, rootDeviceID := range rootDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530634 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400635 if rootDevice.Adapter == adapter.Id {
636 if isOkToReconcile(rootDevice) {
637 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530638 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400639 } else {
640 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
641 }
642 } else { // Should we be reconciling the root's children instead?
643 childManagedByAdapter:
644 for _, port := range rootDevice.Ports {
645 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530646 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400647 if childDevice.Adapter == adapter.Id {
648 if isOkToReconcile(childDevice) {
649 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530650 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400651 } else {
652 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
653 }
654 } else {
655 // All child devices under a parent device are typically managed by the same adapter type.
656 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
657 break childManagedByAdapter
658 }
659 }
660 }
661 }
662 }
663 }
664 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500665 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400666 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500667 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400668 return status.Errorf(codes.Aborted, "errors-%s", res)
669 }
670 } else {
671 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
672 }
673 return nil
674}
675
npujar467fe752020-01-16 20:17:45 +0530676func (dMgr *DeviceManager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400677 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
678 // 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 +0530679 // 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 -0400680 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500681 response := utils.NewResponse()
khenaidooba6b6c42019-08-02 09:11:56 -0400682 go func(device *voltha.Device) {
npujar467fe752020-01-16 20:17:45 +0530683 if err := dMgr.adapterProxy.ReconcileDevice(ctx, device); err != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400684 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500685 response.Error(status.Errorf(codes.Internal, "device: %s", device.Id))
khenaidooba6b6c42019-08-02 09:11:56 -0400686 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500687 response.Done()
khenaidooba6b6c42019-08-02 09:11:56 -0400688 }(device)
689
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500690 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400691}
692
npujar467fe752020-01-16 20:17:45 +0530693func (dMgr *DeviceManager) reconcileChildDevices(ctx context.Context, parentDeviceID string) error {
694 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500695 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400696 for _, port := range parentDevice.Ports {
697 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530698 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
699 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400700 }
701 }
702 }
703 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500704 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400705 return status.Errorf(codes.Aborted, "errors-%s", res)
706 }
707 }
708 return nil
709}
710
npujar467fe752020-01-16 20:17:45 +0530711func (dMgr *DeviceManager) updateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700712 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530713 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
714 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400715 }
716 return status.Errorf(codes.NotFound, "%s", device.Id)
717}
718
npujar467fe752020-01-16 20:17:45 +0530719func (dMgr *DeviceManager) addPort(ctx context.Context, deviceID string, port *voltha.Port) error {
720 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530721 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530722 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400723 return err
724 }
725 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530726 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400727 for _, peerPort := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530728 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
729 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400730 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
731 return err
732 }
733 }
734 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400735 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
736 // then a logical port will be added to the logical device and the device graph generated. If the port is a
737 // PON port then only the device graph will be generated.
npujar467fe752020-01-16 20:17:45 +0530738 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530739 go func() {
npujar467fe752020-01-16 20:17:45 +0530740 err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port)
npujar1d86a522019-11-14 17:11:16 +0530741 if err != nil {
742 log.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
743 }
744 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400745 } else {
npujar1d86a522019-11-14 17:11:16 +0530746 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400747 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400748 }
khenaidoo92e62c52018-10-03 14:02:54 -0400749 return nil
khenaidoob9203542018-09-17 22:56:37 -0400750 }
npujar1d86a522019-11-14 17:11:16 +0530751 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400752}
753
npujar467fe752020-01-16 20:17:45 +0530754func (dMgr *DeviceManager) deletePeerPorts(ctx context.Context, fromDeviceID string, deviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530755 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceID, "deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530756 if agent := dMgr.getDeviceAgent(ctx, fromDeviceID); agent != nil {
757 return agent.deletePeerPorts(ctx, deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400758 }
npujar1d86a522019-11-14 17:11:16 +0530759 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400760}
761
npujar467fe752020-01-16 20:17:45 +0530762func (dMgr *DeviceManager) addFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Esin Karaman09959ae2019-11-29 13:59:58 +0000763 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530764 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
765 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400766 }
npujar1d86a522019-11-14 17:11:16 +0530767 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400768}
769
npujar467fe752020-01-16 20:17:45 +0530770func (dMgr *DeviceManager) deleteFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530771 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530772 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
773 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400774 }
npujar1d86a522019-11-14 17:11:16 +0530775 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400776}
777
npujar467fe752020-01-16 20:17:45 +0530778func (dMgr *DeviceManager) updateFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530779 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530780 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
781 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400782 }
npujar1d86a522019-11-14 17:11:16 +0530783 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400784}
785
khenaidoob3127472019-07-24 21:04:55 -0400786// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
787// following a user action
788func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
789 var res interface{}
790 if pmConfigs.Id == "" {
791 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
npujar467fe752020-01-16 20:17:45 +0530792 } else if agent := dMgr.getDeviceAgent(ctx, pmConfigs.Id); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400793 res = agent.updatePmConfigs(ctx, pmConfigs)
794 } else {
795 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
796 }
797 sendResponse(ctx, ch, res)
798}
799
800// initPmConfigs initialize the pm configs as defined by the adapter.
npujar467fe752020-01-16 20:17:45 +0530801func (dMgr *DeviceManager) initPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400802 if pmConfigs.Id == "" {
803 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
804 }
npujar467fe752020-01-16 20:17:45 +0530805 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
806 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400807 }
npujar1d86a522019-11-14 17:11:16 +0530808 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400809}
810
npujar1d86a522019-11-14 17:11:16 +0530811func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
npujar467fe752020-01-16 20:17:45 +0530812 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400813 return agent.listPmConfigs(ctx)
814 }
npujar1d86a522019-11-14 17:11:16 +0530815 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400816}
817
npujar1d86a522019-11-14 17:11:16 +0530818func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
819 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530820 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400821 return agent.getSwitchCapability(ctx)
822 }
npujar1d86a522019-11-14 17:11:16 +0530823 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400824}
825
npujar1d86a522019-11-14 17:11:16 +0530826func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
827 log.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530828 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400829 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400830 }
npujar1d86a522019-11-14 17:11:16 +0530831 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400832}
833
npujar1d86a522019-11-14 17:11:16 +0530834func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
835 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530836 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400837 return agent.getPortCapability(ctx, portNo)
838 }
npujar1d86a522019-11-14 17:11:16 +0530839 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400840}
841
npujar467fe752020-01-16 20:17:45 +0530842func (dMgr *DeviceManager) updateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530843 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530844 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
845 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400846 }
npujar1d86a522019-11-14 17:11:16 +0530847 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400848}
849
npujar467fe752020-01-16 20:17:45 +0530850func (dMgr *DeviceManager) updateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530851 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400852 var parentDevice *voltha.Device
853 var err error
npujar467fe752020-01-16 20:17:45 +0530854 if parentDevice, err = dMgr.GetDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400855 return status.Errorf(codes.Aborted, "%s", err.Error())
856 }
857 var childDeviceIds []string
858 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
859 return status.Errorf(codes.Aborted, "%s", err.Error())
860 }
861 if len(childDeviceIds) == 0 {
862 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
863 }
npujar1d86a522019-11-14 17:11:16 +0530864 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530865 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
866 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530867 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400868 }
869 }
870 }
871 return nil
872}
873
npujar467fe752020-01-16 20:17:45 +0530874func (dMgr *DeviceManager) updatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530875 log.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530876 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
877 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530878 log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400879 return err
880 }
881 // Notify the logical device manager to change the port state
npujar1d86a522019-11-14 17:11:16 +0530882 go func() {
npujar467fe752020-01-16 20:17:45 +0530883 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
npujar1d86a522019-11-14 17:11:16 +0530884 if err != nil {
885 log.Errorw("unable-to-update-port-state", log.Fields{"error": err})
886 }
887 }()
khenaidoob9203542018-09-17 22:56:37 -0400888 }
npujar1d86a522019-11-14 17:11:16 +0530889 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400890}
891
npujar467fe752020-01-16 20:17:45 +0530892func (dMgr *DeviceManager) deleteAllPorts(ctx context.Context, deviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530893 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530894 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
895 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400896 return err
897 }
898 // Notify the logical device manager to remove all logical ports, if needed.
899 // At this stage the device itself may gave been deleted already at a deleteAllPorts
900 // typically is part of a device deletion phase.
npujar467fe752020-01-16 20:17:45 +0530901 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530902 go func() {
npujar467fe752020-01-16 20:17:45 +0530903 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530904 if err != nil {
905 log.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
906 }
907 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400908 } else {
npujar1d86a522019-11-14 17:11:16 +0530909 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400910 return err
911 }
912 return nil
913 }
npujar1d86a522019-11-14 17:11:16 +0530914 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400915}
916
khenaidoo3ab34882019-05-02 21:33:30 -0400917//updatePortsState updates all ports on the device
npujar467fe752020-01-16 20:17:45 +0530918func (dMgr *DeviceManager) updatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530919 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400920
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800921 var adminState voltha.AdminState_Types
npujar467fe752020-01-16 20:17:45 +0530922 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400923 switch state {
924 case voltha.OperStatus_ACTIVE:
925 adminState = voltha.AdminState_ENABLED
npujar467fe752020-01-16 20:17:45 +0530926 if err := agent.enablePorts(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530927 log.Warnw("enable-all-ports-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400928 return err
929 }
930 case voltha.OperStatus_UNKNOWN:
931 adminState = voltha.AdminState_DISABLED
npujar467fe752020-01-16 20:17:45 +0530932 if err := agent.disablePorts(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530933 log.Warnw("disable-all-ports-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400934 return err
935 }
936 default:
937 return status.Error(codes.Unimplemented, "state-change-not-implemented")
938 }
939 // Notify the logical device about the state change
npujar467fe752020-01-16 20:17:45 +0530940 device, err := dMgr.GetDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530941 if err != nil {
942 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400943 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400944 }
npujar467fe752020-01-16 20:17:45 +0530945 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, adminState); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530946 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
947 return err
948 }
949 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400950 }
npujar1d86a522019-11-14 17:11:16 +0530951 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400952}
953
npujar467fe752020-01-16 20:17:45 +0530954func (dMgr *DeviceManager) childDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530955 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
956 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 -0700957
npujar1d86a522019-11-14 17:11:16 +0530958 if deviceType == "" && vendorID != "" {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700959 log.Debug("device-type-is-nil-fetching-device-type")
npujar467fe752020-01-16 20:17:45 +0530960 deviceTypesIf, err := dMgr.adapterMgr.clusterDataProxy.List(ctx, "/device_types", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530961 if err != nil {
962 log.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
963 return nil, err
964 }
965 if deviceTypesIf != nil {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700966 OLoop:
967 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
968 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
969 for _, v := range dType.VendorIds {
npujar1d86a522019-11-14 17:11:16 +0530970 if v == vendorID {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700971 deviceType = dType.Adapter
972 break OLoop
973 }
974 }
975 }
976 }
977 }
978 }
979 //if no match found for the vendorid,report adapter with the custom error message
980 if deviceType == "" {
npujar1d86a522019-11-14 17:11:16 +0530981 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
982 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700983 }
khenaidoob9203542018-09-17 22:56:37 -0400984
985 // Create the ONU device
986 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400987 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530988 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400989 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530990 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500991 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400992 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400993
994 //Get parent device type
npujar467fe752020-01-16 20:17:45 +0530995 parent, err := dMgr.GetDevice(ctx, parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400996 if err != nil {
npujar1d86a522019-11-14 17:11:16 +0530997 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceID})
998 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400999 }
1000
npujar467fe752020-01-16 20:17:45 +05301001 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
npujar1d86a522019-11-14 17:11:16 +05301002 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001003 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001004 }
1005
npujar1d86a522019-11-14 17:11:16 +05301006 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: parent.Type, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001007
1008 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -04001009 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -04001010 dMgr.addDeviceAgentToMap(agent)
npujar467fe752020-01-16 20:17:45 +05301011 childDevice, err = agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001012 if err != nil {
1013 log.Error("error-starting-child")
1014 return nil, err
1015 }
khenaidoob9203542018-09-17 22:56:37 -04001016
khenaidoo09771ef2019-10-11 14:25:02 -04001017 // Since this Core has handled this request then it therefore owns this child device. Set the
1018 // ownership of this device to this Core
npujar467fe752020-01-16 20:17:45 +05301019 _, err = dMgr.core.deviceOwnership.OwnedByMe(ctx, &utils.DeviceID{ID: agent.deviceID})
npujar1d86a522019-11-14 17:11:16 +05301020 if err != nil {
1021 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
1022 }
khenaidoo09771ef2019-10-11 14:25:02 -04001023
khenaidoob9203542018-09-17 22:56:37 -04001024 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301025 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301026 go func() {
npujar467fe752020-01-16 20:17:45 +05301027 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301028 if err != nil {
1029 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1030 }
1031 }()
khenaidoob9203542018-09-17 22:56:37 -04001032 }
1033
khenaidoo79232702018-12-04 11:00:41 -05001034 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301035 go func() {
1036 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1037 if err != nil {
1038 log.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
1039 }
1040 }()
khenaidoo79232702018-12-04 11:00:41 -05001041
Scott Baker80678602019-11-14 16:57:36 -08001042 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001043}
1044
npujar467fe752020-01-16 20:17:45 +05301045func (dMgr *DeviceManager) processTransition(ctx context.Context, previous *voltha.Device, current *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001046 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -04001047 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
1048 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -05001049 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001050 return nil
khenaidoob9203542018-09-17 22:56:37 -04001051 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001052 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -04001053 for _, handler := range handlers {
1054 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
npujar467fe752020-01-16 20:17:45 +05301055 if err := handler(ctx, current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -04001056 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001057 return err
1058 }
1059 }
khenaidoob9203542018-09-17 22:56:37 -04001060 return nil
1061}
1062
npujar467fe752020-01-16 20:17:45 +05301063func (dMgr *DeviceManager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
npujar1d86a522019-11-14 17:11:16 +05301064 log.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301065 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1066 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001067 }
npujar1d86a522019-11-14 17:11:16 +05301068 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001069}
1070
npujar1d86a522019-11-14 17:11:16 +05301071// PacketIn receives packet from adapter
npujar467fe752020-01-16 20:17:45 +05301072func (dMgr *DeviceManager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
npujar1d86a522019-11-14 17:11:16 +05301073 log.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001074 // Get the logical device Id based on the deviceId
1075 var device *voltha.Device
1076 var err error
npujar467fe752020-01-16 20:17:45 +05301077 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301078 log.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001079 return err
1080 }
khenaidoo43c82122018-11-22 18:38:28 -05001081 if !device.Root {
npujar1d86a522019-11-14 17:11:16 +05301082 log.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
1083 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001084 }
1085
npujar467fe752020-01-16 20:17:45 +05301086 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001087 return err
1088 }
1089 return nil
1090}
1091
npujar467fe752020-01-16 20:17:45 +05301092func (dMgr *DeviceManager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
npujar1d86a522019-11-14 17:11:16 +05301093 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301094 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1095 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001096 }
1097 return status.Errorf(codes.NotFound, "%s", device.Id)
1098}
1099
npujar1d86a522019-11-14 17:11:16 +05301100// CreateLogicalDevice creates logical device in core
npujar467fe752020-01-16 20:17:45 +05301101func (dMgr *DeviceManager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001102 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001103 // Verify whether the logical device has already been created
1104 if cDevice.ParentId != "" {
1105 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1106 return nil
1107 }
khenaidoob9203542018-09-17 22:56:37 -04001108 var err error
npujar467fe752020-01-16 20:17:45 +05301109 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001110 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1111 return err
1112 }
khenaidoob9203542018-09-17 22:56:37 -04001113 return nil
1114}
1115
npujar1d86a522019-11-14 17:11:16 +05301116// DeleteLogicalDevice deletes logical device from core
npujar467fe752020-01-16 20:17:45 +05301117func (dMgr *DeviceManager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001118 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001119 var err error
npujar467fe752020-01-16 20:17:45 +05301120 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001121 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1122 return err
1123 }
1124 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301125 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301126 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001127 return nil
1128}
1129
npujar1d86a522019-11-14 17:11:16 +05301130// DeleteLogicalPort removes the logical port associated with a device
npujar467fe752020-01-16 20:17:45 +05301131func (dMgr *DeviceManager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001132 log.Info("deleteLogicalPort")
1133 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001134 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301135 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301136 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001137 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001138 return err
1139 }
npujar467fe752020-01-16 20:17:45 +05301140 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001141 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001142 return err
1143 }
khenaidoo92e62c52018-10-03 14:02:54 -04001144 return nil
1145}
1146
npujar1d86a522019-11-14 17:11:16 +05301147// DeleteLogicalPorts removes the logical ports associated with that deviceId
npujar467fe752020-01-16 20:17:45 +05301148func (dMgr *DeviceManager) DeleteLogicalPorts(ctx context.Context, device *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001149 log.Info("deleteLogicalPorts")
npujar467fe752020-01-16 20:17:45 +05301150 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, device.Id); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -04001151 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1152 return err
1153 }
1154 return nil
1155}
1156
npujar467fe752020-01-16 20:17:45 +05301157func (dMgr *DeviceManager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001158 // Sanity check
1159 if childDevice.Root {
1160 // childDevice is the parent device
1161 return childDevice
1162 }
npujar467fe752020-01-16 20:17:45 +05301163 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001164 return parentDevice
1165}
1166
khenaidoo0a822f92019-05-08 15:15:57 -04001167//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1168//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar467fe752020-01-16 20:17:45 +05301169func (dMgr *DeviceManager) childDevicesLost(ctx context.Context, parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001170 log.Debug("childDevicesLost")
1171 var err error
1172 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301173 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301174 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001175 return err
1176 }
npujar467fe752020-01-16 20:17:45 +05301177 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001178}
1179
1180//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1181// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar467fe752020-01-16 20:17:45 +05301182func (dMgr *DeviceManager) childDevicesDetected(ctx context.Context, parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001183 log.Debug("childDevicesDetected")
1184 var err error
1185 var parentDevice *voltha.Device
1186 var childDeviceIds []string
1187
npujar467fe752020-01-16 20:17:45 +05301188 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301189 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001190 return err
1191 }
1192
1193 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1194 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1195 }
1196 if len(childDeviceIds) == 0 {
1197 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1198 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001199 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301200 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301201 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001202 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301203 go func() {
npujar467fe752020-01-16 20:17:45 +05301204 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301205 if err != nil {
1206 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1207 }
1208 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001209 } else {
npujar1d86a522019-11-14 17:11:16 +05301210 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
1211 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001212 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001213 }
1214 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001215 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001216 return err
1217 }
1218 return nil
1219}
1220
khenaidoo4d4802d2018-10-04 21:59:49 -04001221/*
1222All the functions below are callback functions where they are invoked with the latest and previous data. We can
1223therefore use the data as is without trying to get the latest from the model.
1224*/
1225
khenaidoo0a822f92019-05-08 15:15:57 -04001226//DisableAllChildDevices is invoked as a callback when the parent device is disabled
npujar467fe752020-01-16 20:17:45 +05301227func (dMgr *DeviceManager) DisableAllChildDevices(ctx context.Context, parentDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001228 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001229 var childDeviceIds []string
1230 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001231 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1232 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001233 }
1234 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001235 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001236 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001237 allChildDisable := true
npujar1d86a522019-11-14 17:11:16 +05301238 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301239 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1240 if err = agent.disableDevice(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301241 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001242 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001243 }
1244 }
1245 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001246 if !allChildDisable {
1247 return err
1248 }
khenaidoo92e62c52018-10-03 14:02:54 -04001249 return nil
1250}
1251
khenaidoo0a822f92019-05-08 15:15:57 -04001252//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
npujar467fe752020-01-16 20:17:45 +05301253func (dMgr *DeviceManager) DeleteAllChildDevices(ctx context.Context, parentDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001254 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001255 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001256 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001257 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1258 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001259 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001260 if len(childDeviceIds) == 0 {
1261 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1262 }
1263 allChildDeleted := true
npujar1d86a522019-11-14 17:11:16 +05301264 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301265 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1266 if err = agent.deleteDevice(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301267 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001268 allChildDeleted = false
khenaidoo4d4802d2018-10-04 21:59:49 -04001269 }
khenaidoo49085352020-01-13 19:15:43 -05001270 // No further action is required here. The deleteDevice will change the device state where the resulting
1271 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001272 }
1273 }
1274 if !allChildDeleted {
1275 return err
1276 }
1277 return nil
1278}
1279
1280//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1281func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1282 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001283 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001284 if parentDevice != nil {
1285 for _, port := range parentDevice.Ports {
1286 for _, peer := range port.Peers {
1287 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1288 }
khenaidoo92e62c52018-10-03 14:02:54 -04001289 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001290 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001291 }
1292 return childDeviceIds, nil
1293}
1294
khenaidoo297cd252019-02-07 22:10:23 -05001295//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar467fe752020-01-16 20:17:45 +05301296func (dMgr *DeviceManager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
npujar1d86a522019-11-14 17:11:16 +05301297 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301298 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001299 childDevices := make([]*voltha.Device, 0)
1300 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301301 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301302 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001303 childDevices = append(childDevices, d)
1304 }
1305 }
1306 }
1307 return &voltha.Devices{Items: childDevices}, nil
1308 }
npujar1d86a522019-11-14 17:11:16 +05301309 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001310}
1311
npujar1d86a522019-11-14 17:11:16 +05301312// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
npujar467fe752020-01-16 20:17:45 +05301313func (dMgr *DeviceManager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001314 log.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301315 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001316 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1317 return err
1318 }
1319 return nil
1320}
1321
khenaidoof5a5bfa2019-01-23 22:20:29 -05001322func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1323 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1324 var res interface{}
1325 var err error
npujar467fe752020-01-16 20:17:45 +05301326 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001327 if res, err = agent.downloadImage(ctx, img); err != nil {
1328 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1329 res = err
1330 }
1331 } else {
1332 res = status.Errorf(codes.NotFound, "%s", img.Id)
1333 }
1334 sendResponse(ctx, ch, res)
1335}
1336
1337func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1338 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1339 var res interface{}
1340 var err error
npujar467fe752020-01-16 20:17:45 +05301341 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001342 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1343 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1344 res = err
1345 }
1346 } else {
1347 res = status.Errorf(codes.NotFound, "%s", img.Id)
1348 }
1349 sendResponse(ctx, ch, res)
1350}
1351
1352func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1353 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1354 var res interface{}
1355 var err error
npujar467fe752020-01-16 20:17:45 +05301356 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001357 if res, err = agent.activateImage(ctx, img); err != nil {
1358 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1359 res = err
1360 }
1361 } else {
1362 res = status.Errorf(codes.NotFound, "%s", img.Id)
1363 }
1364 sendResponse(ctx, ch, res)
1365}
1366
1367func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1368 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1369 var res interface{}
1370 var err error
npujar467fe752020-01-16 20:17:45 +05301371 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001372 if res, err = agent.revertImage(ctx, img); err != nil {
1373 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1374 res = err
1375 }
1376 } else {
1377 res = status.Errorf(codes.NotFound, "%s", img.Id)
1378 }
1379 sendResponse(ctx, ch, res)
1380}
1381
1382func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1383 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1384 var res interface{}
1385 var err error
npujar467fe752020-01-16 20:17:45 +05301386 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001387 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1388 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1389 res = err
1390 }
1391 } else {
1392 res = status.Errorf(codes.NotFound, "%s", img.Id)
1393 }
1394 sendResponse(ctx, ch, res)
1395}
1396
npujar467fe752020-01-16 20:17:45 +05301397func (dMgr *DeviceManager) updateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001398 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301399 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1400 if err := agent.updateImageDownload(ctx, img); err != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001401 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1402 return err
1403 }
1404 } else {
1405 return status.Errorf(codes.NotFound, "%s", img.Id)
1406 }
1407 return nil
1408}
1409
1410func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1411 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301412 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001413 return agent.getImageDownload(ctx, img)
1414 }
1415 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1416}
1417
npujar1d86a522019-11-14 17:11:16 +05301418func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
1419 log.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301420 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301421 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001422 }
npujar1d86a522019-11-14 17:11:16 +05301423 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001424}
1425
npujar1d86a522019-11-14 17:11:16 +05301426// SetAdminStateToEnable sets admin state of device to enabled
npujar467fe752020-01-16 20:17:45 +05301427func (dMgr *DeviceManager) SetAdminStateToEnable(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001428 log.Info("SetAdminStateToEnable")
npujar467fe752020-01-16 20:17:45 +05301429 if agent := dMgr.getDeviceAgent(ctx, cDevice.Id); agent != nil {
1430 return agent.updateAdminState(ctx, voltha.AdminState_ENABLED)
khenaidoo0a822f92019-05-08 15:15:57 -04001431 }
1432 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1433}
1434
npujar1d86a522019-11-14 17:11:16 +05301435// NotifyInvalidTransition notifies about invalid transition
npujar467fe752020-01-16 20:17:45 +05301436func (dMgr *DeviceManager) NotifyInvalidTransition(ctx context.Context, pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001437 log.Errorw("NotifyInvalidTransition", log.Fields{
1438 "device": pcDevice.Id,
1439 "adminState": pcDevice.AdminState,
1440 "operState": pcDevice.OperStatus,
1441 "connState": pcDevice.ConnectStatus,
1442 })
khenaidoo0a822f92019-05-08 15:15:57 -04001443 //TODO: notify over kafka?
1444 return nil
1445}
1446
khenaidoob9203542018-09-17 22:56:37 -04001447func funcName(f interface{}) string {
1448 p := reflect.ValueOf(f).Pointer()
1449 rf := runtime.FuncForPC(p)
1450 return rf.Name()
1451}
1452
npujar1d86a522019-11-14 17:11:16 +05301453// UpdateDeviceAttribute updates value of particular device attribute
npujar467fe752020-01-16 20:17:45 +05301454func (dMgr *DeviceManager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301455 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
npujar467fe752020-01-16 20:17:45 +05301456 agent.(*DeviceAgent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001457 }
1458}
1459
npujar1d86a522019-11-14 17:11:16 +05301460// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +05301461func (dMgr *DeviceManager) GetParentDeviceID(ctx context.Context, deviceID string) string {
1462 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001463 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001464 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001465 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001466 return ""
khenaidoob9203542018-09-17 22:56:37 -04001467}
serkant.uluderya334479d2019-04-10 08:26:15 -07001468
1469func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1470 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1471 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1472 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1473 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301474 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001475 res = agent.simulateAlarm(ctx, simulatereq)
1476 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1477 }
1478 //TODO CLI always get successful response
1479 sendResponse(ctx, ch, res)
1480}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001481
npujar467fe752020-01-16 20:17:45 +05301482func (dMgr *DeviceManager) updateDeviceReason(ctx context.Context, deviceID string, reason string) error {
npujar1d86a522019-11-14 17:11:16 +05301483 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301484 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1485 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001486 }
npujar1d86a522019-11-14 17:11:16 +05301487 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001488}