blob: df94772febf69cc6f66d67cc10baa6445d9fbe74 [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
npujar1d86a522019-11-14 17:11:16 +053016
khenaidoob9203542018-09-17 22:56:37 -040017package core
18
19import (
20 "context"
21 "errors"
npujar1d86a522019-11-14 17:11:16 +053022 "reflect"
23 "runtime"
24 "sync"
25
sbarbari17d7e222019-11-05 10:02:29 -050026 "github.com/opencord/voltha-go/db/model"
khenaidoo3d3b8c22019-05-22 18:10:39 -040027 "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080028 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
29 "github.com/opencord/voltha-lib-go/v3/pkg/log"
30 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
31 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
32 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
33 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040034 "google.golang.org/grpc/codes"
35 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040036)
37
npujar1d86a522019-11-14 17:11:16 +053038// DeviceManager represent device manager attributes
khenaidoob9203542018-09-17 22:56:37 -040039type DeviceManager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040040 deviceAgents sync.Map
41 rootDevices map[string]bool
42 lockRootDeviceMap sync.RWMutex
43 core *Core
44 adapterProxy *AdapterProxy
45 adapterMgr *AdapterManager
46 logicalDeviceMgr *LogicalDeviceManager
npujar467fe752020-01-16 20:17:45 +053047 kafkaICProxy kafka.InterContainerProxy
khenaidoo4c9e5592019-09-09 16:20:41 -040048 stateTransitions *TransitionMap
49 clusterDataProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053050 coreInstanceID string
khenaidoo4c9e5592019-09-09 16:20:41 -040051 exitChannel chan int
52 defaultTimeout int64
53 devicesLoadingLock sync.RWMutex
54 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040055}
56
Richard Jankowski199fd862019-03-18 14:49:51 -040057func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040058 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040059 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040060 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040061 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040062 deviceMgr.kafkaICProxy = core.kmp
Kent Hagermana6d0c362019-07-30 12:50:21 -040063 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic)
npujar1d86a522019-11-14 17:11:16 +053064 deviceMgr.coreInstanceID = core.instanceID
Richard Jankowski199fd862019-03-18 14:49:51 -040065 deviceMgr.clusterDataProxy = core.clusterDataProxy
66 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040067 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
68 deviceMgr.defaultTimeout = core.config.DefaultCoreTimeout
khenaidoo4c9e5592019-09-09 16:20:41 -040069 deviceMgr.devicesLoadingLock = sync.RWMutex{}
70 deviceMgr.deviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040071 return &deviceMgr
72}
73
khenaidoo4d4802d2018-10-04 21:59:49 -040074func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040075 log.Info("starting-device-manager")
76 dMgr.logicalDeviceMgr = logicalDeviceMgr
77 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070078 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
khenaidoob9203542018-09-17 22:56:37 -040079 log.Info("device-manager-started")
80}
81
khenaidoo4d4802d2018-10-04 21:59:49 -040082func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040083 log.Info("stopping-device-manager")
84 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070085 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
khenaidoob9203542018-09-17 22:56:37 -040086 log.Info("device-manager-stopped")
87}
88
89func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
90 if ctx.Err() == nil {
91 // Returned response only of the ctx has not been cancelled/timeout/etc
92 // Channel is automatically closed when a context is Done
93 ch <- result
94 log.Debugw("sendResponse", log.Fields{"result": result})
95 } else {
96 // Should the transaction be reverted back?
97 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
98 }
99}
100
101func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530102 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
103 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -0400104 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400105 dMgr.lockRootDeviceMap.Lock()
106 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530107 dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400108
khenaidoob9203542018-09-17 22:56:37 -0400109}
110
khenaidoo4c9e5592019-09-09 16:20:41 -0400111func (dMgr *DeviceManager) deleteDeviceAgentFromMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530112 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400113 dMgr.lockRootDeviceMap.Lock()
114 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530115 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400116}
117
khenaidoo297cd252019-02-07 22:10:23 -0500118// getDeviceAgent returns the agent managing the device. If the device is not in memory, it will loads it, if it exists
npujar467fe752020-01-16 20:17:45 +0530119func (dMgr *DeviceManager) getDeviceAgent(ctx context.Context, deviceID string) *DeviceAgent {
npujar1d86a522019-11-14 17:11:16 +0530120 agent, ok := dMgr.deviceAgents.Load(deviceID)
121 if ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400122 return agent.(*DeviceAgent)
khenaidoob9203542018-09-17 22:56:37 -0400123 }
npujar1d86a522019-11-14 17:11:16 +0530124 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530125 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530126 if err == nil {
127 agent, ok = dMgr.deviceAgents.Load(deviceID)
128 if !ok {
129 return nil
130 }
131 // Register this device for ownership tracking
132 go func() {
npujar467fe752020-01-16 20:17:45 +0530133 _, err = dMgr.core.deviceOwnership.OwnedByMe(ctx, &utils.DeviceID{ID: deviceID})
npujar1d86a522019-11-14 17:11:16 +0530134 if err != nil {
135 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
136 }
137 }()
138 return agent.(*DeviceAgent)
139 }
140 //TODO: Change the return params to return an error as well
141 log.Errorw("loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400142 return nil
143}
144
khenaidoo297cd252019-02-07 22:10:23 -0500145// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500146func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500147 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400148
149 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
150 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
151 return true
152 })
153
khenaidoo7ccedd52018-12-14 16:48:54 -0500154 return result
155}
156
khenaidoob9203542018-09-17 22:56:37 -0400157func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
npujar467fe752020-01-16 20:17:45 +0530158 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530159 if err != nil {
160 log.Errorf("Failed to fetch parent device info")
161 sendResponse(ctx, ch, err)
162 return
163 }
164 if deviceExist {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530165 log.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
166 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
167 return
168 }
khenaidoo92e62c52018-10-03 14:02:54 -0400169 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400170
khenaidoo5e677ae2019-02-28 17:26:29 -0500171 // Ensure this device is set as root
172 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400173 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400174 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400175 dMgr.addDeviceAgentToMap(agent)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530176 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800177 if err != nil {
178 log.Errorf("Failed to start device")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530179 sendResponse(ctx, ch, err)
Scott Baker80678602019-11-14 16:57:36 -0800180 return
181 }
khenaidoob9203542018-09-17 22:56:37 -0400182
Scott Baker80678602019-11-14 16:57:36 -0800183 sendResponse(ctx, ch, device)
khenaidoob9203542018-09-17 22:56:37 -0400184}
185
186func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400187 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400188 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530189 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400190 res = agent.enableDevice(ctx)
191 log.Debugw("EnableDevice-result", log.Fields{"result": res})
Hardik Windlassb9cfcb12020-02-03 15:59:46 +0000192 } else {
193 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400194 }
195
196 sendResponse(ctx, ch, res)
197}
198
khenaidoo92e62c52018-10-03 14:02:54 -0400199func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
200 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400201 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530202 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400203 res = agent.disableDevice(ctx)
204 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400205 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400206 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400207 }
khenaidoo92e62c52018-10-03 14:02:54 -0400208
209 sendResponse(ctx, ch, res)
210}
211
khenaidoo4d4802d2018-10-04 21:59:49 -0400212func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
213 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
214 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530215 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400216 res = agent.rebootDevice(ctx)
217 log.Debugw("rebootDevice-result", log.Fields{"result": res})
218 } else {
219 res = status.Errorf(codes.NotFound, "%s", id.Id)
220 }
221 sendResponse(ctx, ch, res)
222}
223
224func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
225 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
226 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530227 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400228 res = agent.deleteDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400229 log.Debugw("deleteDevice-result", log.Fields{"result": res})
230 } else {
231 res = status.Errorf(codes.NotFound, "%s", id.Id)
232 }
233 sendResponse(ctx, ch, res)
234}
235
khenaidoo6d62c002019-05-15 21:57:03 -0400236// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
237// This function is called only in the Core that does not own this device. In the Core that owns this device then a
238// deletion deletion also includes removal of any reference of this device.
npujar467fe752020-01-16 20:17:45 +0530239func (dMgr *DeviceManager) stopManagingDevice(ctx context.Context, id string) {
khenaidoo6d62c002019-05-15 21:57:03 -0400240 log.Infow("stopManagingDevice", log.Fields{"deviceId": id})
241 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530242 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400243 // stop managing the logical device
npujar467fe752020-01-16 20:17:45 +0530244 ldeviceID := dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
npujar1d86a522019-11-14 17:11:16 +0530245 if ldeviceID != "" { // Can happen if logical device agent was already stopped
246 err := dMgr.core.deviceOwnership.AbandonDevice(ldeviceID)
247 if err != nil {
248 log.Errorw("unable-to-abandon-the-device", log.Fields{"error": err})
249 }
khenaidoo6d62c002019-05-15 21:57:03 -0400250 }
khenaidoo49085352020-01-13 19:15:43 -0500251 // We do not need to stop the child devices as this is taken care by the state machine.
khenaidoo6d62c002019-05-15 21:57:03 -0400252 }
npujar467fe752020-01-16 20:17:45 +0530253 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
254 agent.stop(ctx)
khenaidoo4c9e5592019-09-09 16:20:41 -0400255 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400256 // Abandon the device ownership
npujar1d86a522019-11-14 17:11:16 +0530257 err := dMgr.core.deviceOwnership.AbandonDevice(id)
258 if err != nil {
259 log.Errorw("unable-to-abandon-device", log.Fields{"error": err})
260 }
khenaidoo6d62c002019-05-15 21:57:03 -0400261 }
262 }
263}
264
npujar1d86a522019-11-14 17:11:16 +0530265// RunPostDeviceDelete removes any reference of this device
npujar467fe752020-01-16 20:17:45 +0530266func (dMgr *DeviceManager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -0400267 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530268 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400269 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400270}
271
khenaidoo297cd252019-02-07 22:10:23 -0500272// GetDevice will returns a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530273func (dMgr *DeviceManager) GetDevice(ctx context.Context, id string) (*voltha.Device, error) {
khenaidoo19d7b632018-10-30 10:49:50 -0400274 log.Debugw("GetDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530275 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500276 return agent.getDevice(), nil
khenaidoo92e62c52018-10-03 14:02:54 -0400277 }
278 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400279}
280
npujar1d86a522019-11-14 17:11:16 +0530281// GetChildDevice will return a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530282func (dMgr *DeviceManager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
npujar1d86a522019-11-14 17:11:16 +0530283 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
284 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500285
286 var parentDevice *voltha.Device
287 var err error
npujar467fe752020-01-16 20:17:45 +0530288 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500289 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
290 }
291 var childDeviceIds []string
292 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
293 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
294 }
295 if len(childDeviceIds) == 0 {
npujar1d86a522019-11-14 17:11:16 +0530296 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
297 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500298 }
299
300 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530301 for _, childDeviceID := range childDeviceIds {
302 var found bool
npujar467fe752020-01-16 20:17:45 +0530303 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500304
npujar1d86a522019-11-14 17:11:16 +0530305 foundOnuID := false
306 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500307 if searchDevice.ParentPortNo == uint32(parentPortNo) {
npujar1d86a522019-11-14 17:11:16 +0530308 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
309 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500310 }
311 }
312
313 foundSerialNumber := false
314 if searchDevice.SerialNumber == serialNumber {
315 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
316 foundSerialNumber = true
317 }
318
319 // if both onuId and serialNumber are provided both must be true for the device to be found
320 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530321 if onuID > 0 && serialNumber != "" {
322 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500323 } else {
npujar1d86a522019-11-14 17:11:16 +0530324 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500325 }
326
npujar1d86a522019-11-14 17:11:16 +0530327 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500328 foundChildDevice = searchDevice
329 break
330 }
331 }
332 }
333
334 if foundChildDevice != nil {
335 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
336 return foundChildDevice, nil
337 }
338
339 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530340 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
341 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500342}
343
npujar1d86a522019-11-14 17:11:16 +0530344// GetChildDeviceWithProxyAddress will return a device based on proxy address
npujar467fe752020-01-16 20:17:45 +0530345func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500346 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
347
348 var parentDevice *voltha.Device
349 var err error
npujar467fe752020-01-16 20:17:45 +0530350 if parentDevice, err = dMgr.GetDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500351 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
352 }
353 var childDeviceIds []string
354 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
355 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
356 }
357 if len(childDeviceIds) == 0 {
358 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
359 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
360 }
361
362 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530363 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530364 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500365 if searchDevice.ProxyAddress == proxyAddress {
366 foundChildDevice = searchDevice
367 break
368 }
369 }
370 }
371
372 if foundChildDevice != nil {
373 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
374 return foundChildDevice, nil
375 }
376
377 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
378 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
379}
380
npujar1d86a522019-11-14 17:11:16 +0530381// IsDeviceInCache returns true if device is found in the map
khenaidoo297cd252019-02-07 22:10:23 -0500382func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400383 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500384 return exist
385}
386
npujar1d86a522019-11-14 17:11:16 +0530387// IsRootDevice returns true if root device is found in the map
khenaidoo19d7b632018-10-30 10:49:50 -0400388func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400389 dMgr.lockRootDeviceMap.RLock()
390 defer dMgr.lockRootDeviceMap.RUnlock()
391 if exist := dMgr.rootDevices[id]; exist {
392 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400393 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400394 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400395}
396
Stephane Barbarieaa467942019-02-06 14:09:44 -0500397// ListDevices retrieves the latest devices from the data model
npujar467fe752020-01-16 20:17:45 +0530398func (dMgr *DeviceManager) ListDevices(ctx context.Context) (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400399 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400400 result := &voltha.Devices{}
npujar467fe752020-01-16 20:17:45 +0530401 devices, err := dMgr.clusterDataProxy.List(ctx, "/devices", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530402 if err != nil {
403 log.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
404 return nil, err
405 }
406 if devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500407 for _, device := range devices.([]interface{}) {
khenaidoo297cd252019-02-07 22:10:23 -0500408 // If device is not in memory then set it up
409 if !dMgr.IsDeviceInCache(device.(*voltha.Device).Id) {
khenaidoo6d62c002019-05-15 21:57:03 -0400410 log.Debugw("loading-device-from-Model", log.Fields{"id": device.(*voltha.Device).Id})
khenaidoo2c6a0992019-04-29 13:46:56 -0400411 agent := newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530412 if _, err := agent.start(ctx, nil); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500413 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.(*voltha.Device).Id})
npujar467fe752020-01-16 20:17:45 +0530414 agent.stop(ctx)
khenaidoo297cd252019-02-07 22:10:23 -0500415 } else {
416 dMgr.addDeviceAgentToMap(agent)
417 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500418 }
419 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400420 }
421 }
khenaidoo6d62c002019-05-15 21:57:03 -0400422 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400423 return result, nil
424}
425
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530426//isParentDeviceExist checks whether device is already preprovisioned.
npujar467fe752020-01-16 20:17:45 +0530427func (dMgr *DeviceManager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530428 hostPort := newDevice.GetHostAndPort()
npujar467fe752020-01-16 20:17:45 +0530429 devices, err := dMgr.clusterDataProxy.List(ctx, "/devices", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530430 if err != nil {
431 log.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
432 return false, err
433 }
434 if devices != nil {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530435 for _, device := range devices.([]interface{}) {
436 if !device.(*voltha.Device).Root {
437 continue
438 }
439 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530440 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530441 }
442 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530443 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530444 }
445 }
446 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530447 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530448}
449
khenaidoo6d62c002019-05-15 21:57:03 -0400450//getDeviceFromModelretrieves the device data from the model.
npujar467fe752020-01-16 20:17:45 +0530451func (dMgr *DeviceManager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
452 device, err := dMgr.clusterDataProxy.Get(ctx, "/devices/"+deviceID, 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530453 if err != nil {
454 log.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
455 return nil, err
456 }
457 if device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400458 if d, ok := device.(*voltha.Device); ok {
459 return d, nil
460 }
461 }
npujar1d86a522019-11-14 17:11:16 +0530462 return nil, status.Error(codes.NotFound, deviceID)
khenaidoo6d62c002019-05-15 21:57:03 -0400463}
464
npujar1d86a522019-11-14 17:11:16 +0530465// loadDevice loads the deviceID in memory, if not present
npujar467fe752020-01-16 20:17:45 +0530466func (dMgr *DeviceManager) loadDevice(ctx context.Context, deviceID string) (*DeviceAgent, error) {
npujar1d86a522019-11-14 17:11:16 +0530467 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500468 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
469 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400470 var err error
471 var device *voltha.Device
472 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530473 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
474 if !dMgr.IsDeviceInCache(deviceID) {
475 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400476 dMgr.devicesLoadingLock.Unlock()
477 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530478 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530479 log.Debugw("loading-device", log.Fields{"deviceId": deviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400480 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530481 if _, err = agent.start(ctx, nil); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530482 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
npujar467fe752020-01-16 20:17:45 +0530483 agent.stop(ctx)
khenaidoo4c9e5592019-09-09 16:20:41 -0400484 } else {
485 dMgr.addDeviceAgentToMap(agent)
486 }
487 } else {
npujar1d86a522019-11-14 17:11:16 +0530488 log.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400489 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400490 // announce completion of task to any number of waiting channels
491 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530492 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400493 for _, ch := range v {
494 close(ch)
495 }
npujar1d86a522019-11-14 17:11:16 +0530496 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400497 }
498 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400499 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400500 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500501 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400502 } else {
503 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530504 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400505 dMgr.devicesLoadingLock.Unlock()
506 // Wait for the channel to be closed, implying the process loading this device is done.
507 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500508 }
npujar1d86a522019-11-14 17:11:16 +0530509 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400510 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500511 }
npujar1d86a522019-11-14 17:11:16 +0530512 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500513}
514
515// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
npujar467fe752020-01-16 20:17:45 +0530516func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
khenaidoo297cd252019-02-07 22:10:23 -0500517 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
518 if device.Root {
519 // Scenario A
520 if device.ParentId != "" {
521 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530522 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500523 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
524 }
525 } else {
526 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
527 }
528 // Load all child devices, if needed
529 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530530 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530531 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530532 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500533 return err
534 }
535 }
536 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
537 } else {
538 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
539 }
540 }
541 return nil
542}
543
544// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
545// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
546// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
547// and the proceed with the request.
npujar467fe752020-01-16 20:17:45 +0530548func (dMgr *DeviceManager) load(ctx context.Context, deviceID string) error {
khenaidoo297cd252019-02-07 22:10:23 -0500549 log.Debug("load...")
550 // First load the device - this may fail in case the device was deleted intentionally by the other core
551 var dAgent *DeviceAgent
552 var err error
npujar467fe752020-01-16 20:17:45 +0530553 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500554 return err
555 }
556 // Get the loaded device details
khenaidoo6e55d9e2019-12-12 18:26:26 -0500557 device := dAgent.getDevice()
khenaidoo297cd252019-02-07 22:10:23 -0500558
559 // If the device is in Pre-provisioning or deleted state stop here
560 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
561 return nil
562 }
563
564 // Now we face two scenarios
565 if device.Root {
566 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530567 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530568 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500569 return err
570 }
npujar1d86a522019-11-14 17:11:16 +0530571 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500572 } else {
573 // Scenario B - use the parentId of that device (root device) to trigger the loading
574 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530575 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500576 }
577 }
578 return nil
579}
580
khenaidoo7ccedd52018-12-14 16:48:54 -0500581// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
582func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
583 log.Debug("ListDeviceIDs")
584 // Report only device IDs that are in the device agent map
585 return dMgr.listDeviceIdsFromMap(), nil
586}
587
khenaidoo4c9e5592019-09-09 16:20:41 -0400588//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
589//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500590func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400591 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500592 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400593 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500594 toReconcile := len(ids.Items)
595 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400596 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500597 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530598 if err = dMgr.load(ctx, id.Id); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400599 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
600 } else {
npujar1d86a522019-11-14 17:11:16 +0530601 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500602 }
603 }
604 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400605 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500606 }
607 } else {
608 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
609 }
610 sendResponse(ctx, ch, res)
611}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500612
khenaidooba6b6c42019-08-02 09:11:56 -0400613// isOkToReconcile validates whether a device is in the correct status to be reconciled
614func isOkToReconcile(device *voltha.Device) bool {
615 if device == nil {
616 return false
617 }
618 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
619}
620
621// adapterRestarted is invoked whenever an adapter is restarted
npujar467fe752020-01-16 20:17:45 +0530622func (dMgr *DeviceManager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
khenaidooba6b6c42019-08-02 09:11:56 -0400623 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
624
625 // Let's reconcile the device managed by this Core only
626 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
627 if len(rootDeviceIds) == 0 {
628 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
629 return nil
630 }
631
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500632 responses := make([]utils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530633 for _, rootDeviceID := range rootDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530634 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400635 if rootDevice.Adapter == adapter.Id {
636 if isOkToReconcile(rootDevice) {
637 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530638 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400639 } else {
640 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
641 }
642 } else { // Should we be reconciling the root's children instead?
643 childManagedByAdapter:
644 for _, port := range rootDevice.Ports {
645 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530646 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400647 if childDevice.Adapter == adapter.Id {
648 if isOkToReconcile(childDevice) {
649 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530650 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400651 } else {
652 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
653 }
654 } else {
655 // All child devices under a parent device are typically managed by the same adapter type.
656 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
657 break childManagedByAdapter
658 }
659 }
660 }
661 }
662 }
663 }
664 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500665 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400666 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500667 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400668 return status.Errorf(codes.Aborted, "errors-%s", res)
669 }
670 } else {
671 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
672 }
673 return nil
674}
675
npujar467fe752020-01-16 20:17:45 +0530676func (dMgr *DeviceManager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400677 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
678 // point of creating a device agent (if the device is not being managed by this Core) before sending the request
npujar1d86a522019-11-14 17:11:16 +0530679 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to the adapter via
khenaidooba6b6c42019-08-02 09:11:56 -0400680 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500681 response := utils.NewResponse()
khenaidooba6b6c42019-08-02 09:11:56 -0400682 go func(device *voltha.Device) {
npujar467fe752020-01-16 20:17:45 +0530683 if err := dMgr.adapterProxy.ReconcileDevice(ctx, device); err != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400684 log.Errorw("reconcile-request-failed", log.Fields{"deviceId": device.Id, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500685 response.Error(status.Errorf(codes.Internal, "device: %s", device.Id))
khenaidooba6b6c42019-08-02 09:11:56 -0400686 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500687 response.Done()
khenaidooba6b6c42019-08-02 09:11:56 -0400688 }(device)
689
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500690 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400691}
692
npujar467fe752020-01-16 20:17:45 +0530693func (dMgr *DeviceManager) reconcileChildDevices(ctx context.Context, parentDeviceID string) error {
694 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500695 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400696 for _, port := range parentDevice.Ports {
697 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530698 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
699 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400700 }
701 }
702 }
703 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500704 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400705 return status.Errorf(codes.Aborted, "errors-%s", res)
706 }
707 }
708 return nil
709}
710
npujar467fe752020-01-16 20:17:45 +0530711func (dMgr *DeviceManager) updateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700712 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530713 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
714 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400715 }
716 return status.Errorf(codes.NotFound, "%s", device.Id)
717}
718
npujar467fe752020-01-16 20:17:45 +0530719func (dMgr *DeviceManager) addPort(ctx context.Context, deviceID string, port *voltha.Port) error {
720 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530721 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530722 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400723 return err
724 }
725 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530726 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400727 for _, peerPort := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530728 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
729 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400730 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
731 return err
732 }
733 }
734 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400735 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
736 // then a logical port will be added to the logical device and the device graph generated. If the port is a
737 // PON port then only the device graph will be generated.
npujar467fe752020-01-16 20:17:45 +0530738 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530739 go func() {
npujar467fe752020-01-16 20:17:45 +0530740 err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port)
npujar1d86a522019-11-14 17:11:16 +0530741 if err != nil {
742 log.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
743 }
744 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400745 } else {
npujar1d86a522019-11-14 17:11:16 +0530746 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400747 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400748 }
khenaidoo92e62c52018-10-03 14:02:54 -0400749 return nil
khenaidoob9203542018-09-17 22:56:37 -0400750 }
npujar1d86a522019-11-14 17:11:16 +0530751 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400752}
753
npujar467fe752020-01-16 20:17:45 +0530754func (dMgr *DeviceManager) deletePeerPorts(ctx context.Context, fromDeviceID string, deviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530755 log.Debugw("deletePeerPorts", log.Fields{"fromDeviceId": fromDeviceID, "deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530756 if agent := dMgr.getDeviceAgent(ctx, fromDeviceID); agent != nil {
757 return agent.deletePeerPorts(ctx, deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400758 }
npujar1d86a522019-11-14 17:11:16 +0530759 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400760}
761
npujar467fe752020-01-16 20:17:45 +0530762func (dMgr *DeviceManager) addFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Esin Karaman09959ae2019-11-29 13:59:58 +0000763 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530764 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
765 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400766 }
npujar1d86a522019-11-14 17:11:16 +0530767 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400768}
769
npujar467fe752020-01-16 20:17:45 +0530770func (dMgr *DeviceManager) deleteFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530771 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530772 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
773 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400774 }
npujar1d86a522019-11-14 17:11:16 +0530775 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400776}
777
npujar467fe752020-01-16 20:17:45 +0530778func (dMgr *DeviceManager) updateFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530779 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530780 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
781 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400782 }
npujar1d86a522019-11-14 17:11:16 +0530783 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400784}
785
khenaidoob3127472019-07-24 21:04:55 -0400786// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
787// following a user action
788func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
789 var res interface{}
790 if pmConfigs.Id == "" {
791 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
npujar467fe752020-01-16 20:17:45 +0530792 } else if agent := dMgr.getDeviceAgent(ctx, pmConfigs.Id); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400793 res = agent.updatePmConfigs(ctx, pmConfigs)
794 } else {
795 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
796 }
797 sendResponse(ctx, ch, res)
798}
799
800// initPmConfigs initialize the pm configs as defined by the adapter.
npujar467fe752020-01-16 20:17:45 +0530801func (dMgr *DeviceManager) initPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400802 if pmConfigs.Id == "" {
803 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
804 }
npujar467fe752020-01-16 20:17:45 +0530805 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
806 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400807 }
npujar1d86a522019-11-14 17:11:16 +0530808 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400809}
810
npujar1d86a522019-11-14 17:11:16 +0530811func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
npujar467fe752020-01-16 20:17:45 +0530812 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400813 return agent.listPmConfigs(ctx)
814 }
npujar1d86a522019-11-14 17:11:16 +0530815 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400816}
817
npujar1d86a522019-11-14 17:11:16 +0530818func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
819 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530820 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400821 return agent.getSwitchCapability(ctx)
822 }
npujar1d86a522019-11-14 17:11:16 +0530823 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400824}
825
npujar1d86a522019-11-14 17:11:16 +0530826func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
827 log.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530828 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400829 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400830 }
npujar1d86a522019-11-14 17:11:16 +0530831 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400832}
833
npujar1d86a522019-11-14 17:11:16 +0530834func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
835 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530836 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400837 return agent.getPortCapability(ctx, portNo)
838 }
npujar1d86a522019-11-14 17:11:16 +0530839 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400840}
841
npujar467fe752020-01-16 20:17:45 +0530842func (dMgr *DeviceManager) updateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530843 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530844 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
845 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400846 }
npujar1d86a522019-11-14 17:11:16 +0530847 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400848}
849
npujar467fe752020-01-16 20:17:45 +0530850func (dMgr *DeviceManager) updateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530851 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400852 var parentDevice *voltha.Device
853 var err error
npujar467fe752020-01-16 20:17:45 +0530854 if parentDevice, err = dMgr.GetDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400855 return status.Errorf(codes.Aborted, "%s", err.Error())
856 }
857 var childDeviceIds []string
858 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
859 return status.Errorf(codes.Aborted, "%s", err.Error())
860 }
861 if len(childDeviceIds) == 0 {
862 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
863 }
npujar1d86a522019-11-14 17:11:16 +0530864 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530865 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
866 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530867 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400868 }
869 }
870 }
871 return nil
872}
873
npujar467fe752020-01-16 20:17:45 +0530874func (dMgr *DeviceManager) updatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530875 log.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530876 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
877 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530878 log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400879 return err
880 }
881 // Notify the logical device manager to change the port state
npujar1d86a522019-11-14 17:11:16 +0530882 go func() {
npujar467fe752020-01-16 20:17:45 +0530883 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
npujar1d86a522019-11-14 17:11:16 +0530884 if err != nil {
885 log.Errorw("unable-to-update-port-state", log.Fields{"error": err})
886 }
887 }()
khenaidoob9203542018-09-17 22:56:37 -0400888 }
npujar1d86a522019-11-14 17:11:16 +0530889 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400890}
891
npujar467fe752020-01-16 20:17:45 +0530892func (dMgr *DeviceManager) deleteAllPorts(ctx context.Context, deviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530893 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530894 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
895 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400896 return err
897 }
898 // Notify the logical device manager to remove all logical ports, if needed.
899 // At this stage the device itself may gave been deleted already at a deleteAllPorts
900 // typically is part of a device deletion phase.
npujar467fe752020-01-16 20:17:45 +0530901 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530902 go func() {
npujar467fe752020-01-16 20:17:45 +0530903 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530904 if err != nil {
905 log.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
906 }
907 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400908 } else {
npujar1d86a522019-11-14 17:11:16 +0530909 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400910 return err
911 }
912 return nil
913 }
npujar1d86a522019-11-14 17:11:16 +0530914 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400915}
916
khenaidoo3ab34882019-05-02 21:33:30 -0400917//updatePortsState updates all ports on the device
npujar467fe752020-01-16 20:17:45 +0530918func (dMgr *DeviceManager) updatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530919 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400920
npujar467fe752020-01-16 20:17:45 +0530921 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400922 switch state {
923 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500924 if err := agent.updatePortsOperState(ctx, state); err != nil {
925 log.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400926 return err
927 }
928 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500929 if err := agent.updatePortsOperState(ctx, state); err != nil {
930 log.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400931 return err
932 }
933 default:
934 return status.Error(codes.Unimplemented, "state-change-not-implemented")
935 }
936 // Notify the logical device about the state change
npujar467fe752020-01-16 20:17:45 +0530937 device, err := dMgr.GetDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530938 if err != nil {
939 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400940 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400941 }
kesavandbc2d1622020-01-21 00:42:01 -0500942 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530943 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
944 return err
945 }
946 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400947 }
npujar1d86a522019-11-14 17:11:16 +0530948 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400949}
950
npujar467fe752020-01-16 20:17:45 +0530951func (dMgr *DeviceManager) childDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530952 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
953 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 -0700954
npujar1d86a522019-11-14 17:11:16 +0530955 if deviceType == "" && vendorID != "" {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700956 log.Debug("device-type-is-nil-fetching-device-type")
npujar467fe752020-01-16 20:17:45 +0530957 deviceTypesIf, err := dMgr.adapterMgr.clusterDataProxy.List(ctx, "/device_types", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530958 if err != nil {
959 log.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
960 return nil, err
961 }
962 if deviceTypesIf != nil {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700963 OLoop:
964 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
965 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
966 for _, v := range dType.VendorIds {
npujar1d86a522019-11-14 17:11:16 +0530967 if v == vendorID {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700968 deviceType = dType.Adapter
969 break OLoop
970 }
971 }
972 }
973 }
974 }
975 }
976 //if no match found for the vendorid,report adapter with the custom error message
977 if deviceType == "" {
npujar1d86a522019-11-14 17:11:16 +0530978 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
979 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700980 }
khenaidoob9203542018-09-17 22:56:37 -0400981
982 // Create the ONU device
983 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400984 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530985 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400986 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530987 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500988 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400989 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400990
991 //Get parent device type
npujar467fe752020-01-16 20:17:45 +0530992 parent, err := dMgr.GetDevice(ctx, parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400993 if err != nil {
npujar1d86a522019-11-14 17:11:16 +0530994 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceID})
995 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400996 }
997
npujar467fe752020-01-16 20:17:45 +0530998 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530999 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001000 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001001 }
1002
npujar1d86a522019-11-14 17:11:16 +05301003 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: parent.Type, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001004
1005 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -04001006 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -04001007 dMgr.addDeviceAgentToMap(agent)
npujar467fe752020-01-16 20:17:45 +05301008 childDevice, err = agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001009 if err != nil {
1010 log.Error("error-starting-child")
1011 return nil, err
1012 }
khenaidoob9203542018-09-17 22:56:37 -04001013
khenaidoo09771ef2019-10-11 14:25:02 -04001014 // Since this Core has handled this request then it therefore owns this child device. Set the
1015 // ownership of this device to this Core
npujar467fe752020-01-16 20:17:45 +05301016 _, err = dMgr.core.deviceOwnership.OwnedByMe(ctx, &utils.DeviceID{ID: agent.deviceID})
npujar1d86a522019-11-14 17:11:16 +05301017 if err != nil {
1018 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
1019 }
khenaidoo09771ef2019-10-11 14:25:02 -04001020
khenaidoob9203542018-09-17 22:56:37 -04001021 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301022 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301023 go func() {
npujar467fe752020-01-16 20:17:45 +05301024 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301025 if err != nil {
1026 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1027 }
1028 }()
khenaidoob9203542018-09-17 22:56:37 -04001029 }
1030
khenaidoo79232702018-12-04 11:00:41 -05001031 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301032 go func() {
1033 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1034 if err != nil {
1035 log.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
1036 }
1037 }()
khenaidoo79232702018-12-04 11:00:41 -05001038
Scott Baker80678602019-11-14 16:57:36 -08001039 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001040}
1041
npujar467fe752020-01-16 20:17:45 +05301042func (dMgr *DeviceManager) processTransition(ctx context.Context, previous *voltha.Device, current *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001043 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -04001044 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
1045 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -05001046 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001047 return nil
khenaidoob9203542018-09-17 22:56:37 -04001048 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001049 log.Debugw("handler-found", log.Fields{"num-handlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -04001050 for _, handler := range handlers {
1051 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
npujar467fe752020-01-16 20:17:45 +05301052 if err := handler(ctx, current); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -04001053 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001054 return err
1055 }
1056 }
khenaidoob9203542018-09-17 22:56:37 -04001057 return nil
1058}
1059
npujar467fe752020-01-16 20:17:45 +05301060func (dMgr *DeviceManager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
npujar1d86a522019-11-14 17:11:16 +05301061 log.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301062 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1063 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001064 }
npujar1d86a522019-11-14 17:11:16 +05301065 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001066}
1067
npujar1d86a522019-11-14 17:11:16 +05301068// PacketIn receives packet from adapter
npujar467fe752020-01-16 20:17:45 +05301069func (dMgr *DeviceManager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
npujar1d86a522019-11-14 17:11:16 +05301070 log.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001071 // Get the logical device Id based on the deviceId
1072 var device *voltha.Device
1073 var err error
npujar467fe752020-01-16 20:17:45 +05301074 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301075 log.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001076 return err
1077 }
khenaidoo43c82122018-11-22 18:38:28 -05001078 if !device.Root {
npujar1d86a522019-11-14 17:11:16 +05301079 log.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
1080 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001081 }
1082
npujar467fe752020-01-16 20:17:45 +05301083 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001084 return err
1085 }
1086 return nil
1087}
1088
npujar467fe752020-01-16 20:17:45 +05301089func (dMgr *DeviceManager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
npujar1d86a522019-11-14 17:11:16 +05301090 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301091 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1092 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001093 }
1094 return status.Errorf(codes.NotFound, "%s", device.Id)
1095}
1096
npujar1d86a522019-11-14 17:11:16 +05301097// CreateLogicalDevice creates logical device in core
npujar467fe752020-01-16 20:17:45 +05301098func (dMgr *DeviceManager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001099 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001100 // Verify whether the logical device has already been created
1101 if cDevice.ParentId != "" {
1102 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1103 return nil
1104 }
khenaidoob9203542018-09-17 22:56:37 -04001105 var err error
npujar467fe752020-01-16 20:17:45 +05301106 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001107 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1108 return err
1109 }
khenaidoob9203542018-09-17 22:56:37 -04001110 return nil
1111}
1112
npujar1d86a522019-11-14 17:11:16 +05301113// DeleteLogicalDevice deletes logical device from core
npujar467fe752020-01-16 20:17:45 +05301114func (dMgr *DeviceManager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001115 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001116 var err error
npujar467fe752020-01-16 20:17:45 +05301117 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001118 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1119 return err
1120 }
1121 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301122 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301123 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001124 return nil
1125}
1126
npujar1d86a522019-11-14 17:11:16 +05301127// DeleteLogicalPort removes the logical port associated with a device
npujar467fe752020-01-16 20:17:45 +05301128func (dMgr *DeviceManager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001129 log.Info("deleteLogicalPort")
1130 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001131 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301132 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301133 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001134 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001135 return err
1136 }
npujar467fe752020-01-16 20:17:45 +05301137 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001138 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001139 return err
1140 }
khenaidoo92e62c52018-10-03 14:02:54 -04001141 return nil
1142}
1143
npujar1d86a522019-11-14 17:11:16 +05301144// DeleteLogicalPorts removes the logical ports associated with that deviceId
npujar467fe752020-01-16 20:17:45 +05301145func (dMgr *DeviceManager) DeleteLogicalPorts(ctx context.Context, device *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001146 log.Info("deleteLogicalPorts")
npujar467fe752020-01-16 20:17:45 +05301147 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, device.Id); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -04001148 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": device.Id})
1149 return err
1150 }
1151 return nil
1152}
1153
npujar467fe752020-01-16 20:17:45 +05301154func (dMgr *DeviceManager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001155 // Sanity check
1156 if childDevice.Root {
1157 // childDevice is the parent device
1158 return childDevice
1159 }
npujar467fe752020-01-16 20:17:45 +05301160 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001161 return parentDevice
1162}
1163
khenaidoo0a822f92019-05-08 15:15:57 -04001164//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1165//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar467fe752020-01-16 20:17:45 +05301166func (dMgr *DeviceManager) childDevicesLost(ctx context.Context, parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001167 log.Debug("childDevicesLost")
1168 var err error
1169 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301170 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301171 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001172 return err
1173 }
npujar467fe752020-01-16 20:17:45 +05301174 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001175}
1176
1177//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1178// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar467fe752020-01-16 20:17:45 +05301179func (dMgr *DeviceManager) childDevicesDetected(ctx context.Context, parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001180 log.Debug("childDevicesDetected")
1181 var err error
1182 var parentDevice *voltha.Device
1183 var childDeviceIds []string
1184
npujar467fe752020-01-16 20:17:45 +05301185 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301186 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001187 return err
1188 }
1189
1190 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1191 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1192 }
1193 if len(childDeviceIds) == 0 {
1194 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1195 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001196 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301197 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301198 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001199 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301200 go func() {
npujar467fe752020-01-16 20:17:45 +05301201 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301202 if err != nil {
1203 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1204 }
1205 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001206 } else {
npujar1d86a522019-11-14 17:11:16 +05301207 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
1208 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001209 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001210 }
1211 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001212 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001213 return err
1214 }
1215 return nil
1216}
1217
khenaidoo4d4802d2018-10-04 21:59:49 -04001218/*
1219All the functions below are callback functions where they are invoked with the latest and previous data. We can
1220therefore use the data as is without trying to get the latest from the model.
1221*/
1222
khenaidoo0a822f92019-05-08 15:15:57 -04001223//DisableAllChildDevices is invoked as a callback when the parent device is disabled
npujar467fe752020-01-16 20:17:45 +05301224func (dMgr *DeviceManager) DisableAllChildDevices(ctx context.Context, parentDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001225 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001226 var childDeviceIds []string
1227 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001228 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1229 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001230 }
1231 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -04001232 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001233 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001234 allChildDisable := true
npujar1d86a522019-11-14 17:11:16 +05301235 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301236 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1237 if err = agent.disableDevice(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301238 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001239 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001240 }
1241 }
1242 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001243 if !allChildDisable {
1244 return err
1245 }
khenaidoo92e62c52018-10-03 14:02:54 -04001246 return nil
1247}
1248
khenaidoo0a822f92019-05-08 15:15:57 -04001249//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
npujar467fe752020-01-16 20:17:45 +05301250func (dMgr *DeviceManager) DeleteAllChildDevices(ctx context.Context, parentDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001251 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001252 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001253 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -04001254 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1255 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001256 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001257 if len(childDeviceIds) == 0 {
1258 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1259 }
1260 allChildDeleted := true
npujar1d86a522019-11-14 17:11:16 +05301261 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301262 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1263 if err = agent.deleteDevice(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301264 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001265 allChildDeleted = false
khenaidoo4d4802d2018-10-04 21:59:49 -04001266 }
khenaidoo49085352020-01-13 19:15:43 -05001267 // No further action is required here. The deleteDevice will change the device state where the resulting
1268 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001269 }
1270 }
1271 if !allChildDeleted {
1272 return err
1273 }
1274 return nil
1275}
1276
1277//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1278func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1279 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001280 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001281 if parentDevice != nil {
1282 for _, port := range parentDevice.Ports {
1283 for _, peer := range port.Peers {
1284 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1285 }
khenaidoo92e62c52018-10-03 14:02:54 -04001286 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001287 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001288 }
1289 return childDeviceIds, nil
1290}
1291
khenaidoo297cd252019-02-07 22:10:23 -05001292//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar467fe752020-01-16 20:17:45 +05301293func (dMgr *DeviceManager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
npujar1d86a522019-11-14 17:11:16 +05301294 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301295 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001296 childDevices := make([]*voltha.Device, 0)
1297 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301298 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301299 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001300 childDevices = append(childDevices, d)
1301 }
1302 }
1303 }
1304 return &voltha.Devices{Items: childDevices}, nil
1305 }
npujar1d86a522019-11-14 17:11:16 +05301306 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001307}
1308
npujar1d86a522019-11-14 17:11:16 +05301309// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
npujar467fe752020-01-16 20:17:45 +05301310func (dMgr *DeviceManager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001311 log.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301312 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001313 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1314 return err
1315 }
1316 return nil
1317}
1318
khenaidoof5a5bfa2019-01-23 22:20:29 -05001319func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1320 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1321 var res interface{}
1322 var err error
npujar467fe752020-01-16 20:17:45 +05301323 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001324 if res, err = agent.downloadImage(ctx, img); err != nil {
1325 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1326 res = err
1327 }
1328 } else {
1329 res = status.Errorf(codes.NotFound, "%s", img.Id)
1330 }
1331 sendResponse(ctx, ch, res)
1332}
1333
1334func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1335 log.Debugw("cancelImageDownload", 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.cancelImageDownload(ctx, img); err != nil {
1340 log.Debugw("cancelImageDownload-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) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1350 log.Debugw("activateImage", 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.activateImage(ctx, img); err != nil {
1355 log.Debugw("activateImage-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) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1365 log.Debugw("revertImage", 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.revertImage(ctx, img); err != nil {
1370 log.Debugw("revertImage-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) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1380 log.Debugw("getImageDownloadStatus", 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.getImageDownloadStatus(ctx, img); err != nil {
1385 log.Debugw("getImageDownloadStatus-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
npujar467fe752020-01-16 20:17:45 +05301394func (dMgr *DeviceManager) updateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001395 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301396 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1397 if err := agent.updateImageDownload(ctx, img); err != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001398 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1399 return err
1400 }
1401 } else {
1402 return status.Errorf(codes.NotFound, "%s", img.Id)
1403 }
1404 return nil
1405}
1406
1407func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1408 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301409 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001410 return agent.getImageDownload(ctx, img)
1411 }
1412 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1413}
1414
npujar1d86a522019-11-14 17:11:16 +05301415func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
1416 log.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301417 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301418 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001419 }
npujar1d86a522019-11-14 17:11:16 +05301420 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001421}
1422
npujar1d86a522019-11-14 17:11:16 +05301423// SetAdminStateToEnable sets admin state of device to enabled
npujar467fe752020-01-16 20:17:45 +05301424func (dMgr *DeviceManager) SetAdminStateToEnable(ctx context.Context, cDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001425 log.Info("SetAdminStateToEnable")
npujar467fe752020-01-16 20:17:45 +05301426 if agent := dMgr.getDeviceAgent(ctx, cDevice.Id); agent != nil {
1427 return agent.updateAdminState(ctx, voltha.AdminState_ENABLED)
khenaidoo0a822f92019-05-08 15:15:57 -04001428 }
1429 return status.Errorf(codes.NotFound, "%s", cDevice.Id)
1430}
1431
npujar1d86a522019-11-14 17:11:16 +05301432// NotifyInvalidTransition notifies about invalid transition
npujar467fe752020-01-16 20:17:45 +05301433func (dMgr *DeviceManager) NotifyInvalidTransition(ctx context.Context, pcDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001434 log.Errorw("NotifyInvalidTransition", log.Fields{
1435 "device": pcDevice.Id,
1436 "adminState": pcDevice.AdminState,
1437 "operState": pcDevice.OperStatus,
1438 "connState": pcDevice.ConnectStatus,
1439 })
khenaidoo0a822f92019-05-08 15:15:57 -04001440 //TODO: notify over kafka?
1441 return nil
1442}
1443
khenaidoob9203542018-09-17 22:56:37 -04001444func funcName(f interface{}) string {
1445 p := reflect.ValueOf(f).Pointer()
1446 rf := runtime.FuncForPC(p)
1447 return rf.Name()
1448}
1449
npujar1d86a522019-11-14 17:11:16 +05301450// UpdateDeviceAttribute updates value of particular device attribute
npujar467fe752020-01-16 20:17:45 +05301451func (dMgr *DeviceManager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301452 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
npujar467fe752020-01-16 20:17:45 +05301453 agent.(*DeviceAgent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001454 }
1455}
1456
npujar1d86a522019-11-14 17:11:16 +05301457// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +05301458func (dMgr *DeviceManager) GetParentDeviceID(ctx context.Context, deviceID string) string {
1459 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001460 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001461 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001462 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001463 return ""
khenaidoob9203542018-09-17 22:56:37 -04001464}
serkant.uluderya334479d2019-04-10 08:26:15 -07001465
1466func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1467 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1468 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1469 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1470 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301471 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001472 res = agent.simulateAlarm(ctx, simulatereq)
1473 log.Debugw("SimulateAlarm-result", log.Fields{"result": res})
1474 }
1475 //TODO CLI always get successful response
1476 sendResponse(ctx, ch, res)
1477}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001478
npujar467fe752020-01-16 20:17:45 +05301479func (dMgr *DeviceManager) updateDeviceReason(ctx context.Context, deviceID string, reason string) error {
npujar1d86a522019-11-14 17:11:16 +05301480 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301481 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1482 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001483 }
npujar1d86a522019-11-14 17:11:16 +05301484 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001485}
kesavandbc2d1622020-01-21 00:42:01 -05001486
1487func (dMgr *DeviceManager) enablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1488 log.Debugw("enablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
1489 var res interface{}
1490 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1491 res = agent.enablePort(ctx, port)
1492 log.Debugw("enablePort-result", log.Fields{"result": res})
1493 } else {
1494 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1495 }
1496
1497 sendResponse(ctx, ch, res)
1498}
1499
1500func (dMgr *DeviceManager) disablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1501 log.Debugw("disablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
1502 var res interface{}
1503 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1504 res = agent.disablePort(ctx, port)
1505 log.Debugw("disablePort-result", log.Fields{"result": res})
1506 } else {
1507 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1508 }
1509
1510 sendResponse(ctx, ch, res)
1511}