blob: 0d774296bf12a6beb81778ed7ce6601bd1cd98ca [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"
sbarbari17d7e222019-11-05 10:02:29 -050022 "github.com/opencord/voltha-go/db/model"
khenaidoo3d3b8c22019-05-22 18:10:39 -040023 "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080024 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
25 "github.com/opencord/voltha-lib-go/v3/pkg/log"
26 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
27 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
28 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
29 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040030 "google.golang.org/grpc/codes"
31 "google.golang.org/grpc/status"
khenaidoo442e7c72020-03-10 16:13:48 -040032 "reflect"
33 "runtime"
34 "sync"
35 "time"
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
khenaidoo442e7c72020-03-10 16:13:48 -040052 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040053 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{}
khenaidoo442e7c72020-03-10 16:13:48 -040068 deviceMgr.defaultTimeout = time.Duration(core.config.DefaultCoreTimeout) * time.Millisecond
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 }
khenaidoo442e7c72020-03-10 16:13:48 -0400124 // 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)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530175 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800176 if err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400177 log.Errorw("Fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530178 sendResponse(ctx, ch, err)
Scott Baker80678602019-11-14 16:57:36 -0800179 return
180 }
khenaidoo442e7c72020-03-10 16:13:48 -0400181 dMgr.addDeviceAgentToMap(agent)
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 {
khenaidoo442e7c72020-03-10 16:13:48 -0400254 if err := agent.stop(ctx); err != nil {
255 log.Warnw("unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
256 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400257 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400258 // Abandon the device ownership
npujar1d86a522019-11-14 17:11:16 +0530259 err := dMgr.core.deviceOwnership.AbandonDevice(id)
260 if err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400261 log.Warnw("unable-to-abandon-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530262 }
khenaidoo6d62c002019-05-15 21:57:03 -0400263 }
264 }
265}
266
npujar1d86a522019-11-14 17:11:16 +0530267// RunPostDeviceDelete removes any reference of this device
khenaidoo442e7c72020-03-10 16:13:48 -0400268func (dMgr *DeviceManager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -0400269 log.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530270 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400271 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400272}
273
khenaidoo297cd252019-02-07 22:10:23 -0500274// GetDevice will returns a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530275func (dMgr *DeviceManager) GetDevice(ctx context.Context, id string) (*voltha.Device, error) {
khenaidoo19d7b632018-10-30 10:49:50 -0400276 log.Debugw("GetDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530277 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400278 return agent.getDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400279 }
280 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400281}
282
npujar1d86a522019-11-14 17:11:16 +0530283// GetChildDevice will return a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530284func (dMgr *DeviceManager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
npujar1d86a522019-11-14 17:11:16 +0530285 log.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
286 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500287
288 var parentDevice *voltha.Device
289 var err error
npujar467fe752020-01-16 20:17:45 +0530290 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500291 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
292 }
293 var childDeviceIds []string
294 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
295 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
296 }
297 if len(childDeviceIds) == 0 {
npujar1d86a522019-11-14 17:11:16 +0530298 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
299 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500300 }
301
302 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530303 for _, childDeviceID := range childDeviceIds {
304 var found bool
npujar467fe752020-01-16 20:17:45 +0530305 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500306
npujar1d86a522019-11-14 17:11:16 +0530307 foundOnuID := false
308 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500309 if searchDevice.ParentPortNo == uint32(parentPortNo) {
npujar1d86a522019-11-14 17:11:16 +0530310 log.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
311 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500312 }
313 }
314
315 foundSerialNumber := false
316 if searchDevice.SerialNumber == serialNumber {
317 log.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
318 foundSerialNumber = true
319 }
320
321 // if both onuId and serialNumber are provided both must be true for the device to be found
322 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530323 if onuID > 0 && serialNumber != "" {
324 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500325 } else {
npujar1d86a522019-11-14 17:11:16 +0530326 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500327 }
328
npujar1d86a522019-11-14 17:11:16 +0530329 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500330 foundChildDevice = searchDevice
331 break
332 }
333 }
334 }
335
336 if foundChildDevice != nil {
337 log.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
338 return foundChildDevice, nil
339 }
340
341 log.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530342 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
343 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500344}
345
npujar1d86a522019-11-14 17:11:16 +0530346// GetChildDeviceWithProxyAddress will return a device based on proxy address
npujar467fe752020-01-16 20:17:45 +0530347func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500348 log.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
349
350 var parentDevice *voltha.Device
351 var err error
npujar467fe752020-01-16 20:17:45 +0530352 if parentDevice, err = dMgr.GetDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500353 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
354 }
355 var childDeviceIds []string
356 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
357 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
358 }
359 if len(childDeviceIds) == 0 {
360 log.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
361 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
362 }
363
364 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530365 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530366 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500367 if searchDevice.ProxyAddress == proxyAddress {
368 foundChildDevice = searchDevice
369 break
370 }
371 }
372 }
373
374 if foundChildDevice != nil {
375 log.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
376 return foundChildDevice, nil
377 }
378
379 log.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
380 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
381}
382
npujar1d86a522019-11-14 17:11:16 +0530383// IsDeviceInCache returns true if device is found in the map
khenaidoo297cd252019-02-07 22:10:23 -0500384func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400385 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500386 return exist
387}
388
npujar1d86a522019-11-14 17:11:16 +0530389// IsRootDevice returns true if root device is found in the map
khenaidoo19d7b632018-10-30 10:49:50 -0400390func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400391 dMgr.lockRootDeviceMap.RLock()
392 defer dMgr.lockRootDeviceMap.RUnlock()
393 if exist := dMgr.rootDevices[id]; exist {
394 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400395 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400396 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400397}
398
Stephane Barbarieaa467942019-02-06 14:09:44 -0500399// ListDevices retrieves the latest devices from the data model
npujar467fe752020-01-16 20:17:45 +0530400func (dMgr *DeviceManager) ListDevices(ctx context.Context) (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400401 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400402 result := &voltha.Devices{}
npujar467fe752020-01-16 20:17:45 +0530403 devices, err := dMgr.clusterDataProxy.List(ctx, "/devices", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530404 if err != nil {
405 log.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
406 return nil, err
407 }
408 if devices != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400409 for _, d := range devices.([]interface{}) {
410 device := d.(*voltha.Device)
khenaidoo297cd252019-02-07 22:10:23 -0500411 // If device is not in memory then set it up
khenaidoo442e7c72020-03-10 16:13:48 -0400412 if !dMgr.IsDeviceInCache(device.Id) {
413 log.Debugw("loading-device-from-Model", log.Fields{"id": device.Id})
414 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530415 if _, err := agent.start(ctx, nil); err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400416 log.Warnw("failure-starting-agent", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500417 } else {
418 dMgr.addDeviceAgentToMap(agent)
419 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500420 }
khenaidoo442e7c72020-03-10 16:13:48 -0400421 result.Items = append(result.Items, device)
khenaidoob9203542018-09-17 22:56:37 -0400422 }
423 }
khenaidoo6d62c002019-05-15 21:57:03 -0400424 log.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400425 return result, nil
426}
427
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530428//isParentDeviceExist checks whether device is already preprovisioned.
npujar467fe752020-01-16 20:17:45 +0530429func (dMgr *DeviceManager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530430 hostPort := newDevice.GetHostAndPort()
npujar467fe752020-01-16 20:17:45 +0530431 devices, err := dMgr.clusterDataProxy.List(ctx, "/devices", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530432 if err != nil {
433 log.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
434 return false, err
435 }
436 if devices != nil {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530437 for _, device := range devices.([]interface{}) {
438 if !device.(*voltha.Device).Root {
439 continue
440 }
441 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530442 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530443 }
444 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530445 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530446 }
447 }
448 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530449 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530450}
451
khenaidoo6d62c002019-05-15 21:57:03 -0400452//getDeviceFromModelretrieves the device data from the model.
npujar467fe752020-01-16 20:17:45 +0530453func (dMgr *DeviceManager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
454 device, err := dMgr.clusterDataProxy.Get(ctx, "/devices/"+deviceID, 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530455 if err != nil {
456 log.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
457 return nil, err
458 }
459 if device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400460 if d, ok := device.(*voltha.Device); ok {
461 return d, nil
462 }
463 }
npujar1d86a522019-11-14 17:11:16 +0530464 return nil, status.Error(codes.NotFound, deviceID)
khenaidoo6d62c002019-05-15 21:57:03 -0400465}
466
npujar1d86a522019-11-14 17:11:16 +0530467// loadDevice loads the deviceID in memory, if not present
npujar467fe752020-01-16 20:17:45 +0530468func (dMgr *DeviceManager) loadDevice(ctx context.Context, deviceID string) (*DeviceAgent, error) {
npujar1d86a522019-11-14 17:11:16 +0530469 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500470 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
471 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400472 var err error
473 var device *voltha.Device
474 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530475 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
476 if !dMgr.IsDeviceInCache(deviceID) {
477 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400478 dMgr.devicesLoadingLock.Unlock()
479 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530480 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530481 log.Debugw("loading-device", log.Fields{"deviceId": deviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400482 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530483 if _, err = agent.start(ctx, nil); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530484 log.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400485 } else {
486 dMgr.addDeviceAgentToMap(agent)
487 }
488 } else {
npujar1d86a522019-11-14 17:11:16 +0530489 log.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400490 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400491 // announce completion of task to any number of waiting channels
492 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530493 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400494 for _, ch := range v {
495 close(ch)
496 }
npujar1d86a522019-11-14 17:11:16 +0530497 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400498 }
499 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400500 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400501 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500502 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400503 } else {
504 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530505 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400506 dMgr.devicesLoadingLock.Unlock()
507 // Wait for the channel to be closed, implying the process loading this device is done.
508 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500509 }
npujar1d86a522019-11-14 17:11:16 +0530510 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400511 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500512 }
npujar1d86a522019-11-14 17:11:16 +0530513 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500514}
515
516// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
npujar467fe752020-01-16 20:17:45 +0530517func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
khenaidoo297cd252019-02-07 22:10:23 -0500518 log.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
519 if device.Root {
520 // Scenario A
521 if device.ParentId != "" {
522 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530523 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500524 log.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
525 }
526 } else {
527 log.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
528 }
529 // Load all child devices, if needed
530 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530531 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530532 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530533 log.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500534 return err
535 }
536 }
537 log.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
538 } else {
539 log.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
540 }
541 }
542 return nil
543}
544
545// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
546// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
547// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
548// and the proceed with the request.
npujar467fe752020-01-16 20:17:45 +0530549func (dMgr *DeviceManager) load(ctx context.Context, deviceID string) error {
khenaidoo297cd252019-02-07 22:10:23 -0500550 log.Debug("load...")
551 // First load the device - this may fail in case the device was deleted intentionally by the other core
552 var dAgent *DeviceAgent
553 var err error
npujar467fe752020-01-16 20:17:45 +0530554 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500555 return err
556 }
557 // Get the loaded device details
khenaidoo442e7c72020-03-10 16:13:48 -0400558 device, err := dAgent.getDevice(ctx)
559 if err != nil {
560 return err
561 }
khenaidoo297cd252019-02-07 22:10:23 -0500562
563 // If the device is in Pre-provisioning or deleted state stop here
564 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
565 return nil
566 }
567
568 // Now we face two scenarios
569 if device.Root {
570 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530571 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530572 log.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500573 return err
574 }
npujar1d86a522019-11-14 17:11:16 +0530575 log.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500576 } else {
577 // Scenario B - use the parentId of that device (root device) to trigger the loading
578 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530579 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500580 }
581 }
582 return nil
583}
584
khenaidoo7ccedd52018-12-14 16:48:54 -0500585// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
586func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
587 log.Debug("ListDeviceIDs")
588 // Report only device IDs that are in the device agent map
589 return dMgr.listDeviceIdsFromMap(), nil
590}
591
khenaidoo4c9e5592019-09-09 16:20:41 -0400592//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
593//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500594func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
khenaidoo4c9e5592019-09-09 16:20:41 -0400595 log.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500596 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400597 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500598 toReconcile := len(ids.Items)
599 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400600 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500601 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530602 if err = dMgr.load(ctx, id.Id); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400603 log.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
604 } else {
npujar1d86a522019-11-14 17:11:16 +0530605 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500606 }
607 }
608 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400609 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500610 }
611 } else {
612 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
613 }
614 sendResponse(ctx, ch, res)
615}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500616
khenaidooba6b6c42019-08-02 09:11:56 -0400617// isOkToReconcile validates whether a device is in the correct status to be reconciled
618func isOkToReconcile(device *voltha.Device) bool {
619 if device == nil {
620 return false
621 }
622 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
623}
624
625// adapterRestarted is invoked whenever an adapter is restarted
npujar467fe752020-01-16 20:17:45 +0530626func (dMgr *DeviceManager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
khenaidooba6b6c42019-08-02 09:11:56 -0400627 log.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
628
629 // Let's reconcile the device managed by this Core only
630 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
631 if len(rootDeviceIds) == 0 {
632 log.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
633 return nil
634 }
635
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500636 responses := make([]utils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530637 for _, rootDeviceID := range rootDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530638 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400639 if rootDevice.Adapter == adapter.Id {
640 if isOkToReconcile(rootDevice) {
641 log.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530642 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400643 } else {
644 log.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
645 }
646 } else { // Should we be reconciling the root's children instead?
647 childManagedByAdapter:
648 for _, port := range rootDevice.Ports {
649 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530650 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400651 if childDevice.Adapter == adapter.Id {
652 if isOkToReconcile(childDevice) {
653 log.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530654 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400655 } else {
656 log.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
657 }
658 } else {
659 // All child devices under a parent device are typically managed by the same adapter type.
660 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
661 break childManagedByAdapter
662 }
663 }
664 }
665 }
666 }
667 }
668 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500669 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400670 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500671 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400672 return status.Errorf(codes.Aborted, "errors-%s", res)
673 }
674 } else {
675 log.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
676 }
677 return nil
678}
679
npujar467fe752020-01-16 20:17:45 +0530680func (dMgr *DeviceManager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400681 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
682 // 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 +0530683 // 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 -0400684 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500685 response := utils.NewResponse()
khenaidoo442e7c72020-03-10 16:13:48 -0400686 ch, err := dMgr.adapterProxy.reconcileDevice(ctx, device)
687 if err != nil {
688 response.Error(err)
689 }
690 // Wait for adapter response in its own routine
691 go func() {
692 resp, ok := <-ch
693 if !ok {
694 response.Error(status.Errorf(codes.Aborted, "channel-closed-device: %s", device.Id))
695 } else if resp.Err != nil {
696 response.Error(resp.Err)
khenaidooba6b6c42019-08-02 09:11:56 -0400697 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500698 response.Done()
khenaidoo442e7c72020-03-10 16:13:48 -0400699 }()
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500700 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400701}
702
npujar467fe752020-01-16 20:17:45 +0530703func (dMgr *DeviceManager) reconcileChildDevices(ctx context.Context, parentDeviceID string) error {
704 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500705 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400706 for _, port := range parentDevice.Ports {
707 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530708 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
709 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400710 }
711 }
712 }
713 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500714 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400715 return status.Errorf(codes.Aborted, "errors-%s", res)
716 }
717 }
718 return nil
719}
720
npujar467fe752020-01-16 20:17:45 +0530721func (dMgr *DeviceManager) updateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
Mahir Gunyel8e2707d2019-07-25 00:36:21 -0700722 log.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530723 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
724 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400725 }
726 return status.Errorf(codes.NotFound, "%s", device.Id)
727}
728
npujar467fe752020-01-16 20:17:45 +0530729func (dMgr *DeviceManager) addPort(ctx context.Context, deviceID string, port *voltha.Port) error {
730 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530731 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530732 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400733 return err
734 }
735 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530736 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400737 for _, peerPort := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530738 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
739 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400740 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
741 return err
742 }
743 }
744 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400745 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
746 // then a logical port will be added to the logical device and the device graph generated. If the port is a
747 // PON port then only the device graph will be generated.
npujar467fe752020-01-16 20:17:45 +0530748 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530749 go func() {
npujar467fe752020-01-16 20:17:45 +0530750 err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port)
npujar1d86a522019-11-14 17:11:16 +0530751 if err != nil {
752 log.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
753 }
754 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400755 } else {
npujar1d86a522019-11-14 17:11:16 +0530756 log.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400757 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400758 }
khenaidoo92e62c52018-10-03 14:02:54 -0400759 return nil
khenaidoob9203542018-09-17 22:56:37 -0400760 }
npujar1d86a522019-11-14 17:11:16 +0530761 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400762}
763
npujar467fe752020-01-16 20:17:45 +0530764func (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 +0000765 log.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530766 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
767 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400768 }
npujar1d86a522019-11-14 17:11:16 +0530769 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400770}
771
npujar467fe752020-01-16 20:17:45 +0530772func (dMgr *DeviceManager) deleteFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530773 log.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530774 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
775 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400776 }
npujar1d86a522019-11-14 17:11:16 +0530777 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400778}
779
npujar467fe752020-01-16 20:17:45 +0530780func (dMgr *DeviceManager) updateFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530781 log.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530782 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
783 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400784 }
npujar1d86a522019-11-14 17:11:16 +0530785 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400786}
787
khenaidoob3127472019-07-24 21:04:55 -0400788// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
789// following a user action
790func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
791 var res interface{}
792 if pmConfigs.Id == "" {
793 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
npujar467fe752020-01-16 20:17:45 +0530794 } else if agent := dMgr.getDeviceAgent(ctx, pmConfigs.Id); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400795 res = agent.updatePmConfigs(ctx, pmConfigs)
796 } else {
797 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
798 }
799 sendResponse(ctx, ch, res)
800}
801
802// initPmConfigs initialize the pm configs as defined by the adapter.
npujar467fe752020-01-16 20:17:45 +0530803func (dMgr *DeviceManager) initPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400804 if pmConfigs.Id == "" {
805 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
806 }
npujar467fe752020-01-16 20:17:45 +0530807 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
808 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400809 }
npujar1d86a522019-11-14 17:11:16 +0530810 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400811}
812
npujar1d86a522019-11-14 17:11:16 +0530813func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
npujar467fe752020-01-16 20:17:45 +0530814 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400815 return agent.listPmConfigs(ctx)
816 }
npujar1d86a522019-11-14 17:11:16 +0530817 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400818}
819
npujar1d86a522019-11-14 17:11:16 +0530820func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
821 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530822 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400823 return agent.getSwitchCapability(ctx)
824 }
npujar1d86a522019-11-14 17:11:16 +0530825 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400826}
827
npujar1d86a522019-11-14 17:11:16 +0530828func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
829 log.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530830 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400831 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400832 }
npujar1d86a522019-11-14 17:11:16 +0530833 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400834}
835
npujar1d86a522019-11-14 17:11:16 +0530836func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
837 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530838 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400839 return agent.getPortCapability(ctx, portNo)
840 }
npujar1d86a522019-11-14 17:11:16 +0530841 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400842}
843
npujar467fe752020-01-16 20:17:45 +0530844func (dMgr *DeviceManager) updateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530845 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530846 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
847 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400848 }
npujar1d86a522019-11-14 17:11:16 +0530849 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400850}
851
npujar467fe752020-01-16 20:17:45 +0530852func (dMgr *DeviceManager) updateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530853 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400854 var parentDevice *voltha.Device
855 var err error
npujar467fe752020-01-16 20:17:45 +0530856 if parentDevice, err = dMgr.GetDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400857 return status.Errorf(codes.Aborted, "%s", err.Error())
858 }
859 var childDeviceIds []string
860 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
861 return status.Errorf(codes.Aborted, "%s", err.Error())
862 }
863 if len(childDeviceIds) == 0 {
864 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
865 }
npujar1d86a522019-11-14 17:11:16 +0530866 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530867 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
868 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530869 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400870 }
871 }
872 }
873 return nil
874}
875
npujar467fe752020-01-16 20:17:45 +0530876func (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 +0530877 log.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530878 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
879 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530880 log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400881 return err
882 }
883 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800884 // Do this for NNI and UNIs only. PON ports are not known by logical device
885 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
886 go func() {
887 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
888 if err != nil {
889 // While we want to handle (catch) and log when
890 // an update to a port was not able to be
891 // propagated to the logical port, we can report
892 // it as a warning and not an error because it
893 // doesn't stop or modify processing.
894 // TODO: VOL-2707
895 log.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
896 }
897 }()
898 }
khenaidoo442e7c72020-03-10 16:13:48 -0400899 return nil
khenaidoob9203542018-09-17 22:56:37 -0400900 }
npujar1d86a522019-11-14 17:11:16 +0530901 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400902}
903
npujar467fe752020-01-16 20:17:45 +0530904func (dMgr *DeviceManager) deleteAllPorts(ctx context.Context, deviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530905 log.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530906 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
907 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400908 return err
909 }
910 // Notify the logical device manager to remove all logical ports, if needed.
911 // At this stage the device itself may gave been deleted already at a deleteAllPorts
912 // typically is part of a device deletion phase.
npujar467fe752020-01-16 20:17:45 +0530913 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530914 go func() {
npujar467fe752020-01-16 20:17:45 +0530915 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530916 if err != nil {
917 log.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
918 }
919 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400920 } else {
npujar1d86a522019-11-14 17:11:16 +0530921 log.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400922 return err
923 }
924 return nil
925 }
npujar1d86a522019-11-14 17:11:16 +0530926 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400927}
928
khenaidoo3ab34882019-05-02 21:33:30 -0400929//updatePortsState updates all ports on the device
npujar467fe752020-01-16 20:17:45 +0530930func (dMgr *DeviceManager) updatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530931 log.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400932
npujar467fe752020-01-16 20:17:45 +0530933 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400934 switch state {
935 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500936 if err := agent.updatePortsOperState(ctx, state); err != nil {
937 log.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400938 return err
939 }
940 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500941 if err := agent.updatePortsOperState(ctx, state); err != nil {
942 log.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400943 return err
944 }
945 default:
946 return status.Error(codes.Unimplemented, "state-change-not-implemented")
947 }
948 // Notify the logical device about the state change
npujar467fe752020-01-16 20:17:45 +0530949 device, err := dMgr.GetDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530950 if err != nil {
951 log.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400952 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400953 }
kesavandbc2d1622020-01-21 00:42:01 -0500954 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530955 log.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
956 return err
957 }
958 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400959 }
npujar1d86a522019-11-14 17:11:16 +0530960 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400961}
962
npujar467fe752020-01-16 20:17:45 +0530963func (dMgr *DeviceManager) childDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530964 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
965 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 -0700966
npujar1d86a522019-11-14 17:11:16 +0530967 if deviceType == "" && vendorID != "" {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700968 log.Debug("device-type-is-nil-fetching-device-type")
npujar467fe752020-01-16 20:17:45 +0530969 deviceTypesIf, err := dMgr.adapterMgr.clusterDataProxy.List(ctx, "/device_types", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530970 if err != nil {
971 log.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
972 return nil, err
973 }
974 if deviceTypesIf != nil {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700975 OLoop:
976 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
977 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
978 for _, v := range dType.VendorIds {
npujar1d86a522019-11-14 17:11:16 +0530979 if v == vendorID {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700980 deviceType = dType.Adapter
981 break OLoop
982 }
983 }
984 }
985 }
986 }
987 }
988 //if no match found for the vendorid,report adapter with the custom error message
989 if deviceType == "" {
npujar1d86a522019-11-14 17:11:16 +0530990 log.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
991 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700992 }
khenaidoob9203542018-09-17 22:56:37 -0400993
994 // Create the ONU device
995 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400996 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530997 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400998 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530999 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -05001000 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -04001001 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001002
khenaidoo442e7c72020-03-10 16:13:48 -04001003 // Get parent device type
1004 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
1005 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +05301006 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001007 }
khenaidoo442e7c72020-03-10 16:13:48 -04001008 if pAgent.deviceType == "" {
1009 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
1010 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001011
npujar467fe752020-01-16 20:17:45 +05301012 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
npujar1d86a522019-11-14 17:11:16 +05301013 log.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001014 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001015 }
1016
khenaidoo442e7c72020-03-10 16:13:48 -04001017 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001018
1019 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -04001020 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -04001021 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001022 if err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -04001023 log.Errorw("error-starting-child-device", log.Fields{"parent-device-id": childDevice.ParentId, "child-device-id": agent.deviceID, "error": err})
Scott Baker80678602019-11-14 16:57:36 -08001024 return nil, err
1025 }
khenaidoo442e7c72020-03-10 16:13:48 -04001026 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001027
khenaidoo09771ef2019-10-11 14:25:02 -04001028 // Since this Core has handled this request then it therefore owns this child device. Set the
1029 // ownership of this device to this Core
npujar467fe752020-01-16 20:17:45 +05301030 _, err = dMgr.core.deviceOwnership.OwnedByMe(ctx, &utils.DeviceID{ID: agent.deviceID})
npujar1d86a522019-11-14 17:11:16 +05301031 if err != nil {
1032 log.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
1033 }
khenaidoo09771ef2019-10-11 14:25:02 -04001034
khenaidoob9203542018-09-17 22:56:37 -04001035 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301036 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301037 go func() {
npujar467fe752020-01-16 20:17:45 +05301038 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301039 if err != nil {
1040 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1041 }
1042 }()
khenaidoob9203542018-09-17 22:56:37 -04001043 }
1044
khenaidoo79232702018-12-04 11:00:41 -05001045 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301046 go func() {
1047 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1048 if err != nil {
1049 log.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
1050 }
1051 }()
khenaidoo79232702018-12-04 11:00:41 -05001052
Scott Baker80678602019-11-14 16:57:36 -08001053 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001054}
1055
npujar467fe752020-01-16 20:17:45 +05301056func (dMgr *DeviceManager) processTransition(ctx context.Context, previous *voltha.Device, current *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001057 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -04001058 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
1059 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -05001060 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001061 return nil
khenaidoob9203542018-09-17 22:56:37 -04001062 }
khenaidoo442e7c72020-03-10 16:13:48 -04001063 log.Debugw("handler-found", log.Fields{"num-expectedHandlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -04001064 for _, handler := range handlers {
1065 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
khenaidoo442e7c72020-03-10 16:13:48 -04001066 if err := handler(ctx, current, previous); err != nil {
khenaidoo6d62c002019-05-15 21:57:03 -04001067 log.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001068 return err
1069 }
1070 }
khenaidoob9203542018-09-17 22:56:37 -04001071 return nil
1072}
1073
npujar467fe752020-01-16 20:17:45 +05301074func (dMgr *DeviceManager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
npujar1d86a522019-11-14 17:11:16 +05301075 log.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301076 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1077 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001078 }
npujar1d86a522019-11-14 17:11:16 +05301079 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001080}
1081
npujar1d86a522019-11-14 17:11:16 +05301082// PacketIn receives packet from adapter
npujar467fe752020-01-16 20:17:45 +05301083func (dMgr *DeviceManager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
npujar1d86a522019-11-14 17:11:16 +05301084 log.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001085 // Get the logical device Id based on the deviceId
1086 var device *voltha.Device
1087 var err error
npujar467fe752020-01-16 20:17:45 +05301088 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301089 log.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001090 return err
1091 }
khenaidoo43c82122018-11-22 18:38:28 -05001092 if !device.Root {
npujar1d86a522019-11-14 17:11:16 +05301093 log.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
1094 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001095 }
1096
npujar467fe752020-01-16 20:17:45 +05301097 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001098 return err
1099 }
1100 return nil
1101}
1102
npujar467fe752020-01-16 20:17:45 +05301103func (dMgr *DeviceManager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
npujar1d86a522019-11-14 17:11:16 +05301104 log.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301105 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1106 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001107 }
1108 return status.Errorf(codes.NotFound, "%s", device.Id)
1109}
1110
npujar1d86a522019-11-14 17:11:16 +05301111// CreateLogicalDevice creates logical device in core
khenaidoo442e7c72020-03-10 16:13:48 -04001112func (dMgr *DeviceManager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001113 log.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001114 // Verify whether the logical device has already been created
1115 if cDevice.ParentId != "" {
1116 log.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
1117 return nil
1118 }
khenaidoob9203542018-09-17 22:56:37 -04001119 var err error
npujar467fe752020-01-16 20:17:45 +05301120 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001121 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
1122 return err
1123 }
khenaidoob9203542018-09-17 22:56:37 -04001124 return nil
1125}
1126
npujar1d86a522019-11-14 17:11:16 +05301127// DeleteLogicalDevice deletes logical device from core
khenaidoo442e7c72020-03-10 16:13:48 -04001128func (dMgr *DeviceManager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001129 log.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001130 var err error
npujar467fe752020-01-16 20:17:45 +05301131 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001132 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
1133 return err
1134 }
1135 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301136 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301137 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001138 return nil
1139}
1140
npujar1d86a522019-11-14 17:11:16 +05301141// DeleteLogicalPort removes the logical port associated with a device
npujar467fe752020-01-16 20:17:45 +05301142func (dMgr *DeviceManager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -04001143 log.Info("deleteLogicalPort")
1144 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001145 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301146 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301147 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001148 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001149 return err
1150 }
npujar467fe752020-01-16 20:17:45 +05301151 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001152 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001153 return err
1154 }
khenaidoo92e62c52018-10-03 14:02:54 -04001155 return nil
1156}
1157
npujar1d86a522019-11-14 17:11:16 +05301158// DeleteLogicalPorts removes the logical ports associated with that deviceId
khenaidoo442e7c72020-03-10 16:13:48 -04001159func (dMgr *DeviceManager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
1160 log.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
1161 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
1162 log.Warnw("deleteLogical-ports-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001163 return err
1164 }
1165 return nil
1166}
1167
npujar467fe752020-01-16 20:17:45 +05301168func (dMgr *DeviceManager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001169 // Sanity check
1170 if childDevice.Root {
1171 // childDevice is the parent device
1172 return childDevice
1173 }
npujar467fe752020-01-16 20:17:45 +05301174 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001175 return parentDevice
1176}
1177
khenaidoo0a822f92019-05-08 15:15:57 -04001178//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1179//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar467fe752020-01-16 20:17:45 +05301180func (dMgr *DeviceManager) childDevicesLost(ctx context.Context, parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001181 log.Debug("childDevicesLost")
1182 var err error
1183 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301184 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301185 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001186 return err
1187 }
khenaidoo442e7c72020-03-10 16:13:48 -04001188 return dMgr.DisableAllChildDevices(ctx, parentDevice, nil)
khenaidoo0a822f92019-05-08 15:15:57 -04001189}
1190
1191//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1192// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar467fe752020-01-16 20:17:45 +05301193func (dMgr *DeviceManager) childDevicesDetected(ctx context.Context, parentDeviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001194 log.Debug("childDevicesDetected")
1195 var err error
1196 var parentDevice *voltha.Device
1197 var childDeviceIds []string
1198
npujar467fe752020-01-16 20:17:45 +05301199 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301200 log.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001201 return err
1202 }
1203
1204 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1205 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1206 }
1207 if len(childDeviceIds) == 0 {
1208 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
1209 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001210 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301211 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301212 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001213 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301214 go func() {
npujar467fe752020-01-16 20:17:45 +05301215 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301216 if err != nil {
1217 log.Errorw("unable-to-enable-device", log.Fields{"error": err})
1218 }
1219 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001220 } else {
npujar1d86a522019-11-14 17:11:16 +05301221 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
1222 log.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001223 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001224 }
1225 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001226 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001227 return err
1228 }
1229 return nil
1230}
1231
khenaidoo4d4802d2018-10-04 21:59:49 -04001232/*
1233All the functions below are callback functions where they are invoked with the latest and previous data. We can
1234therefore use the data as is without trying to get the latest from the model.
1235*/
1236
khenaidoo0a822f92019-05-08 15:15:57 -04001237//DisableAllChildDevices is invoked as a callback when the parent device is disabled
khenaidoo442e7c72020-03-10 16:13:48 -04001238func (dMgr *DeviceManager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device, parentPrevDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001239 log.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001240 var childDeviceIds []string
1241 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001242 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1243 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001244 }
1245 if len(childDeviceIds) == 0 {
khenaidoo442e7c72020-03-10 16:13:48 -04001246 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001247 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001248 allChildDisable := true
npujar1d86a522019-11-14 17:11:16 +05301249 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301250 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1251 if err = agent.disableDevice(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301252 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001253 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -04001254 }
1255 }
1256 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001257 if !allChildDisable {
1258 return err
1259 }
khenaidoo92e62c52018-10-03 14:02:54 -04001260 return nil
1261}
1262
khenaidoo0a822f92019-05-08 15:15:57 -04001263//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
khenaidoo442e7c72020-03-10 16:13:48 -04001264func (dMgr *DeviceManager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device, parentPrevDevice *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001265 log.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001266 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001267 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001268 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1269 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001270 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001271 if len(childDeviceIds) == 0 {
khenaidoo442e7c72020-03-10 16:13:48 -04001272 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001273 }
1274 allChildDeleted := true
npujar1d86a522019-11-14 17:11:16 +05301275 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301276 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1277 if err = agent.deleteDevice(ctx); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301278 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001279 allChildDeleted = false
khenaidoo4d4802d2018-10-04 21:59:49 -04001280 }
khenaidoo49085352020-01-13 19:15:43 -05001281 // No further action is required here. The deleteDevice will change the device state where the resulting
1282 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001283 }
1284 }
1285 if !allChildDeleted {
1286 return err
1287 }
1288 return nil
1289}
1290
Hardik Windlassc704def2020-02-26 18:23:19 +00001291//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
khenaidoo442e7c72020-03-10 16:13:48 -04001292func (dMgr *DeviceManager) DeleteAllUNILogicalPorts(ctx context.Context, curr *voltha.Device, prev *voltha.Device) error {
1293 log.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": curr.Id})
1294 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, curr); err != nil {
Hardik Windlassc704def2020-02-26 18:23:19 +00001295 return err
1296 }
1297 return nil
1298}
1299
khenaidoo4d4802d2018-10-04 21:59:49 -04001300//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1301func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
1302 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001303 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001304 if parentDevice != nil {
1305 for _, port := range parentDevice.Ports {
1306 for _, peer := range port.Peers {
1307 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1308 }
khenaidoo92e62c52018-10-03 14:02:54 -04001309 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001310 log.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001311 }
1312 return childDeviceIds, nil
1313}
1314
khenaidoo297cd252019-02-07 22:10:23 -05001315//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar467fe752020-01-16 20:17:45 +05301316func (dMgr *DeviceManager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
npujar1d86a522019-11-14 17:11:16 +05301317 log.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301318 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001319 childDevices := make([]*voltha.Device, 0)
1320 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301321 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301322 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001323 childDevices = append(childDevices, d)
1324 }
1325 }
1326 }
1327 return &voltha.Devices{Items: childDevices}, nil
1328 }
npujar1d86a522019-11-14 17:11:16 +05301329 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001330}
1331
npujar1d86a522019-11-14 17:11:16 +05301332// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
khenaidoo442e7c72020-03-10 16:13:48 -04001333func (dMgr *DeviceManager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001334 log.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301335 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -04001336 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
1337 return err
1338 }
1339 return nil
1340}
1341
khenaidoof5a5bfa2019-01-23 22:20:29 -05001342func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1343 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1344 var res interface{}
1345 var err error
npujar467fe752020-01-16 20:17:45 +05301346 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001347 if res, err = agent.downloadImage(ctx, img); err != nil {
1348 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
1349 res = err
1350 }
1351 } else {
1352 res = status.Errorf(codes.NotFound, "%s", img.Id)
1353 }
1354 sendResponse(ctx, ch, res)
1355}
1356
1357func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1358 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1359 var res interface{}
1360 var err error
npujar467fe752020-01-16 20:17:45 +05301361 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001362 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
1363 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1364 res = err
1365 }
1366 } else {
1367 res = status.Errorf(codes.NotFound, "%s", img.Id)
1368 }
1369 sendResponse(ctx, ch, res)
1370}
1371
1372func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1373 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1374 var res interface{}
1375 var err error
npujar467fe752020-01-16 20:17:45 +05301376 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001377 if res, err = agent.activateImage(ctx, img); err != nil {
1378 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
1379 res = err
1380 }
1381 } else {
1382 res = status.Errorf(codes.NotFound, "%s", img.Id)
1383 }
1384 sendResponse(ctx, ch, res)
1385}
1386
1387func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1388 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1389 var res interface{}
1390 var err error
npujar467fe752020-01-16 20:17:45 +05301391 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001392 if res, err = agent.revertImage(ctx, img); err != nil {
1393 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
1394 res = err
1395 }
1396 } else {
1397 res = status.Errorf(codes.NotFound, "%s", img.Id)
1398 }
1399 sendResponse(ctx, ch, res)
1400}
1401
1402func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1403 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
1404 var res interface{}
1405 var err error
npujar467fe752020-01-16 20:17:45 +05301406 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001407 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
1408 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
1409 res = err
1410 }
1411 } else {
1412 res = status.Errorf(codes.NotFound, "%s", img.Id)
1413 }
1414 sendResponse(ctx, ch, res)
1415}
1416
npujar467fe752020-01-16 20:17:45 +05301417func (dMgr *DeviceManager) updateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001418 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301419 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1420 if err := agent.updateImageDownload(ctx, img); err != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001421 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
1422 return err
1423 }
1424 } else {
1425 return status.Errorf(codes.NotFound, "%s", img.Id)
1426 }
1427 return nil
1428}
1429
1430func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1431 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301432 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001433 return agent.getImageDownload(ctx, img)
1434 }
1435 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1436}
1437
npujar1d86a522019-11-14 17:11:16 +05301438func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
1439 log.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301440 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301441 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001442 }
npujar1d86a522019-11-14 17:11:16 +05301443 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001444}
1445
khenaidoo442e7c72020-03-10 16:13:48 -04001446func (dMgr *DeviceManager) NotifyInvalidTransition(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001447 log.Errorw("NotifyInvalidTransition", log.Fields{
khenaidoo442e7c72020-03-10 16:13:48 -04001448 "device": cDevice.Id,
1449 "prev-admin-state": pDevice.AdminState,
1450 "prev-oper-state": pDevice.OperStatus,
1451 "prev-conn-state": pDevice.ConnectStatus,
1452 "curr-admin-state": cDevice.AdminState,
1453 "curr-oper-state": cDevice.OperStatus,
1454 "curr-conn-state": cDevice.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001455 })
khenaidoo0a822f92019-05-08 15:15:57 -04001456 //TODO: notify over kafka?
1457 return nil
1458}
1459
khenaidoob9203542018-09-17 22:56:37 -04001460func funcName(f interface{}) string {
1461 p := reflect.ValueOf(f).Pointer()
1462 rf := runtime.FuncForPC(p)
1463 return rf.Name()
1464}
1465
npujar1d86a522019-11-14 17:11:16 +05301466// UpdateDeviceAttribute updates value of particular device attribute
npujar467fe752020-01-16 20:17:45 +05301467func (dMgr *DeviceManager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301468 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
npujar467fe752020-01-16 20:17:45 +05301469 agent.(*DeviceAgent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001470 }
1471}
1472
npujar1d86a522019-11-14 17:11:16 +05301473// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +05301474func (dMgr *DeviceManager) GetParentDeviceID(ctx context.Context, deviceID string) string {
1475 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001476 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001477 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001478 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001479 return ""
khenaidoob9203542018-09-17 22:56:37 -04001480}
serkant.uluderya334479d2019-04-10 08:26:15 -07001481
1482func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1483 log.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
1484 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1485 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1486 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301487 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001488 res = agent.simulateAlarm(ctx, simulatereq)
khenaidoo442e7c72020-03-10 16:13:48 -04001489 log.Debugw("simulateAlarm-result", log.Fields{"result": res})
serkant.uluderya334479d2019-04-10 08:26:15 -07001490 }
1491 //TODO CLI always get successful response
1492 sendResponse(ctx, ch, res)
1493}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001494
npujar467fe752020-01-16 20:17:45 +05301495func (dMgr *DeviceManager) updateDeviceReason(ctx context.Context, deviceID string, reason string) error {
npujar1d86a522019-11-14 17:11:16 +05301496 log.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301497 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1498 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001499 }
npujar1d86a522019-11-14 17:11:16 +05301500 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001501}
kesavandbc2d1622020-01-21 00:42:01 -05001502
1503func (dMgr *DeviceManager) enablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1504 log.Debugw("enablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
1505 var res interface{}
1506 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1507 res = agent.enablePort(ctx, port)
1508 log.Debugw("enablePort-result", log.Fields{"result": res})
1509 } else {
1510 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1511 }
1512
1513 sendResponse(ctx, ch, res)
1514}
1515
1516func (dMgr *DeviceManager) disablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1517 log.Debugw("disablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
1518 var res interface{}
1519 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1520 res = agent.disablePort(ctx, port)
1521 log.Debugw("disablePort-result", log.Fields{"result": res})
1522 } else {
1523 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1524 }
1525
1526 sendResponse(ctx, ch, res)
1527}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001528
khenaidoo442e7c72020-03-10 16:13:48 -04001529// childDeviceLost calls parent adapter to delete child device and all its references
1530func (dMgr *DeviceManager) ChildDeviceLost(ctx context.Context, curr *voltha.Device, prev *voltha.Device) error {
1531 log.Debugw("childDeviceLost", log.Fields{"device-id": curr.Id})
1532 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
1533 return parentAgent.ChildDeviceLost(ctx, curr)
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001534 }
khenaidoo442e7c72020-03-10 16:13:48 -04001535 return status.Errorf(codes.NotFound, "%s", curr.Id)
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001536}