blob: 98c45eb6d2bacd224ac4fc5a0a624c776a6cb1c4 [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
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800882 // Do this for NNI and UNIs only. PON ports are not known by logical device
883 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
884 go func() {
885 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
886 if err != nil {
887 // While we want to handle (catch) and log when
888 // an update to a port was not able to be
889 // propagated to the logical port, we can report
890 // it as a warning and not an error because it
891 // doesn't stop or modify processing.
892 // TODO: VOL-2707
893 log.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
894 }
895 }()
896 }
khenaidoob9203542018-09-17 22:56:37 -0400897 }
npujar1d86a522019-11-14 17:11:16 +0530898 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400899}
900
npujar467fe752020-01-16 20:17:45 +0530901func (dMgr *DeviceManager) deleteAllPorts(ctx context.Context, deviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530902 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530903 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
904 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400905 return err
906 }
907 // Notify the logical device manager to remove all logical ports, if needed.
908 // At this stage the device itself may gave been deleted already at a deleteAllPorts
909 // typically is part of a device deletion phase.
npujar467fe752020-01-16 20:17:45 +0530910 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530911 go func() {
npujar467fe752020-01-16 20:17:45 +0530912 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530913 if err != nil {
914 log.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
915 }
916 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400917 } else {
npujar1d86a522019-11-14 17:11:16 +0530918 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400919 return err
920 }
921 return nil
922 }
npujar1d86a522019-11-14 17:11:16 +0530923 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400924}
925
khenaidoo3ab34882019-05-02 21:33:30 -0400926//updatePortsState updates all ports on the device
npujar467fe752020-01-16 20:17:45 +0530927func (dMgr *DeviceManager) updatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530928 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400929
npujar467fe752020-01-16 20:17:45 +0530930 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400931 switch state {
932 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500933 if err := agent.updatePortsOperState(ctx, state); err != nil {
934 log.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400935 return err
936 }
937 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500938 if err := agent.updatePortsOperState(ctx, state); err != nil {
939 log.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400940 return err
941 }
942 default:
943 return status.Error(codes.Unimplemented, "state-change-not-implemented")
944 }
945 // Notify the logical device about the state change
npujar467fe752020-01-16 20:17:45 +0530946 device, err := dMgr.GetDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530947 if err != nil {
948 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400949 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400950 }
kesavandbc2d1622020-01-21 00:42:01 -0500951 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530952 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
953 return err
954 }
955 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400956 }
npujar1d86a522019-11-14 17:11:16 +0530957 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400958}
959
npujar467fe752020-01-16 20:17:45 +0530960func (dMgr *DeviceManager) childDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530961 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
962 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 -0700963
npujar1d86a522019-11-14 17:11:16 +0530964 if deviceType == "" && vendorID != "" {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700965 log.Debug("device-type-is-nil-fetching-device-type")
npujar467fe752020-01-16 20:17:45 +0530966 deviceTypesIf, err := dMgr.adapterMgr.clusterDataProxy.List(ctx, "/device_types", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530967 if err != nil {
968 log.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
969 return nil, err
970 }
971 if deviceTypesIf != nil {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700972 OLoop:
973 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
974 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
975 for _, v := range dType.VendorIds {
npujar1d86a522019-11-14 17:11:16 +0530976 if v == vendorID {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700977 deviceType = dType.Adapter
978 break OLoop
979 }
980 }
981 }
982 }
983 }
984 }
985 //if no match found for the vendorid,report adapter with the custom error message
986 if deviceType == "" {
npujar1d86a522019-11-14 17:11:16 +0530987 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
988 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700989 }
khenaidoob9203542018-09-17 22:56:37 -0400990
991 // Create the ONU device
992 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400993 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530994 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400995 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530996 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500997 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400998 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400999
1000 //Get parent device type
npujar467fe752020-01-16 20:17:45 +05301001 parent, err := dMgr.GetDevice(ctx, parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001002 if err != nil {
npujar1d86a522019-11-14 17:11:16 +05301003 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceID})
1004 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001005 }
1006
npujar467fe752020-01-16 20:17:45 +05301007 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
npujar1d86a522019-11-14 17:11:16 +05301008 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001009 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001010 }
1011
npujar1d86a522019-11-14 17:11:16 +05301012 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: parent.Type, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001013
1014 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -04001015 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -04001016 dMgr.addDeviceAgentToMap(agent)
npujar467fe752020-01-16 20:17:45 +05301017 childDevice, err = agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001018 if err != nil {
1019 log.Error("error-starting-child")
1020 return nil, err
1021 }
khenaidoob9203542018-09-17 22:56:37 -04001022
khenaidoo09771ef2019-10-11 14:25:02 -04001023 // Since this Core has handled this request then it therefore owns this child device. Set the
1024 // ownership of this device to this Core
npujar467fe752020-01-16 20:17:45 +05301025 _, err = dMgr.core.deviceOwnership.OwnedByMe(ctx, &utils.DeviceID{ID: agent.deviceID})
npujar1d86a522019-11-14 17:11:16 +05301026 if err != nil {
1027 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
1028 }
khenaidoo09771ef2019-10-11 14:25:02 -04001029
khenaidoob9203542018-09-17 22:56:37 -04001030 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301031 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301032 go func() {
npujar467fe752020-01-16 20:17:45 +05301033 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301034 if err != nil {
1035 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1036 }
1037 }()
khenaidoob9203542018-09-17 22:56:37 -04001038 }
1039
khenaidoo79232702018-12-04 11:00:41 -05001040 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301041 go func() {
1042 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1043 if err != nil {
1044 log.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
1045 }
1046 }()
khenaidoo79232702018-12-04 11:00:41 -05001047
Scott Baker80678602019-11-14 16:57:36 -08001048 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001049}
1050
npujar467fe752020-01-16 20:17:45 +05301051func (dMgr *DeviceManager) processTransition(ctx context.Context, previous *voltha.Device, current *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001052 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -04001053 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
1054 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -05001055 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001056 return nil
khenaidoob9203542018-09-17 22:56:37 -04001057 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001058 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -04001059 for _, handler := range handlers {
1060 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
npujar467fe752020-01-16 20:17:45 +05301061 if err := handler(ctx, current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -04001062 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001063 return err
1064 }
1065 }
khenaidoob9203542018-09-17 22:56:37 -04001066 return nil
1067}
1068
npujar467fe752020-01-16 20:17:45 +05301069func (dMgr *DeviceManager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
npujar1d86a522019-11-14 17:11:16 +05301070 log.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301071 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1072 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001073 }
npujar1d86a522019-11-14 17:11:16 +05301074 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001075}
1076
npujar1d86a522019-11-14 17:11:16 +05301077// PacketIn receives packet from adapter
npujar467fe752020-01-16 20:17:45 +05301078func (dMgr *DeviceManager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
npujar1d86a522019-11-14 17:11:16 +05301079 log.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001080 // Get the logical device Id based on the deviceId
1081 var device *voltha.Device
1082 var err error
npujar467fe752020-01-16 20:17:45 +05301083 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301084 log.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001085 return err
1086 }
khenaidoo43c82122018-11-22 18:38:28 -05001087 if !device.Root {
npujar1d86a522019-11-14 17:11:16 +05301088 log.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
1089 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001090 }
1091
npujar467fe752020-01-16 20:17:45 +05301092 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001093 return err
1094 }
1095 return nil
1096}
1097
npujar467fe752020-01-16 20:17:45 +05301098func (dMgr *DeviceManager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
npujar1d86a522019-11-14 17:11:16 +05301099 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301100 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1101 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001102 }
1103 return status.Errorf(codes.NotFound, "%s", device.Id)
1104}
1105
npujar1d86a522019-11-14 17:11:16 +05301106// CreateLogicalDevice creates logical device in core
npujar467fe752020-01-16 20:17:45 +05301107func (dMgr *DeviceManager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001108 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001109 // Verify whether the logical device has already been created
1110 if cDevice.ParentId != "" {
1111 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1112 return nil
1113 }
khenaidoob9203542018-09-17 22:56:37 -04001114 var err error
npujar467fe752020-01-16 20:17:45 +05301115 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001116 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1117 return err
1118 }
khenaidoob9203542018-09-17 22:56:37 -04001119 return nil
1120}
1121
npujar1d86a522019-11-14 17:11:16 +05301122// DeleteLogicalDevice deletes logical device from core
npujar467fe752020-01-16 20:17:45 +05301123func (dMgr *DeviceManager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001124 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001125 var err error
npujar467fe752020-01-16 20:17:45 +05301126 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001127 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1128 return err
1129 }
1130 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301131 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301132 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001133 return nil
1134}
1135
npujar1d86a522019-11-14 17:11:16 +05301136// DeleteLogicalPort removes the logical port associated with a device
npujar467fe752020-01-16 20:17:45 +05301137func (dMgr *DeviceManager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001138 log.Info("deleteLogicalPort")
1139 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001140 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301141 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301142 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001143 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001144 return err
1145 }
npujar467fe752020-01-16 20:17:45 +05301146 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001147 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001148 return err
1149 }
khenaidoo92e62c52018-10-03 14:02:54 -04001150 return nil
1151}
1152
npujar1d86a522019-11-14 17:11:16 +05301153// DeleteLogicalPorts removes the logical ports associated with that deviceId
npujar467fe752020-01-16 20:17:45 +05301154func (dMgr *DeviceManager) DeleteLogicalPorts(ctx context.Context, device *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001155 log.Info("deleteLogicalPorts")
npujar467fe752020-01-16 20:17:45 +05301156 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, device.Id); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -04001157 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1158 return err
1159 }
1160 return nil
1161}
1162
npujar467fe752020-01-16 20:17:45 +05301163func (dMgr *DeviceManager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001164 // Sanity check
1165 if childDevice.Root {
1166 // childDevice is the parent device
1167 return childDevice
1168 }
npujar467fe752020-01-16 20:17:45 +05301169 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001170 return parentDevice
1171}
1172
khenaidoo0a822f92019-05-08 15:15:57 -04001173//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1174//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar467fe752020-01-16 20:17:45 +05301175func (dMgr *DeviceManager) childDevicesLost(ctx context.Context, parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001176 log.Debug("childDevicesLost")
1177 var err error
1178 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301179 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301180 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001181 return err
1182 }
npujar467fe752020-01-16 20:17:45 +05301183 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001184}
1185
1186//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1187// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar467fe752020-01-16 20:17:45 +05301188func (dMgr *DeviceManager) childDevicesDetected(ctx context.Context, parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001189 log.Debug("childDevicesDetected")
1190 var err error
1191 var parentDevice *voltha.Device
1192 var childDeviceIds []string
1193
npujar467fe752020-01-16 20:17:45 +05301194 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301195 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001196 return err
1197 }
1198
1199 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1200 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1201 }
1202 if len(childDeviceIds) == 0 {
1203 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1204 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001205 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301206 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301207 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001208 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301209 go func() {
npujar467fe752020-01-16 20:17:45 +05301210 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301211 if err != nil {
1212 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1213 }
1214 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001215 } else {
npujar1d86a522019-11-14 17:11:16 +05301216 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
1217 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001218 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001219 }
1220 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001221 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001222 return err
1223 }
1224 return nil
1225}
1226
khenaidoo4d4802d2018-10-04 21:59:49 -04001227/*
1228All the functions below are callback functions where they are invoked with the latest and previous data. We can
1229therefore use the data as is without trying to get the latest from the model.
1230*/
1231
khenaidoo0a822f92019-05-08 15:15:57 -04001232//DisableAllChildDevices is invoked as a callback when the parent device is disabled
npujar467fe752020-01-16 20:17:45 +05301233func (dMgr *DeviceManager) DisableAllChildDevices(ctx context.Context, parentDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001234 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001235 var childDeviceIds []string
1236 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001237 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1238 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001239 }
1240 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001241 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001242 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001243 allChildDisable := true
npujar1d86a522019-11-14 17:11:16 +05301244 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301245 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1246 if err = agent.disableDevice(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301247 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001248 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001249 }
1250 }
1251 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001252 if !allChildDisable {
1253 return err
1254 }
khenaidoo92e62c52018-10-03 14:02:54 -04001255 return nil
1256}
1257
khenaidoo0a822f92019-05-08 15:15:57 -04001258//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
npujar467fe752020-01-16 20:17:45 +05301259func (dMgr *DeviceManager) DeleteAllChildDevices(ctx context.Context, parentDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001260 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001261 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001262 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001263 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1264 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001265 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001266 if len(childDeviceIds) == 0 {
1267 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1268 }
1269 allChildDeleted := true
npujar1d86a522019-11-14 17:11:16 +05301270 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301271 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1272 if err = agent.deleteDevice(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301273 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001274 allChildDeleted = false
khenaidoo4d4802d2018-10-04 21:59:49 -04001275 }
khenaidoo49085352020-01-13 19:15:43 -05001276 // No further action is required here. The deleteDevice will change the device state where the resulting
1277 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001278 }
1279 }
1280 if !allChildDeleted {
1281 return err
1282 }
1283 return nil
1284}
1285
Hardik Windlassc704def2020-02-26 18:23:19 +00001286//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
1287func (dMgr *DeviceManager) DeleteAllUNILogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
1288 log.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
1289 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, parentDevice); err != nil {
1290 return err
1291 }
1292 return nil
1293}
1294
khenaidoo4d4802d2018-10-04 21:59:49 -04001295//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1296func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1297 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001298 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001299 if parentDevice != nil {
1300 for _, port := range parentDevice.Ports {
1301 for _, peer := range port.Peers {
1302 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1303 }
khenaidoo92e62c52018-10-03 14:02:54 -04001304 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001305 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001306 }
1307 return childDeviceIds, nil
1308}
1309
khenaidoo297cd252019-02-07 22:10:23 -05001310//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar467fe752020-01-16 20:17:45 +05301311func (dMgr *DeviceManager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
npujar1d86a522019-11-14 17:11:16 +05301312 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301313 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001314 childDevices := make([]*voltha.Device, 0)
1315 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301316 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301317 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001318 childDevices = append(childDevices, d)
1319 }
1320 }
1321 }
1322 return &voltha.Devices{Items: childDevices}, nil
1323 }
npujar1d86a522019-11-14 17:11:16 +05301324 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001325}
1326
npujar1d86a522019-11-14 17:11:16 +05301327// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
npujar467fe752020-01-16 20:17:45 +05301328func (dMgr *DeviceManager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001329 log.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301330 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001331 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1332 return err
1333 }
1334 return nil
1335}
1336
khenaidoof5a5bfa2019-01-23 22:20:29 -05001337func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1338 log.Debugw("downloadImage", 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.downloadImage(ctx, img); err != nil {
1343 log.Debugw("downloadImage-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) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1353 log.Debugw("cancelImageDownload", 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.cancelImageDownload(ctx, img); err != nil {
1358 log.Debugw("cancelImageDownload-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) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1368 log.Debugw("activateImage", 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.activateImage(ctx, img); err != nil {
1373 log.Debugw("activateImage-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) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1383 log.Debugw("revertImage", 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.revertImage(ctx, img); err != nil {
1388 log.Debugw("revertImage-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
1397func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1398 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1399 var res interface{}
1400 var err error
npujar467fe752020-01-16 20:17:45 +05301401 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001402 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1403 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1404 res = err
1405 }
1406 } else {
1407 res = status.Errorf(codes.NotFound, "%s", img.Id)
1408 }
1409 sendResponse(ctx, ch, res)
1410}
1411
npujar467fe752020-01-16 20:17:45 +05301412func (dMgr *DeviceManager) updateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001413 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301414 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1415 if err := agent.updateImageDownload(ctx, img); err != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001416 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1417 return err
1418 }
1419 } else {
1420 return status.Errorf(codes.NotFound, "%s", img.Id)
1421 }
1422 return nil
1423}
1424
1425func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1426 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301427 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001428 return agent.getImageDownload(ctx, img)
1429 }
1430 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1431}
1432
npujar1d86a522019-11-14 17:11:16 +05301433func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
1434 log.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301435 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301436 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001437 }
npujar1d86a522019-11-14 17:11:16 +05301438 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001439}
1440
npujar1d86a522019-11-14 17:11:16 +05301441// SetAdminStateToEnable sets admin state of device to enabled
npujar467fe752020-01-16 20:17:45 +05301442func (dMgr *DeviceManager) SetAdminStateToEnable(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001443 log.Info("SetAdminStateToEnable")
npujar467fe752020-01-16 20:17:45 +05301444 if agent := dMgr.getDeviceAgent(ctx, cDevice.Id); agent != nil {
1445 return agent.updateAdminState(ctx, voltha.AdminState_ENABLED)
khenaidoo0a822f92019-05-08 15:15:57 -04001446 }
1447 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1448}
1449
npujar1d86a522019-11-14 17:11:16 +05301450// NotifyInvalidTransition notifies about invalid transition
npujar467fe752020-01-16 20:17:45 +05301451func (dMgr *DeviceManager) NotifyInvalidTransition(ctx context.Context, pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001452 log.Errorw("NotifyInvalidTransition", log.Fields{
1453 "device": pcDevice.Id,
1454 "adminState": pcDevice.AdminState,
1455 "operState": pcDevice.OperStatus,
1456 "connState": pcDevice.ConnectStatus,
1457 })
khenaidoo0a822f92019-05-08 15:15:57 -04001458 //TODO: notify over kafka?
1459 return nil
1460}
1461
khenaidoob9203542018-09-17 22:56:37 -04001462func funcName(f interface{}) string {
1463 p := reflect.ValueOf(f).Pointer()
1464 rf := runtime.FuncForPC(p)
1465 return rf.Name()
1466}
1467
npujar1d86a522019-11-14 17:11:16 +05301468// UpdateDeviceAttribute updates value of particular device attribute
npujar467fe752020-01-16 20:17:45 +05301469func (dMgr *DeviceManager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301470 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
npujar467fe752020-01-16 20:17:45 +05301471 agent.(*DeviceAgent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001472 }
1473}
1474
npujar1d86a522019-11-14 17:11:16 +05301475// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +05301476func (dMgr *DeviceManager) GetParentDeviceID(ctx context.Context, deviceID string) string {
1477 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001478 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001479 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001480 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001481 return ""
khenaidoob9203542018-09-17 22:56:37 -04001482}
serkant.uluderya334479d2019-04-10 08:26:15 -07001483
1484func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1485 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1486 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1487 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1488 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301489 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001490 res = agent.simulateAlarm(ctx, simulatereq)
1491 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1492 }
1493 //TODO CLI always get successful response
1494 sendResponse(ctx, ch, res)
1495}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001496
npujar467fe752020-01-16 20:17:45 +05301497func (dMgr *DeviceManager) updateDeviceReason(ctx context.Context, deviceID string, reason string) error {
npujar1d86a522019-11-14 17:11:16 +05301498 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301499 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1500 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001501 }
npujar1d86a522019-11-14 17:11:16 +05301502 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001503}
kesavandbc2d1622020-01-21 00:42:01 -05001504
1505func (dMgr *DeviceManager) enablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1506 log.Debugw("enablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
1507 var res interface{}
1508 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1509 res = agent.enablePort(ctx, port)
1510 log.Debugw("enablePort-result", log.Fields{"result": res})
1511 } else {
1512 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1513 }
1514
1515 sendResponse(ctx, ch, res)
1516}
1517
1518func (dMgr *DeviceManager) disablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1519 log.Debugw("disablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
1520 var res interface{}
1521 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1522 res = agent.disablePort(ctx, port)
1523 log.Debugw("disablePort-result", log.Fields{"result": res})
1524 } else {
1525 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1526 }
1527
1528 sendResponse(ctx, ch, res)
1529}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001530
1531// ChildDeviceLost calls parent adapter to delete child device and all its references
1532func (dMgr *DeviceManager) ChildDeviceLost(ctx context.Context, cDevice *voltha.Device) error {
1533 log.Debugw("ChildDeviceLost", log.Fields{"deviceid": cDevice.Id})
1534 if parentAgent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); parentAgent != nil {
1535 return parentAgent.ChildDeviceLost(ctx, cDevice)
1536 }
1537 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1538}