blob: e8b79a699d8e3a02fcb99e64664660d086a34f69 [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) {
Girish Kumarf56a4682020-03-20 20:07:46 +000075 logger.Info("starting-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040076 dMgr.logicalDeviceMgr = logicalDeviceMgr
77 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070078 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
Girish Kumarf56a4682020-03-20 20:07:46 +000079 logger.Info("device-manager-started")
khenaidoob9203542018-09-17 22:56:37 -040080}
81
khenaidoo4d4802d2018-10-04 21:59:49 -040082func (dMgr *DeviceManager) stop(ctx context.Context) {
Girish Kumarf56a4682020-03-20 20:07:46 +000083 logger.Info("stopping-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040084 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070085 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
Girish Kumarf56a4682020-03-20 20:07:46 +000086 logger.Info("device-manager-stopped")
khenaidoob9203542018-09-17 22:56:37 -040087}
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
Girish Kumarf56a4682020-03-20 20:07:46 +000094 logger.Debugw("sendResponse", log.Fields{"result": result})
khenaidoob9203542018-09-17 22:56:37 -040095 } else {
96 // Should the transaction be reverted back?
Girish Kumarf56a4682020-03-20 20:07:46 +000097 logger.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
khenaidoob9203542018-09-17 22:56:37 -040098 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000135 logger.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530136 }
137 }()
138 return agent.(*DeviceAgent)
139 }
140 //TODO: Change the return params to return an error as well
Girish Kumarf56a4682020-03-20 20:07:46 +0000141 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000160 logger.Errorf("Failed to fetch parent device info")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530161 sendResponse(ctx, ch, err)
162 return
163 }
164 if deviceExist {
Girish Kumarf56a4682020-03-20 20:07:46 +0000165 logger.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530166 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
167 return
168 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000169 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000177 logger.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{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000187 logger.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)
Girish Kumarf56a4682020-03-20 20:07:46 +0000191 logger.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{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000200 logger.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)
Girish Kumarf56a4682020-03-20 20:07:46 +0000204 logger.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{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000213 logger.Debugw("rebootDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400214 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)
Girish Kumarf56a4682020-03-20 20:07:46 +0000217 logger.Debugw("rebootDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400218 } 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{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000225 logger.Debugw("deleteDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400226 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)
Girish Kumarf56a4682020-03-20 20:07:46 +0000229 logger.Debugw("deleteDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400230 } 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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000240 logger.Infow("stopManagingDevice", log.Fields{"deviceId": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400241 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000248 logger.Errorw("unable-to-abandon-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530249 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000255 logger.Warnw("unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400256 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000261 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000269 logger.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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000276 logger.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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000285 logger.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
npujar1d86a522019-11-14 17:11:16 +0530286 "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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000298 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530299 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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000310 logger.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530311 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500312 }
313 }
314
315 foundSerialNumber := false
316 if searchDevice.SerialNumber == serialNumber {
Girish Kumarf56a4682020-03-20 20:07:46 +0000317 logger.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500318 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000337 logger.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500338 return foundChildDevice, nil
339 }
340
Girish Kumarf56a4682020-03-20 20:07:46 +0000341 logger.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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000348 logger.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500349
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000360 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500361 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000375 logger.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500376 return foundChildDevice, nil
377 }
378
Girish Kumarf56a4682020-03-20 20:07:46 +0000379 logger.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500380 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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000401 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000405 logger.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530406 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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000413 logger.Debugw("loading-device-from-Model", log.Fields{"id": device.Id})
khenaidoo442e7c72020-03-10 16:13:48 -0400414 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000416 logger.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 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000424 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000433 logger.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530434 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000456 logger.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530457 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000481 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000484 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000489 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000518 logger.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500519 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000524 logger.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500525 }
526 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000527 logger.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500528 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000533 logger.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500534 return err
535 }
536 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000537 logger.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500538 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000539 logger.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500540 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000550 logger.Debug("load...")
khenaidoo297cd252019-02-07 22:10:23 -0500551 // 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000572 logger.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500573 return err
574 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000575 logger.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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000587 logger.Debug("ListDeviceIDs")
khenaidoo7ccedd52018-12-14 16:48:54 -0500588 // 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{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000595 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000603 logger.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400604 } 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000627 logger.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400628
629 // Let's reconcile the device managed by this Core only
630 rootDeviceIds := dMgr.core.deviceOwnership.GetAllDeviceIdsOwnedByMe()
631 if len(rootDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000632 logger.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400633 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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000641 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000644 logger.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400645 }
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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000653 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000656 logger.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400657 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000675 logger.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400676 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000722 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000740 logger.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
khenaidoo92e62c52018-10-03 14:02:54 -0400741 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000752 logger.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530753 }
754 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400755 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000756 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000765 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000773 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000781 logger.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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000821 logger.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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000829 logger.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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000837 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000845 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000853 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000864 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400865 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000877 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000880 logger.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
Girish Kumarf56a4682020-03-20 20:07:46 +0000895 logger.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800896 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000905 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000917 logger.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530918 }
919 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400920 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000921 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000931 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000937 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000942 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000951 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000955 logger.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530956 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) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000965 logger.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 != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000968 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000971 logger.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530972 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 == "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000990 logger.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +0530991 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001013 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001023 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001032 logger.Errorw("unable-to-find-core-instance-active-owns-this-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301033 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001040 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301041 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001049 logger.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301050 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001060 logger.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 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001063 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001065 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
khenaidoo442e7c72020-03-10 16:13:48 -04001066 if err := handler(ctx, current, previous); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001067 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001075 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001084 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001089 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001093 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301094 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001104 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001113 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001114 // Verify whether the logical device has already been created
1115 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001116 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001117 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001121 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001122 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001129 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001132 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001133 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001143 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001144 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001148 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001152 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001160 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001161 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001162 // Just log the error. The logical device or port may already have been deleted before this callback is invoked.
Girish Kumarf56a4682020-03-20 20:07:46 +00001163 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001164 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001181 logger.Debug("childDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001182 var err error
1183 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301184 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001185 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001194 logger.Debug("childDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001195 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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001200 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001208 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001209 }
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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001217 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301218 }
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)
Girish Kumarf56a4682020-03-20 20:07:46 +00001222 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001239 logger.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 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001246 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001247 }
npujar1d86a522019-11-14 17:11:16 +05301248 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301249 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1250 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001251 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001252 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001253 }
1254 }
1255 }
1256 return nil
1257}
1258
khenaidoo0a822f92019-05-08 15:15:57 -04001259//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
khenaidoo442e7c72020-03-10 16:13:48 -04001260func (dMgr *DeviceManager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device, parentPrevDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001261 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001262 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001263 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001264 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1265 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001266 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001267 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001268 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001269 }
npujar1d86a522019-11-14 17:11:16 +05301270 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301271 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1272 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001273 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001274 }
khenaidoo49085352020-01-13 19:15:43 -05001275 // No further action is required here. The deleteDevice will change the device state where the resulting
1276 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001277 }
1278 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001279 return nil
1280}
1281
Hardik Windlassc704def2020-02-26 18:23:19 +00001282//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
khenaidoo442e7c72020-03-10 16:13:48 -04001283func (dMgr *DeviceManager) DeleteAllUNILogicalPorts(ctx context.Context, curr *voltha.Device, prev *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001284 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": curr.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001285 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, curr); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001286 // Just log the error and let the remaining pipeline proceed - ports may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001287 logger.Warnw("delete-all-uni-logical-ports-failed", log.Fields{"parent-device-id": curr.Id, "error": err})
Hardik Windlassc704def2020-02-26 18:23:19 +00001288 }
1289 return nil
1290}
1291
Girish Gowdra408cd962020-03-11 14:31:31 -07001292//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
1293func (dMgr *DeviceManager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device, prev *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001294 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001295 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001296 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001297 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001298 }
1299 return nil
1300}
1301
1302//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
1303func (dMgr *DeviceManager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device, prev *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001304 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001305 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1306 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001307 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001308 return err
1309 }
1310 return nil
1311 }
1312 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1313}
1314
khenaidoo4d4802d2018-10-04 21:59:49 -04001315//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1316func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001317 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001318 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001319 if parentDevice != nil {
1320 for _, port := range parentDevice.Ports {
1321 for _, peer := range port.Peers {
1322 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1323 }
khenaidoo92e62c52018-10-03 14:02:54 -04001324 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001325 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001326 }
1327 return childDeviceIds, nil
1328}
1329
khenaidoo297cd252019-02-07 22:10:23 -05001330//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar467fe752020-01-16 20:17:45 +05301331func (dMgr *DeviceManager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001332 logger.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301333 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001334 childDevices := make([]*voltha.Device, 0)
1335 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301336 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301337 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001338 childDevices = append(childDevices, d)
1339 }
1340 }
1341 }
1342 return &voltha.Devices{Items: childDevices}, nil
1343 }
npujar1d86a522019-11-14 17:11:16 +05301344 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001345}
1346
npujar1d86a522019-11-14 17:11:16 +05301347// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
khenaidoo442e7c72020-03-10 16:13:48 -04001348func (dMgr *DeviceManager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001349 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301350 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001351 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001352 return err
1353 }
1354 return nil
1355}
1356
khenaidoof5a5bfa2019-01-23 22:20:29 -05001357func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001358 logger.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001359 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.downloadImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001363 logger.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001364 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) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001373 logger.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001374 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.cancelImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001378 logger.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001379 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) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001388 logger.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001389 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.activateImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001393 logger.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001394 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) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001403 logger.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001404 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.revertImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001408 logger.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001409 res = err
1410 }
1411 } else {
1412 res = status.Errorf(codes.NotFound, "%s", img.Id)
1413 }
1414 sendResponse(ctx, ch, res)
1415}
1416
1417func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001418 logger.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001419 var res interface{}
1420 var err error
npujar467fe752020-01-16 20:17:45 +05301421 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001422 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001423 logger.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001424 res = err
1425 }
1426 } else {
1427 res = status.Errorf(codes.NotFound, "%s", img.Id)
1428 }
1429 sendResponse(ctx, ch, res)
1430}
1431
npujar467fe752020-01-16 20:17:45 +05301432func (dMgr *DeviceManager) updateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001433 logger.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301434 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1435 if err := agent.updateImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001436 logger.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001437 return err
1438 }
1439 } else {
1440 return status.Errorf(codes.NotFound, "%s", img.Id)
1441 }
1442 return nil
1443}
1444
1445func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001446 logger.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301447 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001448 return agent.getImageDownload(ctx, img)
1449 }
1450 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1451}
1452
npujar1d86a522019-11-14 17:11:16 +05301453func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001454 logger.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301455 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301456 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001457 }
npujar1d86a522019-11-14 17:11:16 +05301458 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001459}
1460
khenaidoo442e7c72020-03-10 16:13:48 -04001461func (dMgr *DeviceManager) NotifyInvalidTransition(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001462 logger.Errorw("NotifyInvalidTransition", log.Fields{
khenaidoo442e7c72020-03-10 16:13:48 -04001463 "device": cDevice.Id,
1464 "prev-admin-state": pDevice.AdminState,
1465 "prev-oper-state": pDevice.OperStatus,
1466 "prev-conn-state": pDevice.ConnectStatus,
1467 "curr-admin-state": cDevice.AdminState,
1468 "curr-oper-state": cDevice.OperStatus,
1469 "curr-conn-state": cDevice.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001470 })
khenaidoo0a822f92019-05-08 15:15:57 -04001471 //TODO: notify over kafka?
1472 return nil
1473}
1474
khenaidoob9203542018-09-17 22:56:37 -04001475func funcName(f interface{}) string {
1476 p := reflect.ValueOf(f).Pointer()
1477 rf := runtime.FuncForPC(p)
1478 return rf.Name()
1479}
1480
npujar1d86a522019-11-14 17:11:16 +05301481// UpdateDeviceAttribute updates value of particular device attribute
npujar467fe752020-01-16 20:17:45 +05301482func (dMgr *DeviceManager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301483 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
npujar467fe752020-01-16 20:17:45 +05301484 agent.(*DeviceAgent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001485 }
1486}
1487
npujar1d86a522019-11-14 17:11:16 +05301488// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +05301489func (dMgr *DeviceManager) GetParentDeviceID(ctx context.Context, deviceID string) string {
1490 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001491 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001492 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001493 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001494 return ""
khenaidoob9203542018-09-17 22:56:37 -04001495}
serkant.uluderya334479d2019-04-10 08:26:15 -07001496
1497func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001498 logger.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
serkant.uluderya334479d2019-04-10 08:26:15 -07001499 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1500 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1501 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301502 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001503 res = agent.simulateAlarm(ctx, simulatereq)
Girish Kumarf56a4682020-03-20 20:07:46 +00001504 logger.Debugw("simulateAlarm-result", log.Fields{"result": res})
serkant.uluderya334479d2019-04-10 08:26:15 -07001505 }
1506 //TODO CLI always get successful response
1507 sendResponse(ctx, ch, res)
1508}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001509
npujar467fe752020-01-16 20:17:45 +05301510func (dMgr *DeviceManager) updateDeviceReason(ctx context.Context, deviceID string, reason string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001511 logger.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301512 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1513 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001514 }
npujar1d86a522019-11-14 17:11:16 +05301515 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001516}
kesavandbc2d1622020-01-21 00:42:01 -05001517
1518func (dMgr *DeviceManager) enablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001519 logger.Debugw("enablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001520 var res interface{}
1521 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1522 res = agent.enablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001523 logger.Debugw("enablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001524 } else {
1525 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1526 }
1527
1528 sendResponse(ctx, ch, res)
1529}
1530
1531func (dMgr *DeviceManager) disablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001532 logger.Debugw("disablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001533 var res interface{}
1534 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1535 res = agent.disablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001536 logger.Debugw("disablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001537 } else {
1538 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1539 }
1540
1541 sendResponse(ctx, ch, res)
1542}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001543
khenaidoo442e7c72020-03-10 16:13:48 -04001544// childDeviceLost calls parent adapter to delete child device and all its references
1545func (dMgr *DeviceManager) ChildDeviceLost(ctx context.Context, curr *voltha.Device, prev *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001546 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001547 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001548 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1549 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001550 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001551 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001552 }
khenaidooe132f522020-03-20 15:23:15 -04001553 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1554 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001555}
onkarkundargi87285252020-01-27 11:34:52 +05301556
1557func (dMgr *DeviceManager) startOmciTest(ctx context.Context, omcitestrequest *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001558 logger.Debugw("Omci_test_Request", log.Fields{"device-id": omcitestrequest.Id, "uuid": omcitestrequest.Uuid})
onkarkundargi87285252020-01-27 11:34:52 +05301559 if agent := dMgr.getDeviceAgent(ctx, omcitestrequest.Id); agent != nil {
1560 res, err := agent.startOmciTest(ctx, omcitestrequest)
1561 if err != nil {
1562 return nil, err
1563 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001564 logger.Debugw("Omci_test_Response_result-device-magnager", log.Fields{"result": res})
onkarkundargi87285252020-01-27 11:34:52 +05301565 return res, nil
1566 }
1567 return nil, status.Errorf(codes.NotFound, "%s", omcitestrequest.Id)
1568}