blob: 714c535a199e94833418a3bcd580d7cf0c173249 [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
npujar1d86a522019-11-14 17:11:16 +053016
khenaidoob9203542018-09-17 22:56:37 -040017package core
18
19import (
20 "context"
21 "errors"
npujar1d86a522019-11-14 17:11:16 +053022 "reflect"
23 "runtime"
24 "sync"
25
sbarbari17d7e222019-11-05 10:02:29 -050026 "github.com/opencord/voltha-go/db/model"
khenaidoo3d3b8c22019-05-22 18:10:39 -040027 "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080028 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
29 "github.com/opencord/voltha-lib-go/v3/pkg/log"
30 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
31 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
32 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
33 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040034 "google.golang.org/grpc/codes"
35 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040036)
37
npujar1d86a522019-11-14 17:11:16 +053038// DeviceManager represent device manager attributes
khenaidoob9203542018-09-17 22:56:37 -040039type DeviceManager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040040 deviceAgents sync.Map
41 rootDevices map[string]bool
42 lockRootDeviceMap sync.RWMutex
43 core *Core
44 adapterProxy *AdapterProxy
45 adapterMgr *AdapterManager
46 logicalDeviceMgr *LogicalDeviceManager
npujar467fe752020-01-16 20:17:45 +053047 kafkaICProxy kafka.InterContainerProxy
khenaidoo4c9e5592019-09-09 16:20:41 -040048 stateTransitions *TransitionMap
49 clusterDataProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053050 coreInstanceID string
khenaidoo4c9e5592019-09-09 16:20:41 -040051 exitChannel chan int
52 defaultTimeout int64
53 devicesLoadingLock sync.RWMutex
54 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040055}
56
Richard Jankowski199fd862019-03-18 14:49:51 -040057func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040058 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040059 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040060 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040061 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040062 deviceMgr.kafkaICProxy = core.kmp
Kent Hagermana6d0c362019-07-30 12:50:21 -040063 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic)
npujar1d86a522019-11-14 17:11:16 +053064 deviceMgr.coreInstanceID = core.instanceID
Richard Jankowski199fd862019-03-18 14:49:51 -040065 deviceMgr.clusterDataProxy = core.clusterDataProxy
66 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040067 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
68 deviceMgr.defaultTimeout = core.config.DefaultCoreTimeout
khenaidoo4c9e5592019-09-09 16:20:41 -040069 deviceMgr.devicesLoadingLock = sync.RWMutex{}
70 deviceMgr.deviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040071 return &deviceMgr
72}
73
khenaidoo4d4802d2018-10-04 21:59:49 -040074func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040075 log.Info("starting-device-manager")
76 dMgr.logicalDeviceMgr = logicalDeviceMgr
77 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070078 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
khenaidoob9203542018-09-17 22:56:37 -040079 log.Info("device-manager-started")
80}
81
khenaidoo4d4802d2018-10-04 21:59:49 -040082func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040083 log.Info("stopping-device-manager")
84 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070085 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
khenaidoob9203542018-09-17 22:56:37 -040086 log.Info("device-manager-stopped")
87}
88
89func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
90 if ctx.Err() == nil {
91 // Returned response only of the ctx has not been cancelled/timeout/etc
92 // Channel is automatically closed when a context is Done
93 ch <- result
94 log.Debugw("sendResponse", log.Fields{"result": result})
95 } else {
96 // Should the transaction be reverted back?
97 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
98 }
99}
100
101func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530102 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
103 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -0400104 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400105 dMgr.lockRootDeviceMap.Lock()
106 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530107 dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400108
khenaidoob9203542018-09-17 22:56:37 -0400109}
110
khenaidoo4c9e5592019-09-09 16:20:41 -0400111func (dMgr *DeviceManager) deleteDeviceAgentFromMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530112 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400113 dMgr.lockRootDeviceMap.Lock()
114 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530115 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400116}
117
khenaidoo297cd252019-02-07 22:10:23 -0500118// getDeviceAgent returns the agent managing the device. If the device is not in memory, it will loads it, if it exists
npujar467fe752020-01-16 20:17:45 +0530119func (dMgr *DeviceManager) getDeviceAgent(ctx context.Context, deviceID string) *DeviceAgent {
npujar1d86a522019-11-14 17:11:16 +0530120 agent, ok := dMgr.deviceAgents.Load(deviceID)
121 if ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400122 return agent.(*DeviceAgent)
khenaidoob9203542018-09-17 22:56:37 -0400123 }
npujar1d86a522019-11-14 17:11:16 +0530124 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530125 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530126 if err == nil {
127 agent, ok = dMgr.deviceAgents.Load(deviceID)
128 if !ok {
129 return nil
130 }
131 // Register this device for ownership tracking
132 go func() {
npujar467fe752020-01-16 20:17:45 +0530133 _, err = dMgr.core.deviceOwnership.OwnedByMe(ctx, &utils.DeviceID{ID: deviceID})
npujar1d86a522019-11-14 17:11:16 +0530134 if err != nil {
135 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
136 }
137 }()
138 return agent.(*DeviceAgent)
139 }
140 //TODO: Change the return params to return an error as well
141 log.Errorw("loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400142 return nil
143}
144
khenaidoo297cd252019-02-07 22:10:23 -0500145// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500146func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500147 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400148
149 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
150 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
151 return true
152 })
153
khenaidoo7ccedd52018-12-14 16:48:54 -0500154 return result
155}
156
khenaidoob9203542018-09-17 22:56:37 -0400157func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
npujar467fe752020-01-16 20:17:45 +0530158 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530159 if err != nil {
160 log.Errorf("Failed to fetch parent device info")
161 sendResponse(ctx, ch, err)
162 return
163 }
164 if deviceExist {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530165 log.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
166 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
167 return
168 }
khenaidoo92e62c52018-10-03 14:02:54 -0400169 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400170
khenaidoo5e677ae2019-02-28 17:26:29 -0500171 // Ensure this device is set as root
172 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400173 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400174 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400175 dMgr.addDeviceAgentToMap(agent)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530176 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800177 if err != nil {
178 log.Errorf("Failed to start device")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530179 sendResponse(ctx, ch, err)
Scott Baker80678602019-11-14 16:57:36 -0800180 return
181 }
khenaidoob9203542018-09-17 22:56:37 -0400182
Scott Baker80678602019-11-14 16:57:36 -0800183 sendResponse(ctx, ch, device)
khenaidoob9203542018-09-17 22:56:37 -0400184}
185
186func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400187 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400188 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530189 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400190 res = agent.enableDevice(ctx)
191 log.Debugw("EnableDevice-result", log.Fields{"result": res})
Hardik Windlassb9cfcb12020-02-03 15:59:46 +0000192 } else {
193 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400194 }
195
196 sendResponse(ctx, ch, res)
197}
198
khenaidoo92e62c52018-10-03 14:02:54 -0400199func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
200 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400201 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530202 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400203 res = agent.disableDevice(ctx)
204 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400205 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400206 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400207 }
khenaidoo92e62c52018-10-03 14:02:54 -0400208
209 sendResponse(ctx, ch, res)
210}
211
khenaidoo4d4802d2018-10-04 21:59:49 -0400212func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
213 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
214 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530215 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400216 res = agent.rebootDevice(ctx)
217 log.Debugw("rebootDevice-result", log.Fields{"result": res})
218 } else {
219 res = status.Errorf(codes.NotFound, "%s", id.Id)
220 }
221 sendResponse(ctx, ch, res)
222}
223
224func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
225 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
226 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530227 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400228 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400229 log.Debugw("deleteDevice-result", log.Fields{"result": res})
230 } else {
231 res = status.Errorf(codes.NotFound, "%s", id.Id)
232 }
233 sendResponse(ctx, ch, res)
234}
235
khenaidoo6d62c002019-05-15 21:57:03 -0400236// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
237// This function is called only in the Core that does not own this device. In the Core that owns this device then a
238// deletion deletion also includes removal of any reference of this device.
npujar467fe752020-01-16 20:17:45 +0530239func (dMgr *DeviceManager) stopManagingDevice(ctx context.Context, id string) {
khenaidoo6d62c002019-05-15 21:57:03 -0400240 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
241 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530242 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400243 // stop managing the logical device
npujar467fe752020-01-16 20:17:45 +0530244 ldeviceID := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
npujar1d86a522019-11-14 17:11:16 +0530245 if ldeviceID != "" { // Can happen if logical device agent was already stopped
246 err := dMgr.core.deviceOwnership.AbandonDevice(ldeviceID)
247 if err != nil {
248 log.Errorw("unable-to-abandon-the-device", log.Fields{"error": err})
249 }
khenaidoo6d62c002019-05-15 21:57:03 -0400250 }
khenaidoo49085352020-01-13 19:15:43 -0500251 // We do not need to stop the child devices as this is taken care by the state machine.
khenaidoo6d62c002019-05-15 21:57:03 -0400252 }
npujar467fe752020-01-16 20:17:45 +0530253 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
254 agent.stop(ctx)
khenaidoo4c9e5592019-09-09 16:20:41 -0400255 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400256 // Abandon the device ownership
npujar1d86a522019-11-14 17:11:16 +0530257 err := dMgr.core.deviceOwnership.AbandonDevice(id)
258 if err != nil {
259 log.Errorw("unable-to-abandon-device", log.Fields{"error": err})
260 }
khenaidoo6d62c002019-05-15 21:57:03 -0400261 }
262 }
263}
264
npujar1d86a522019-11-14 17:11:16 +0530265// RunPostDeviceDelete removes any reference of this device
npujar467fe752020-01-16 20:17:45 +0530266func (dMgr *DeviceManager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -0400267 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530268 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400269 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400270}
271
khenaidoo297cd252019-02-07 22:10:23 -0500272// GetDevice will returns a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530273func (dMgr *DeviceManager) GetDevice(ctx context.Context, id string) (*voltha.Device, error) {
khenaidoo19d7b632018-10-30 10:49:50 -0400274 log.Debugw("GetDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530275 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500276 return agent.getDevice(), nil
khenaidoo92e62c52018-10-03 14:02:54 -0400277 }
278 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400279}
280
npujar1d86a522019-11-14 17:11:16 +0530281// GetChildDevice will return a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530282func (dMgr *DeviceManager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
npujar1d86a522019-11-14 17:11:16 +0530283 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
284 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500285
286 var parentDevice *voltha.Device
287 var err error
npujar467fe752020-01-16 20:17:45 +0530288 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500289 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
290 }
291 var childDeviceIds []string
292 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
293 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
294 }
295 if len(childDeviceIds) == 0 {
npujar1d86a522019-11-14 17:11:16 +0530296 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
297 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500298 }
299
300 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530301 for _, childDeviceID := range childDeviceIds {
302 var found bool
npujar467fe752020-01-16 20:17:45 +0530303 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500304
npujar1d86a522019-11-14 17:11:16 +0530305 foundOnuID := false
306 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500307 if searchDevice.ParentPortNo == uint32(parentPortNo) {
npujar1d86a522019-11-14 17:11:16 +0530308 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
309 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500310 }
311 }
312
313 foundSerialNumber := false
314 if searchDevice.SerialNumber == serialNumber {
315 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
316 foundSerialNumber = true
317 }
318
319 // if both onuId and serialNumber are provided both must be true for the device to be found
320 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530321 if onuID > 0 && serialNumber != "" {
322 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500323 } else {
npujar1d86a522019-11-14 17:11:16 +0530324 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500325 }
326
npujar1d86a522019-11-14 17:11:16 +0530327 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500328 foundChildDevice = searchDevice
329 break
330 }
331 }
332 }
333
334 if foundChildDevice != nil {
335 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
336 return foundChildDevice, nil
337 }
338
339 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530340 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
341 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500342}
343
npujar1d86a522019-11-14 17:11:16 +0530344// GetChildDeviceWithProxyAddress will return a device based on proxy address
npujar467fe752020-01-16 20:17:45 +0530345func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500346 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
347
348 var parentDevice *voltha.Device
349 var err error
npujar467fe752020-01-16 20:17:45 +0530350 if parentDevice, err = dMgr.GetDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500351 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
352 }
353 var childDeviceIds []string
354 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
355 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
356 }
357 if len(childDeviceIds) == 0 {
358 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
359 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
360 }
361
362 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530363 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530364 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500365 if searchDevice.ProxyAddress == proxyAddress {
366 foundChildDevice = searchDevice
367 break
368 }
369 }
370 }
371
372 if foundChildDevice != nil {
373 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
374 return foundChildDevice, nil
375 }
376
377 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
378 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
379}
380
npujar1d86a522019-11-14 17:11:16 +0530381// IsDeviceInCache returns true if device is found in the map
khenaidoo297cd252019-02-07 22:10:23 -0500382func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400383 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500384 return exist
385}
386
npujar1d86a522019-11-14 17:11:16 +0530387// IsRootDevice returns true if root device is found in the map
khenaidoo19d7b632018-10-30 10:49:50 -0400388func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400389 dMgr.lockRootDeviceMap.RLock()
390 defer dMgr.lockRootDeviceMap.RUnlock()
391 if exist := dMgr.rootDevices[id]; exist {
392 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400393 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400394 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400395}
396
Stephane Barbarieaa467942019-02-06 14:09:44 -0500397// ListDevices retrieves the latest devices from the data model
npujar467fe752020-01-16 20:17:45 +0530398func (dMgr *DeviceManager) ListDevices(ctx context.Context) (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400399 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400400 result := &voltha.Devices{}
npujar467fe752020-01-16 20:17:45 +0530401 devices, err := dMgr.clusterDataProxy.List(ctx, "/devices", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530402 if err != nil {
403 log.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
404 return nil, err
405 }
406 if devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500407 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500408 // If device is not in memory then set it up
409 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400410 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400411 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530412 if _, err := agent.start(ctx, nil); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500413 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
npujar467fe752020-01-16 20:17:45 +0530414 agent.stop(ctx)
khenaidoo297cd252019-02-07 22:10:23 -0500415 } else {
416 dMgr.addDeviceAgentToMap(agent)
417 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500418 }
419 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400420 }
421 }
khenaidoo6d62c002019-05-15 21:57:03 -0400422 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400423 return result, nil
424}
425
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530426//isParentDeviceExist checks whether device is already preprovisioned.
npujar467fe752020-01-16 20:17:45 +0530427func (dMgr *DeviceManager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530428 hostPort := newDevice.GetHostAndPort()
npujar467fe752020-01-16 20:17:45 +0530429 devices, err := dMgr.clusterDataProxy.List(ctx, "/devices", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530430 if err != nil {
431 log.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
432 return false, err
433 }
434 if devices != nil {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530435 for _, device := range devices.([]interface{}) {
436 if !device.(*voltha.Device).Root {
437 continue
438 }
439 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530440 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530441 }
442 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530443 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530444 }
445 }
446 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530447 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530448}
449
khenaidoo6d62c002019-05-15 21:57:03 -0400450//getDeviceFromModelretrieves the device data from the model.
npujar467fe752020-01-16 20:17:45 +0530451func (dMgr *DeviceManager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
452 device, err := dMgr.clusterDataProxy.Get(ctx, "/devices/"+deviceID, 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530453 if err != nil {
454 log.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
455 return nil, err
456 }
457 if device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400458 if d, ok := device.(*voltha.Device); ok {
459 return d, nil
460 }
461 }
npujar1d86a522019-11-14 17:11:16 +0530462 return nil, status.Error(codes.NotFound, deviceID)
khenaidoo6d62c002019-05-15 21:57:03 -0400463}
464
npujar1d86a522019-11-14 17:11:16 +0530465// loadDevice loads the deviceID in memory, if not present
npujar467fe752020-01-16 20:17:45 +0530466func (dMgr *DeviceManager) loadDevice(ctx context.Context, deviceID string) (*DeviceAgent, error) {
npujar1d86a522019-11-14 17:11:16 +0530467 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500468 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
469 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400470 var err error
471 var device *voltha.Device
472 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530473 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
474 if !dMgr.IsDeviceInCache(deviceID) {
475 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400476 dMgr.devicesLoadingLock.Unlock()
477 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530478 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530479 log.Debugw("loading-device", log.Fields{"deviceId": deviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400480 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530481 if _, err = agent.start(ctx, nil); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530482 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
npujar467fe752020-01-16 20:17:45 +0530483 agent.stop(ctx)
khenaidoo4c9e5592019-09-09 16:20:41 -0400484 } else {
485 dMgr.addDeviceAgentToMap(agent)
486 }
487 } else {
npujar1d86a522019-11-14 17:11:16 +0530488 log.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400489 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400490 // announce completion of task to any number of waiting channels
491 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530492 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400493 for _, ch := range v {
494 close(ch)
495 }
npujar1d86a522019-11-14 17:11:16 +0530496 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400497 }
498 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400499 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400500 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500501 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400502 } else {
503 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530504 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400505 dMgr.devicesLoadingLock.Unlock()
506 // Wait for the channel to be closed, implying the process loading this device is done.
507 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500508 }
npujar1d86a522019-11-14 17:11:16 +0530509 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400510 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500511 }
npujar1d86a522019-11-14 17:11:16 +0530512 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500513}
514
515// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
npujar467fe752020-01-16 20:17:45 +0530516func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
khenaidoo297cd252019-02-07 22:10:23 -0500517 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
518 if device.Root {
519 // Scenario A
520 if device.ParentId != "" {
521 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530522 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500523 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
524 }
525 } else {
526 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
527 }
528 // Load all child devices, if needed
529 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530530 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530531 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530532 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500533 return err
534 }
535 }
536 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
537 } else {
538 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
539 }
540 }
541 return nil
542}
543
544// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
545// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
546// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
547// and the proceed with the request.
npujar467fe752020-01-16 20:17:45 +0530548func (dMgr *DeviceManager) load(ctx context.Context, deviceID string) error {
khenaidoo297cd252019-02-07 22:10:23 -0500549 log.Debug("load...")
550 // First load the device - this may fail in case the device was deleted intentionally by the other core
551 var dAgent *DeviceAgent
552 var err error
npujar467fe752020-01-16 20:17:45 +0530553 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500554 return err
555 }
556 // Get the loaded device details
khenaidoo6e55d9e2019-12-12 18:26:26 -0500557 device := dAgent.getDevice()
khenaidoo297cd252019-02-07 22:10:23 -0500558
559 // If the device is in Pre-provisioning or deleted state stop here
560 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
561 return nil
562 }
563
564 // Now we face two scenarios
565 if device.Root {
566 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530567 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530568 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500569 return err
570 }
npujar1d86a522019-11-14 17:11:16 +0530571 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500572 } else {
573 // Scenario B - use the parentId of that device (root device) to trigger the loading
574 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530575 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500576 }
577 }
578 return nil
579}
580
khenaidoo7ccedd52018-12-14 16:48:54 -0500581// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
582func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
583 log.Debug("ListDeviceIDs")
584 // Report only device IDs that are in the device agent map
585 return dMgr.listDeviceIdsFromMap(), nil
586}
587
khenaidoo4c9e5592019-09-09 16:20:41 -0400588//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
589//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500590func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400591 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500592 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400593 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500594 toReconcile := len(ids.Items)
595 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400596 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500597 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530598 if err = dMgr.load(ctx, id.Id); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400599 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
600 } else {
npujar1d86a522019-11-14 17:11:16 +0530601 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500602 }
603 }
604 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400605 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500606 }
607 } else {
608 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
609 }
610 sendResponse(ctx, ch, res)
611}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500612
khenaidooba6b6c42019-08-02 09:11:56 -0400613// isOkToReconcile validates whether a device is in the correct status to be reconciled
614func isOkToReconcile(device *voltha.Device) bool {
615 if device == nil {
616 return false
617 }
618 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
619}
620
621// adapterRestarted is invoked whenever an adapter is restarted
npujar467fe752020-01-16 20:17:45 +0530622func (dMgr *DeviceManager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
khenaidooba6b6c42019-08-02 09:11:56 -0400623 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
624
625 // Let's reconcile the device managed by this Core only
626 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
627 if len(rootDeviceIds) == 0 {
628 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
629 return nil
630 }
631
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500632 responses := make([]utils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530633 for _, rootDeviceID := range rootDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530634 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400635 if rootDevice.Adapter == adapter.Id {
636 if isOkToReconcile(rootDevice) {
637 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530638 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400639 } else {
640 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
641 }
642 } else { // Should we be reconciling the root's children instead?
643 childManagedByAdapter:
644 for _, port := range rootDevice.Ports {
645 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530646 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400647 if childDevice.Adapter == adapter.Id {
648 if isOkToReconcile(childDevice) {
649 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530650 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400651 } else {
652 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
653 }
654 } else {
655 // All child devices under a parent device are typically managed by the same adapter type.
656 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
657 break childManagedByAdapter
658 }
659 }
660 }
661 }
662 }
663 }
664 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500665 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400666 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500667 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400668 return status.Errorf(codes.Aborted, "errors-%s", res)
669 }
670 } else {
671 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
672 }
673 return nil
674}
675
npujar467fe752020-01-16 20:17:45 +0530676func (dMgr *DeviceManager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400677 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
678 // point of creating a device agent (if the device is not being managed by this Core) before sending the request
npujar1d86a522019-11-14 17:11:16 +0530679 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to the adapter via
khenaidooba6b6c42019-08-02 09:11:56 -0400680 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500681 response := utils.NewResponse()
khenaidooba6b6c42019-08-02 09:11:56 -0400682 go func(device *voltha.Device) {
npujar467fe752020-01-16 20:17:45 +0530683 if err := dMgr.adapterProxy.ReconcileDevice(ctx, device); err != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400684 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500685 response.Error(status.Errorf(codes.Internal, "device: %s", device.Id))
khenaidooba6b6c42019-08-02 09:11:56 -0400686 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500687 response.Done()
khenaidooba6b6c42019-08-02 09:11:56 -0400688 }(device)
689
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500690 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400691}
692
npujar467fe752020-01-16 20:17:45 +0530693func (dMgr *DeviceManager) reconcileChildDevices(ctx context.Context, parentDeviceID string) error {
694 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500695 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400696 for _, port := range parentDevice.Ports {
697 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530698 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
699 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400700 }
701 }
702 }
703 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500704 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400705 return status.Errorf(codes.Aborted, "errors-%s", res)
706 }
707 }
708 return nil
709}
710
npujar467fe752020-01-16 20:17:45 +0530711func (dMgr *DeviceManager) updateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700712 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530713 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
714 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400715 }
716 return status.Errorf(codes.NotFound, "%s", device.Id)
717}
718
npujar467fe752020-01-16 20:17:45 +0530719func (dMgr *DeviceManager) addPort(ctx context.Context, deviceID string, port *voltha.Port) error {
720 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530721 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530722 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400723 return err
724 }
725 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530726 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400727 for _, peerPort := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530728 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
729 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400730 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
731 return err
732 }
733 }
734 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400735 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
736 // then a logical port will be added to the logical device and the device graph generated. If the port is a
737 // PON port then only the device graph will be generated.
npujar467fe752020-01-16 20:17:45 +0530738 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530739 go func() {
npujar467fe752020-01-16 20:17:45 +0530740 err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port)
npujar1d86a522019-11-14 17:11:16 +0530741 if err != nil {
742 log.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
743 }
744 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400745 } else {
npujar1d86a522019-11-14 17:11:16 +0530746 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400747 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400748 }
khenaidoo92e62c52018-10-03 14:02:54 -0400749 return nil
khenaidoob9203542018-09-17 22:56:37 -0400750 }
npujar1d86a522019-11-14 17:11:16 +0530751 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400752}
753
npujar467fe752020-01-16 20:17:45 +0530754func (dMgr *DeviceManager) deletePeerPorts(ctx context.Context, fromDeviceID string, deviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530755 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceID, "deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530756 if agent := dMgr.getDeviceAgent(ctx, fromDeviceID); agent != nil {
757 return agent.deletePeerPorts(ctx, deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400758 }
npujar1d86a522019-11-14 17:11:16 +0530759 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400760}
761
npujar467fe752020-01-16 20:17:45 +0530762func (dMgr *DeviceManager) addFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Esin Karaman09959ae2019-11-29 13:59:58 +0000763 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530764 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
765 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400766 }
npujar1d86a522019-11-14 17:11:16 +0530767 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400768}
769
npujar467fe752020-01-16 20:17:45 +0530770func (dMgr *DeviceManager) deleteFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530771 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530772 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
773 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400774 }
npujar1d86a522019-11-14 17:11:16 +0530775 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400776}
777
npujar467fe752020-01-16 20:17:45 +0530778func (dMgr *DeviceManager) updateFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530779 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530780 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
781 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400782 }
npujar1d86a522019-11-14 17:11:16 +0530783 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400784}
785
khenaidoob3127472019-07-24 21:04:55 -0400786// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
787// following a user action
788func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
789 var res interface{}
790 if pmConfigs.Id == "" {
791 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
npujar467fe752020-01-16 20:17:45 +0530792 } else if agent := dMgr.getDeviceAgent(ctx, pmConfigs.Id); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400793 res = agent.updatePmConfigs(ctx, pmConfigs)
794 } else {
795 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
796 }
797 sendResponse(ctx, ch, res)
798}
799
800// initPmConfigs initialize the pm configs as defined by the adapter.
npujar467fe752020-01-16 20:17:45 +0530801func (dMgr *DeviceManager) initPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400802 if pmConfigs.Id == "" {
803 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
804 }
npujar467fe752020-01-16 20:17:45 +0530805 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
806 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400807 }
npujar1d86a522019-11-14 17:11:16 +0530808 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400809}
810
npujar1d86a522019-11-14 17:11:16 +0530811func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
npujar467fe752020-01-16 20:17:45 +0530812 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400813 return agent.listPmConfigs(ctx)
814 }
npujar1d86a522019-11-14 17:11:16 +0530815 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400816}
817
npujar1d86a522019-11-14 17:11:16 +0530818func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
819 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530820 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400821 return agent.getSwitchCapability(ctx)
822 }
npujar1d86a522019-11-14 17:11:16 +0530823 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400824}
825
npujar1d86a522019-11-14 17:11:16 +0530826func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
827 log.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530828 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400829 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400830 }
npujar1d86a522019-11-14 17:11:16 +0530831 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400832}
833
npujar1d86a522019-11-14 17:11:16 +0530834func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
835 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530836 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400837 return agent.getPortCapability(ctx, portNo)
838 }
npujar1d86a522019-11-14 17:11:16 +0530839 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400840}
841
npujar467fe752020-01-16 20:17:45 +0530842func (dMgr *DeviceManager) updateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530843 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530844 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
845 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400846 }
npujar1d86a522019-11-14 17:11:16 +0530847 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400848}
849
npujar467fe752020-01-16 20:17:45 +0530850func (dMgr *DeviceManager) updateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530851 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400852 var parentDevice *voltha.Device
853 var err error
npujar467fe752020-01-16 20:17:45 +0530854 if parentDevice, err = dMgr.GetDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400855 return status.Errorf(codes.Aborted, "%s", err.Error())
856 }
857 var childDeviceIds []string
858 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
859 return status.Errorf(codes.Aborted, "%s", err.Error())
860 }
861 if len(childDeviceIds) == 0 {
862 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
863 }
npujar1d86a522019-11-14 17:11:16 +0530864 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530865 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
866 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530867 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400868 }
869 }
870 }
871 return nil
872}
873
npujar467fe752020-01-16 20:17:45 +0530874func (dMgr *DeviceManager) updatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530875 log.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530876 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
877 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530878 log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400879 return err
880 }
881 // Notify the logical device manager to change the port state
npujar1d86a522019-11-14 17:11:16 +0530882 go func() {
npujar467fe752020-01-16 20:17:45 +0530883 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
npujar1d86a522019-11-14 17:11:16 +0530884 if err != nil {
David K. Bainbridgeeb8c4f82020-03-04 12:34:30 -0800885 // While we want to handle (catch) and log when
886 // an update to a port was not able to be
887 // propagated to the logical port, we can report
888 // it as a warning and not an error because it
889 // doesn't stop or modify processing.
890 // TODO: VOL-2707
891 log.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530892 }
893 }()
khenaidoob9203542018-09-17 22:56:37 -0400894 }
npujar1d86a522019-11-14 17:11:16 +0530895 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400896}
897
npujar467fe752020-01-16 20:17:45 +0530898func (dMgr *DeviceManager) deleteAllPorts(ctx context.Context, deviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530899 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530900 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
901 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400902 return err
903 }
904 // Notify the logical device manager to remove all logical ports, if needed.
905 // At this stage the device itself may gave been deleted already at a deleteAllPorts
906 // typically is part of a device deletion phase.
npujar467fe752020-01-16 20:17:45 +0530907 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530908 go func() {
npujar467fe752020-01-16 20:17:45 +0530909 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530910 if err != nil {
911 log.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
912 }
913 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400914 } else {
npujar1d86a522019-11-14 17:11:16 +0530915 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400916 return err
917 }
918 return nil
919 }
npujar1d86a522019-11-14 17:11:16 +0530920 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400921}
922
khenaidoo3ab34882019-05-02 21:33:30 -0400923//updatePortsState updates all ports on the device
npujar467fe752020-01-16 20:17:45 +0530924func (dMgr *DeviceManager) updatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530925 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400926
npujar467fe752020-01-16 20:17:45 +0530927 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400928 switch state {
929 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500930 if err := agent.updatePortsOperState(ctx, state); err != nil {
931 log.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400932 return err
933 }
934 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500935 if err := agent.updatePortsOperState(ctx, state); err != nil {
936 log.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400937 return err
938 }
939 default:
940 return status.Error(codes.Unimplemented, "state-change-not-implemented")
941 }
942 // Notify the logical device about the state change
npujar467fe752020-01-16 20:17:45 +0530943 device, err := dMgr.GetDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530944 if err != nil {
945 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400946 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400947 }
kesavandbc2d1622020-01-21 00:42:01 -0500948 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530949 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
950 return err
951 }
952 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400953 }
npujar1d86a522019-11-14 17:11:16 +0530954 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400955}
956
npujar467fe752020-01-16 20:17:45 +0530957func (dMgr *DeviceManager) childDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530958 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
959 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 -0700960
npujar1d86a522019-11-14 17:11:16 +0530961 if deviceType == "" && vendorID != "" {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700962 log.Debug("device-type-is-nil-fetching-device-type")
npujar467fe752020-01-16 20:17:45 +0530963 deviceTypesIf, err := dMgr.adapterMgr.clusterDataProxy.List(ctx, "/device_types", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530964 if err != nil {
965 log.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
966 return nil, err
967 }
968 if deviceTypesIf != nil {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700969 OLoop:
970 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
971 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
972 for _, v := range dType.VendorIds {
npujar1d86a522019-11-14 17:11:16 +0530973 if v == vendorID {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700974 deviceType = dType.Adapter
975 break OLoop
976 }
977 }
978 }
979 }
980 }
981 }
982 //if no match found for the vendorid,report adapter with the custom error message
983 if deviceType == "" {
npujar1d86a522019-11-14 17:11:16 +0530984 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
985 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700986 }
khenaidoob9203542018-09-17 22:56:37 -0400987
988 // Create the ONU device
989 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400990 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530991 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400992 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530993 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500994 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400995 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400996
997 //Get parent device type
npujar467fe752020-01-16 20:17:45 +0530998 parent, err := dMgr.GetDevice(ctx, parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400999 if err != nil {
npujar1d86a522019-11-14 17:11:16 +05301000 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceID})
1001 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001002 }
1003
npujar467fe752020-01-16 20:17:45 +05301004 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
npujar1d86a522019-11-14 17:11:16 +05301005 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001006 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001007 }
1008
npujar1d86a522019-11-14 17:11:16 +05301009 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: parent.Type, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001010
1011 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -04001012 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -04001013 dMgr.addDeviceAgentToMap(agent)
npujar467fe752020-01-16 20:17:45 +05301014 childDevice, err = agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001015 if err != nil {
1016 log.Error("error-starting-child")
1017 return nil, err
1018 }
khenaidoob9203542018-09-17 22:56:37 -04001019
khenaidoo09771ef2019-10-11 14:25:02 -04001020 // Since this Core has handled this request then it therefore owns this child device. Set the
1021 // ownership of this device to this Core
npujar467fe752020-01-16 20:17:45 +05301022 _, err = dMgr.core.deviceOwnership.OwnedByMe(ctx, &utils.DeviceID{ID: agent.deviceID})
npujar1d86a522019-11-14 17:11:16 +05301023 if err != nil {
1024 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
1025 }
khenaidoo09771ef2019-10-11 14:25:02 -04001026
khenaidoob9203542018-09-17 22:56:37 -04001027 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301028 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301029 go func() {
npujar467fe752020-01-16 20:17:45 +05301030 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301031 if err != nil {
1032 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1033 }
1034 }()
khenaidoob9203542018-09-17 22:56:37 -04001035 }
1036
khenaidoo79232702018-12-04 11:00:41 -05001037 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301038 go func() {
1039 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1040 if err != nil {
1041 log.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
1042 }
1043 }()
khenaidoo79232702018-12-04 11:00:41 -05001044
Scott Baker80678602019-11-14 16:57:36 -08001045 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001046}
1047
npujar467fe752020-01-16 20:17:45 +05301048func (dMgr *DeviceManager) processTransition(ctx context.Context, previous *voltha.Device, current *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001049 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -04001050 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
1051 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -05001052 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001053 return nil
khenaidoob9203542018-09-17 22:56:37 -04001054 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001055 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -04001056 for _, handler := range handlers {
1057 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
npujar467fe752020-01-16 20:17:45 +05301058 if err := handler(ctx, current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -04001059 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001060 return err
1061 }
1062 }
khenaidoob9203542018-09-17 22:56:37 -04001063 return nil
1064}
1065
npujar467fe752020-01-16 20:17:45 +05301066func (dMgr *DeviceManager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
npujar1d86a522019-11-14 17:11:16 +05301067 log.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301068 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1069 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001070 }
npujar1d86a522019-11-14 17:11:16 +05301071 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001072}
1073
npujar1d86a522019-11-14 17:11:16 +05301074// PacketIn receives packet from adapter
npujar467fe752020-01-16 20:17:45 +05301075func (dMgr *DeviceManager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
npujar1d86a522019-11-14 17:11:16 +05301076 log.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001077 // Get the logical device Id based on the deviceId
1078 var device *voltha.Device
1079 var err error
npujar467fe752020-01-16 20:17:45 +05301080 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301081 log.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001082 return err
1083 }
khenaidoo43c82122018-11-22 18:38:28 -05001084 if !device.Root {
npujar1d86a522019-11-14 17:11:16 +05301085 log.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
1086 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001087 }
1088
npujar467fe752020-01-16 20:17:45 +05301089 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001090 return err
1091 }
1092 return nil
1093}
1094
npujar467fe752020-01-16 20:17:45 +05301095func (dMgr *DeviceManager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
npujar1d86a522019-11-14 17:11:16 +05301096 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301097 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1098 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001099 }
1100 return status.Errorf(codes.NotFound, "%s", device.Id)
1101}
1102
npujar1d86a522019-11-14 17:11:16 +05301103// CreateLogicalDevice creates logical device in core
npujar467fe752020-01-16 20:17:45 +05301104func (dMgr *DeviceManager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001105 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001106 // Verify whether the logical device has already been created
1107 if cDevice.ParentId != "" {
1108 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1109 return nil
1110 }
khenaidoob9203542018-09-17 22:56:37 -04001111 var err error
npujar467fe752020-01-16 20:17:45 +05301112 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001113 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1114 return err
1115 }
khenaidoob9203542018-09-17 22:56:37 -04001116 return nil
1117}
1118
npujar1d86a522019-11-14 17:11:16 +05301119// DeleteLogicalDevice deletes logical device from core
npujar467fe752020-01-16 20:17:45 +05301120func (dMgr *DeviceManager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001121 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001122 var err error
npujar467fe752020-01-16 20:17:45 +05301123 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001124 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1125 return err
1126 }
1127 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301128 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301129 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001130 return nil
1131}
1132
npujar1d86a522019-11-14 17:11:16 +05301133// DeleteLogicalPort removes the logical port associated with a device
npujar467fe752020-01-16 20:17:45 +05301134func (dMgr *DeviceManager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001135 log.Info("deleteLogicalPort")
1136 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001137 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301138 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301139 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001140 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001141 return err
1142 }
npujar467fe752020-01-16 20:17:45 +05301143 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001144 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001145 return err
1146 }
khenaidoo92e62c52018-10-03 14:02:54 -04001147 return nil
1148}
1149
npujar1d86a522019-11-14 17:11:16 +05301150// DeleteLogicalPorts removes the logical ports associated with that deviceId
npujar467fe752020-01-16 20:17:45 +05301151func (dMgr *DeviceManager) DeleteLogicalPorts(ctx context.Context, device *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001152 log.Info("deleteLogicalPorts")
npujar467fe752020-01-16 20:17:45 +05301153 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, device.Id); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -04001154 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1155 return err
1156 }
1157 return nil
1158}
1159
npujar467fe752020-01-16 20:17:45 +05301160func (dMgr *DeviceManager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001161 // Sanity check
1162 if childDevice.Root {
1163 // childDevice is the parent device
1164 return childDevice
1165 }
npujar467fe752020-01-16 20:17:45 +05301166 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001167 return parentDevice
1168}
1169
khenaidoo0a822f92019-05-08 15:15:57 -04001170//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1171//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar467fe752020-01-16 20:17:45 +05301172func (dMgr *DeviceManager) childDevicesLost(ctx context.Context, parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001173 log.Debug("childDevicesLost")
1174 var err error
1175 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301176 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301177 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001178 return err
1179 }
npujar467fe752020-01-16 20:17:45 +05301180 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001181}
1182
1183//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1184// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar467fe752020-01-16 20:17:45 +05301185func (dMgr *DeviceManager) childDevicesDetected(ctx context.Context, parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001186 log.Debug("childDevicesDetected")
1187 var err error
1188 var parentDevice *voltha.Device
1189 var childDeviceIds []string
1190
npujar467fe752020-01-16 20:17:45 +05301191 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301192 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001193 return err
1194 }
1195
1196 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1197 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1198 }
1199 if len(childDeviceIds) == 0 {
1200 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1201 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001202 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301203 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301204 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001205 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301206 go func() {
npujar467fe752020-01-16 20:17:45 +05301207 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301208 if err != nil {
1209 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1210 }
1211 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001212 } else {
npujar1d86a522019-11-14 17:11:16 +05301213 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
1214 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001215 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001216 }
1217 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001218 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001219 return err
1220 }
1221 return nil
1222}
1223
khenaidoo4d4802d2018-10-04 21:59:49 -04001224/*
1225All the functions below are callback functions where they are invoked with the latest and previous data. We can
1226therefore use the data as is without trying to get the latest from the model.
1227*/
1228
khenaidoo0a822f92019-05-08 15:15:57 -04001229//DisableAllChildDevices is invoked as a callback when the parent device is disabled
npujar467fe752020-01-16 20:17:45 +05301230func (dMgr *DeviceManager) DisableAllChildDevices(ctx context.Context, parentDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001231 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001232 var childDeviceIds []string
1233 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001234 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1235 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001236 }
1237 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001238 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001239 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001240 allChildDisable := true
npujar1d86a522019-11-14 17:11:16 +05301241 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301242 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1243 if err = agent.disableDevice(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301244 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001245 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001246 }
1247 }
1248 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001249 if !allChildDisable {
1250 return err
1251 }
khenaidoo92e62c52018-10-03 14:02:54 -04001252 return nil
1253}
1254
khenaidoo0a822f92019-05-08 15:15:57 -04001255//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
npujar467fe752020-01-16 20:17:45 +05301256func (dMgr *DeviceManager) DeleteAllChildDevices(ctx context.Context, parentDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001257 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001258 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001259 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001260 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1261 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001262 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001263 if len(childDeviceIds) == 0 {
1264 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1265 }
1266 allChildDeleted := true
npujar1d86a522019-11-14 17:11:16 +05301267 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301268 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1269 if err = agent.deleteDevice(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301270 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001271 allChildDeleted = false
khenaidoo4d4802d2018-10-04 21:59:49 -04001272 }
khenaidoo49085352020-01-13 19:15:43 -05001273 // No further action is required here. The deleteDevice will change the device state where the resulting
1274 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001275 }
1276 }
1277 if !allChildDeleted {
1278 return err
1279 }
1280 return nil
1281}
1282
Hardik Windlassc704def2020-02-26 18:23:19 +00001283//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
1284func (dMgr *DeviceManager) DeleteAllUNILogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
1285 log.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
1286 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, parentDevice); err != nil {
1287 return err
1288 }
1289 return nil
1290}
1291
khenaidoo4d4802d2018-10-04 21:59:49 -04001292//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1293func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1294 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001295 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001296 if parentDevice != nil {
1297 for _, port := range parentDevice.Ports {
1298 for _, peer := range port.Peers {
1299 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1300 }
khenaidoo92e62c52018-10-03 14:02:54 -04001301 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001302 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001303 }
1304 return childDeviceIds, nil
1305}
1306
khenaidoo297cd252019-02-07 22:10:23 -05001307//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar467fe752020-01-16 20:17:45 +05301308func (dMgr *DeviceManager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
npujar1d86a522019-11-14 17:11:16 +05301309 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301310 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001311 childDevices := make([]*voltha.Device, 0)
1312 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301313 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301314 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001315 childDevices = append(childDevices, d)
1316 }
1317 }
1318 }
1319 return &voltha.Devices{Items: childDevices}, nil
1320 }
npujar1d86a522019-11-14 17:11:16 +05301321 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001322}
1323
npujar1d86a522019-11-14 17:11:16 +05301324// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
npujar467fe752020-01-16 20:17:45 +05301325func (dMgr *DeviceManager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001326 log.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301327 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001328 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1329 return err
1330 }
1331 return nil
1332}
1333
khenaidoof5a5bfa2019-01-23 22:20:29 -05001334func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1335 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1336 var res interface{}
1337 var err error
npujar467fe752020-01-16 20:17:45 +05301338 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001339 if res, err = agent.downloadImage(ctx, img); err != nil {
1340 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1341 res = err
1342 }
1343 } else {
1344 res = status.Errorf(codes.NotFound, "%s", img.Id)
1345 }
1346 sendResponse(ctx, ch, res)
1347}
1348
1349func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1350 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1351 var res interface{}
1352 var err error
npujar467fe752020-01-16 20:17:45 +05301353 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001354 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1355 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1356 res = err
1357 }
1358 } else {
1359 res = status.Errorf(codes.NotFound, "%s", img.Id)
1360 }
1361 sendResponse(ctx, ch, res)
1362}
1363
1364func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1365 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1366 var res interface{}
1367 var err error
npujar467fe752020-01-16 20:17:45 +05301368 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001369 if res, err = agent.activateImage(ctx, img); err != nil {
1370 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1371 res = err
1372 }
1373 } else {
1374 res = status.Errorf(codes.NotFound, "%s", img.Id)
1375 }
1376 sendResponse(ctx, ch, res)
1377}
1378
1379func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1380 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1381 var res interface{}
1382 var err error
npujar467fe752020-01-16 20:17:45 +05301383 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001384 if res, err = agent.revertImage(ctx, img); err != nil {
1385 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1386 res = err
1387 }
1388 } else {
1389 res = status.Errorf(codes.NotFound, "%s", img.Id)
1390 }
1391 sendResponse(ctx, ch, res)
1392}
1393
1394func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1395 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1396 var res interface{}
1397 var err error
npujar467fe752020-01-16 20:17:45 +05301398 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001399 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1400 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1401 res = err
1402 }
1403 } else {
1404 res = status.Errorf(codes.NotFound, "%s", img.Id)
1405 }
1406 sendResponse(ctx, ch, res)
1407}
1408
npujar467fe752020-01-16 20:17:45 +05301409func (dMgr *DeviceManager) updateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001410 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301411 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1412 if err := agent.updateImageDownload(ctx, img); err != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001413 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1414 return err
1415 }
1416 } else {
1417 return status.Errorf(codes.NotFound, "%s", img.Id)
1418 }
1419 return nil
1420}
1421
1422func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1423 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301424 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001425 return agent.getImageDownload(ctx, img)
1426 }
1427 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1428}
1429
npujar1d86a522019-11-14 17:11:16 +05301430func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
1431 log.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301432 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301433 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001434 }
npujar1d86a522019-11-14 17:11:16 +05301435 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001436}
1437
npujar1d86a522019-11-14 17:11:16 +05301438// SetAdminStateToEnable sets admin state of device to enabled
npujar467fe752020-01-16 20:17:45 +05301439func (dMgr *DeviceManager) SetAdminStateToEnable(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001440 log.Info("SetAdminStateToEnable")
npujar467fe752020-01-16 20:17:45 +05301441 if agent := dMgr.getDeviceAgent(ctx, cDevice.Id); agent != nil {
1442 return agent.updateAdminState(ctx, voltha.AdminState_ENABLED)
khenaidoo0a822f92019-05-08 15:15:57 -04001443 }
1444 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1445}
1446
npujar1d86a522019-11-14 17:11:16 +05301447// NotifyInvalidTransition notifies about invalid transition
npujar467fe752020-01-16 20:17:45 +05301448func (dMgr *DeviceManager) NotifyInvalidTransition(ctx context.Context, pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001449 log.Errorw("NotifyInvalidTransition", log.Fields{
1450 "device": pcDevice.Id,
1451 "adminState": pcDevice.AdminState,
1452 "operState": pcDevice.OperStatus,
1453 "connState": pcDevice.ConnectStatus,
1454 })
khenaidoo0a822f92019-05-08 15:15:57 -04001455 //TODO: notify over kafka?
1456 return nil
1457}
1458
khenaidoob9203542018-09-17 22:56:37 -04001459func funcName(f interface{}) string {
1460 p := reflect.ValueOf(f).Pointer()
1461 rf := runtime.FuncForPC(p)
1462 return rf.Name()
1463}
1464
npujar1d86a522019-11-14 17:11:16 +05301465// UpdateDeviceAttribute updates value of particular device attribute
npujar467fe752020-01-16 20:17:45 +05301466func (dMgr *DeviceManager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301467 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
npujar467fe752020-01-16 20:17:45 +05301468 agent.(*DeviceAgent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001469 }
1470}
1471
npujar1d86a522019-11-14 17:11:16 +05301472// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +05301473func (dMgr *DeviceManager) GetParentDeviceID(ctx context.Context, deviceID string) string {
1474 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001475 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001476 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001477 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001478 return ""
khenaidoob9203542018-09-17 22:56:37 -04001479}
serkant.uluderya334479d2019-04-10 08:26:15 -07001480
1481func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1482 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1483 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1484 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1485 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301486 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001487 res = agent.simulateAlarm(ctx, simulatereq)
1488 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1489 }
1490 //TODO CLI always get successful response
1491 sendResponse(ctx, ch, res)
1492}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001493
npujar467fe752020-01-16 20:17:45 +05301494func (dMgr *DeviceManager) updateDeviceReason(ctx context.Context, deviceID string, reason string) error {
npujar1d86a522019-11-14 17:11:16 +05301495 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301496 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1497 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001498 }
npujar1d86a522019-11-14 17:11:16 +05301499 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001500}
kesavandbc2d1622020-01-21 00:42:01 -05001501
1502func (dMgr *DeviceManager) enablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1503 log.Debugw("enablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
1504 var res interface{}
1505 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1506 res = agent.enablePort(ctx, port)
1507 log.Debugw("enablePort-result", log.Fields{"result": res})
1508 } else {
1509 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1510 }
1511
1512 sendResponse(ctx, ch, res)
1513}
1514
1515func (dMgr *DeviceManager) disablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1516 log.Debugw("disablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
1517 var res interface{}
1518 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1519 res = agent.disablePort(ctx, port)
1520 log.Debugw("disablePort-result", log.Fields{"result": res})
1521 } else {
1522 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1523 }
1524
1525 sendResponse(ctx, ch, res)
1526}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001527
1528// ChildDeviceLost calls parent adapter to delete child device and all its references
1529func (dMgr *DeviceManager) ChildDeviceLost(ctx context.Context, cDevice *voltha.Device) error {
1530 log.Debugw("ChildDeviceLost", log.Fields{"deviceid": cDevice.Id})
1531 if parentAgent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); parentAgent != nil {
1532 return parentAgent.ChildDeviceLost(ctx, cDevice)
1533 }
1534 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1535}