blob: afe84e86841b9c90b1a9ae51a117e579cdff7f81 [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"
David Bainbridged1afd662020-03-26 18:27:41 -070022 "reflect"
23 "runtime"
24 "sync"
25 "time"
26
sbarbari17d7e222019-11-05 10:02:29 -050027 "github.com/opencord/voltha-go/db/model"
khenaidoo3d3b8c22019-05-22 18:10:39 -040028 "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080029 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
30 "github.com/opencord/voltha-lib-go/v3/pkg/log"
31 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
32 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
33 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
34 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040035 "google.golang.org/grpc/codes"
36 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040037)
38
npujar1d86a522019-11-14 17:11:16 +053039// DeviceManager represent device manager attributes
khenaidoob9203542018-09-17 22:56:37 -040040type DeviceManager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040041 deviceAgents sync.Map
42 rootDevices map[string]bool
43 lockRootDeviceMap sync.RWMutex
44 core *Core
45 adapterProxy *AdapterProxy
46 adapterMgr *AdapterManager
47 logicalDeviceMgr *LogicalDeviceManager
npujar467fe752020-01-16 20:17:45 +053048 kafkaICProxy kafka.InterContainerProxy
khenaidoo4c9e5592019-09-09 16:20:41 -040049 stateTransitions *TransitionMap
50 clusterDataProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053051 coreInstanceID string
khenaidoo4c9e5592019-09-09 16:20:41 -040052 exitChannel chan int
khenaidoo442e7c72020-03-10 16:13:48 -040053 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040054 devicesLoadingLock sync.RWMutex
55 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040056}
57
Richard Jankowski199fd862019-03-18 14:49:51 -040058func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040059 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040060 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040061 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040062 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040063 deviceMgr.kafkaICProxy = core.kmp
Kent Hagermana6d0c362019-07-30 12:50:21 -040064 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic)
npujar1d86a522019-11-14 17:11:16 +053065 deviceMgr.coreInstanceID = core.instanceID
Richard Jankowski199fd862019-03-18 14:49:51 -040066 deviceMgr.clusterDataProxy = core.clusterDataProxy
67 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040068 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
khenaidoo442e7c72020-03-10 16:13:48 -040069 deviceMgr.defaultTimeout = time.Duration(core.config.DefaultCoreTimeout) * time.Millisecond
khenaidoo4c9e5592019-09-09 16:20:41 -040070 deviceMgr.devicesLoadingLock = sync.RWMutex{}
71 deviceMgr.deviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040072 return &deviceMgr
73}
74
khenaidoo4d4802d2018-10-04 21:59:49 -040075func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
Girish Kumarf56a4682020-03-20 20:07:46 +000076 logger.Info("starting-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040077 dMgr.logicalDeviceMgr = logicalDeviceMgr
78 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070079 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
Girish Kumarf56a4682020-03-20 20:07:46 +000080 logger.Info("device-manager-started")
khenaidoob9203542018-09-17 22:56:37 -040081}
82
khenaidoo4d4802d2018-10-04 21:59:49 -040083func (dMgr *DeviceManager) stop(ctx context.Context) {
Girish Kumarf56a4682020-03-20 20:07:46 +000084 logger.Info("stopping-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040085 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070086 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
Girish Kumarf56a4682020-03-20 20:07:46 +000087 logger.Info("device-manager-stopped")
khenaidoob9203542018-09-17 22:56:37 -040088}
89
90func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
91 if ctx.Err() == nil {
92 // Returned response only of the ctx has not been cancelled/timeout/etc
93 // Channel is automatically closed when a context is Done
94 ch <- result
Girish Kumarf56a4682020-03-20 20:07:46 +000095 logger.Debugw("sendResponse", log.Fields{"result": result})
khenaidoob9203542018-09-17 22:56:37 -040096 } else {
97 // Should the transaction be reverted back?
Girish Kumarf56a4682020-03-20 20:07:46 +000098 logger.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
khenaidoob9203542018-09-17 22:56:37 -040099 }
100}
101
102func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530103 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
104 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -0400105 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400106 dMgr.lockRootDeviceMap.Lock()
107 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530108 dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400109
khenaidoob9203542018-09-17 22:56:37 -0400110}
111
khenaidoo4c9e5592019-09-09 16:20:41 -0400112func (dMgr *DeviceManager) deleteDeviceAgentFromMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530113 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400114 dMgr.lockRootDeviceMap.Lock()
115 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530116 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400117}
118
khenaidoo297cd252019-02-07 22:10:23 -0500119// 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 +0530120func (dMgr *DeviceManager) getDeviceAgent(ctx context.Context, deviceID string) *DeviceAgent {
npujar1d86a522019-11-14 17:11:16 +0530121 agent, ok := dMgr.deviceAgents.Load(deviceID)
122 if ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400123 return agent.(*DeviceAgent)
khenaidoob9203542018-09-17 22:56:37 -0400124 }
khenaidoo442e7c72020-03-10 16:13:48 -0400125 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530126 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530127 if err == nil {
128 agent, ok = dMgr.deviceAgents.Load(deviceID)
129 if !ok {
130 return nil
131 }
npujar1d86a522019-11-14 17:11:16 +0530132 return agent.(*DeviceAgent)
133 }
134 //TODO: Change the return params to return an error as well
Girish Kumarf56a4682020-03-20 20:07:46 +0000135 logger.Errorw("loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400136 return nil
137}
138
khenaidoo297cd252019-02-07 22:10:23 -0500139// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500140func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500141 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400142
143 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
144 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
145 return true
146 })
147
khenaidoo7ccedd52018-12-14 16:48:54 -0500148 return result
149}
150
khenaidoob9203542018-09-17 22:56:37 -0400151func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
npujar467fe752020-01-16 20:17:45 +0530152 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530153 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000154 logger.Errorf("Failed to fetch parent device info")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530155 sendResponse(ctx, ch, err)
156 return
157 }
158 if deviceExist {
Girish Kumarf56a4682020-03-20 20:07:46 +0000159 logger.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530160 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
161 return
162 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000163 logger.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400164
khenaidoo5e677ae2019-02-28 17:26:29 -0500165 // Ensure this device is set as root
166 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400167 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400168 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530169 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800170 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000171 logger.Errorw("Fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530172 sendResponse(ctx, ch, err)
Scott Baker80678602019-11-14 16:57:36 -0800173 return
174 }
khenaidoo442e7c72020-03-10 16:13:48 -0400175 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -0400176
Scott Baker80678602019-11-14 16:57:36 -0800177 sendResponse(ctx, ch, device)
khenaidoob9203542018-09-17 22:56:37 -0400178}
179
180func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000181 logger.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400182 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530183 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400184 res = agent.enableDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000185 logger.Debugw("EnableDevice-result", log.Fields{"result": res})
Hardik Windlassb9cfcb12020-02-03 15:59:46 +0000186 } else {
187 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400188 }
189
190 sendResponse(ctx, ch, res)
191}
192
khenaidoo92e62c52018-10-03 14:02:54 -0400193func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000194 logger.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400195 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530196 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400197 res = agent.disableDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000198 logger.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400199 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400200 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400201 }
khenaidoo92e62c52018-10-03 14:02:54 -0400202
203 sendResponse(ctx, ch, res)
204}
205
khenaidoo4d4802d2018-10-04 21:59:49 -0400206func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000207 logger.Debugw("rebootDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400208 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530209 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400210 res = agent.rebootDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000211 logger.Debugw("rebootDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400212 } else {
213 res = status.Errorf(codes.NotFound, "%s", id.Id)
214 }
215 sendResponse(ctx, ch, res)
216}
217
218func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000219 logger.Debugw("deleteDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400220 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530221 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400222 res = agent.deleteDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000223 logger.Debugw("deleteDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400224 } else {
225 res = status.Errorf(codes.NotFound, "%s", id.Id)
226 }
227 sendResponse(ctx, ch, res)
228}
229
khenaidoo6d62c002019-05-15 21:57:03 -0400230// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
231// This function is called only in the Core that does not own this device. In the Core that owns this device then a
232// deletion deletion also includes removal of any reference of this device.
npujar467fe752020-01-16 20:17:45 +0530233func (dMgr *DeviceManager) stopManagingDevice(ctx context.Context, id string) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000234 logger.Infow("stopManagingDevice", log.Fields{"deviceId": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400235 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530236 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400237 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700238 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400239 }
npujar467fe752020-01-16 20:17:45 +0530240 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400241 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000242 logger.Warnw("unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400243 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400244 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400245 }
246 }
247}
248
npujar1d86a522019-11-14 17:11:16 +0530249// RunPostDeviceDelete removes any reference of this device
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500250func (dMgr *DeviceManager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000251 logger.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530252 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400253 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400254}
255
khenaidoo297cd252019-02-07 22:10:23 -0500256// GetDevice will returns a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530257func (dMgr *DeviceManager) GetDevice(ctx context.Context, id string) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000258 logger.Debugw("GetDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530259 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400260 return agent.getDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400261 }
262 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400263}
264
npujar1d86a522019-11-14 17:11:16 +0530265// GetChildDevice will return a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530266func (dMgr *DeviceManager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000267 logger.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
npujar1d86a522019-11-14 17:11:16 +0530268 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500269
270 var parentDevice *voltha.Device
271 var err error
npujar467fe752020-01-16 20:17:45 +0530272 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500273 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
274 }
275 var childDeviceIds []string
276 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
277 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
278 }
279 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000280 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530281 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500282 }
283
284 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530285 for _, childDeviceID := range childDeviceIds {
286 var found bool
npujar467fe752020-01-16 20:17:45 +0530287 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500288
npujar1d86a522019-11-14 17:11:16 +0530289 foundOnuID := false
290 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500291 if searchDevice.ParentPortNo == uint32(parentPortNo) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000292 logger.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530293 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500294 }
295 }
296
297 foundSerialNumber := false
298 if searchDevice.SerialNumber == serialNumber {
Girish Kumarf56a4682020-03-20 20:07:46 +0000299 logger.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500300 foundSerialNumber = true
301 }
302
303 // if both onuId and serialNumber are provided both must be true for the device to be found
304 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530305 if onuID > 0 && serialNumber != "" {
306 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500307 } else {
npujar1d86a522019-11-14 17:11:16 +0530308 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500309 }
310
npujar1d86a522019-11-14 17:11:16 +0530311 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500312 foundChildDevice = searchDevice
313 break
314 }
315 }
316 }
317
318 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000319 logger.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500320 return foundChildDevice, nil
321 }
322
Girish Kumarf56a4682020-03-20 20:07:46 +0000323 logger.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530324 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
325 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500326}
327
npujar1d86a522019-11-14 17:11:16 +0530328// GetChildDeviceWithProxyAddress will return a device based on proxy address
npujar467fe752020-01-16 20:17:45 +0530329func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000330 logger.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500331
332 var parentDevice *voltha.Device
333 var err error
npujar467fe752020-01-16 20:17:45 +0530334 if parentDevice, err = dMgr.GetDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500335 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
336 }
337 var childDeviceIds []string
338 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
339 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
340 }
341 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000342 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500343 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
344 }
345
346 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530347 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530348 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500349 if searchDevice.ProxyAddress == proxyAddress {
350 foundChildDevice = searchDevice
351 break
352 }
353 }
354 }
355
356 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000357 logger.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500358 return foundChildDevice, nil
359 }
360
Girish Kumarf56a4682020-03-20 20:07:46 +0000361 logger.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500362 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
363}
364
npujar1d86a522019-11-14 17:11:16 +0530365// IsDeviceInCache returns true if device is found in the map
khenaidoo297cd252019-02-07 22:10:23 -0500366func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400367 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500368 return exist
369}
370
npujar1d86a522019-11-14 17:11:16 +0530371// IsRootDevice returns true if root device is found in the map
khenaidoo19d7b632018-10-30 10:49:50 -0400372func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400373 dMgr.lockRootDeviceMap.RLock()
374 defer dMgr.lockRootDeviceMap.RUnlock()
375 if exist := dMgr.rootDevices[id]; exist {
376 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400377 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400378 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400379}
380
Stephane Barbarieaa467942019-02-06 14:09:44 -0500381// ListDevices retrieves the latest devices from the data model
npujar467fe752020-01-16 20:17:45 +0530382func (dMgr *DeviceManager) ListDevices(ctx context.Context) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000383 logger.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400384 result := &voltha.Devices{}
Kent Hagerman4f355f52020-03-30 16:01:33 -0400385
386 var devices []*voltha.Device
387 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000388 logger.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530389 return nil, err
390 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400391
392 for _, device := range devices {
393 // If device is not in memory then set it up
394 if !dMgr.IsDeviceInCache(device.Id) {
395 logger.Debugw("loading-device-from-Model", log.Fields{"id": device.Id})
396 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
397 if _, err := agent.start(ctx, nil); err != nil {
398 logger.Warnw("failure-starting-agent", log.Fields{"deviceId": device.Id})
399 } else {
400 dMgr.addDeviceAgentToMap(agent)
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500401 }
khenaidoob9203542018-09-17 22:56:37 -0400402 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400403 result.Items = append(result.Items, device)
khenaidoob9203542018-09-17 22:56:37 -0400404 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000405 logger.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400406 return result, nil
407}
408
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530409//isParentDeviceExist checks whether device is already preprovisioned.
npujar467fe752020-01-16 20:17:45 +0530410func (dMgr *DeviceManager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530411 hostPort := newDevice.GetHostAndPort()
Kent Hagerman4f355f52020-03-30 16:01:33 -0400412 var devices []*voltha.Device
413 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000414 logger.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530415 return false, err
416 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400417 for _, device := range devices {
418 if !device.Root {
419 continue
420 }
421 if hostPort != "" && hostPort == device.GetHostAndPort() && device.AdminState != voltha.AdminState_DELETED {
422 return true, nil
423 }
424 if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress && device.AdminState != voltha.AdminState_DELETED {
425 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530426 }
427 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530428 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530429}
430
khenaidoo6d62c002019-05-15 21:57:03 -0400431//getDeviceFromModelretrieves the device data from the model.
npujar467fe752020-01-16 20:17:45 +0530432func (dMgr *DeviceManager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400433 device := &voltha.Device{}
434 if have, err := dMgr.clusterDataProxy.Get(ctx, "devices/"+deviceID, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000435 logger.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530436 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400437 } else if !have {
438 return nil, status.Error(codes.NotFound, deviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530439 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400440
441 return device, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400442}
443
npujar1d86a522019-11-14 17:11:16 +0530444// loadDevice loads the deviceID in memory, if not present
npujar467fe752020-01-16 20:17:45 +0530445func (dMgr *DeviceManager) loadDevice(ctx context.Context, deviceID string) (*DeviceAgent, error) {
npujar1d86a522019-11-14 17:11:16 +0530446 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500447 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
448 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400449 var err error
450 var device *voltha.Device
451 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530452 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
453 if !dMgr.IsDeviceInCache(deviceID) {
454 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400455 dMgr.devicesLoadingLock.Unlock()
456 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530457 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000458 logger.Debugw("loading-device", log.Fields{"deviceId": deviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400459 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530460 if _, err = agent.start(ctx, nil); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000461 logger.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400462 } else {
463 dMgr.addDeviceAgentToMap(agent)
464 }
465 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000466 logger.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400467 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400468 // announce completion of task to any number of waiting channels
469 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530470 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400471 for _, ch := range v {
472 close(ch)
473 }
npujar1d86a522019-11-14 17:11:16 +0530474 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400475 }
476 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400477 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400478 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500479 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400480 } else {
481 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530482 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400483 dMgr.devicesLoadingLock.Unlock()
484 // Wait for the channel to be closed, implying the process loading this device is done.
485 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500486 }
npujar1d86a522019-11-14 17:11:16 +0530487 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400488 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500489 }
npujar1d86a522019-11-14 17:11:16 +0530490 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500491}
492
493// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
npujar467fe752020-01-16 20:17:45 +0530494func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000495 logger.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500496 if device.Root {
497 // Scenario A
498 if device.ParentId != "" {
499 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530500 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000501 logger.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500502 }
503 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000504 logger.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500505 }
506 // Load all child devices, if needed
507 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530508 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530509 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000510 logger.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500511 return err
512 }
513 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000514 logger.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500515 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000516 logger.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500517 }
518 }
519 return nil
520}
521
522// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
523// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
524// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
525// and the proceed with the request.
npujar467fe752020-01-16 20:17:45 +0530526func (dMgr *DeviceManager) load(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000527 logger.Debug("load...")
khenaidoo297cd252019-02-07 22:10:23 -0500528 // First load the device - this may fail in case the device was deleted intentionally by the other core
529 var dAgent *DeviceAgent
530 var err error
npujar467fe752020-01-16 20:17:45 +0530531 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500532 return err
533 }
534 // Get the loaded device details
khenaidoo442e7c72020-03-10 16:13:48 -0400535 device, err := dAgent.getDevice(ctx)
536 if err != nil {
537 return err
538 }
khenaidoo297cd252019-02-07 22:10:23 -0500539
540 // If the device is in Pre-provisioning or deleted state stop here
541 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
542 return nil
543 }
544
545 // Now we face two scenarios
546 if device.Root {
547 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530548 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000549 logger.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500550 return err
551 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000552 logger.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500553 } else {
554 // Scenario B - use the parentId of that device (root device) to trigger the loading
555 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530556 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500557 }
558 }
559 return nil
560}
561
khenaidoo7ccedd52018-12-14 16:48:54 -0500562// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
563func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000564 logger.Debug("ListDeviceIDs")
khenaidoo7ccedd52018-12-14 16:48:54 -0500565 // Report only device IDs that are in the device agent map
566 return dMgr.listDeviceIdsFromMap(), nil
567}
568
khenaidoo4c9e5592019-09-09 16:20:41 -0400569//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
570//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500571func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000572 logger.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500573 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400574 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500575 toReconcile := len(ids.Items)
576 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400577 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500578 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530579 if err = dMgr.load(ctx, id.Id); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000580 logger.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400581 } else {
npujar1d86a522019-11-14 17:11:16 +0530582 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500583 }
584 }
585 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400586 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500587 }
588 } else {
589 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
590 }
591 sendResponse(ctx, ch, res)
592}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500593
khenaidooba6b6c42019-08-02 09:11:56 -0400594// isOkToReconcile validates whether a device is in the correct status to be reconciled
595func isOkToReconcile(device *voltha.Device) bool {
596 if device == nil {
597 return false
598 }
599 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
600}
601
602// adapterRestarted is invoked whenever an adapter is restarted
npujar467fe752020-01-16 20:17:45 +0530603func (dMgr *DeviceManager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000604 logger.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400605
606 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700607 if len(dMgr.rootDevices) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000608 logger.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400609 return nil
610 }
611
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500612 responses := make([]utils.Response, 0)
David Bainbridged1afd662020-03-26 18:27:41 -0700613 for rootDeviceID := range dMgr.rootDevices {
npujar467fe752020-01-16 20:17:45 +0530614 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400615 if rootDevice.Adapter == adapter.Id {
616 if isOkToReconcile(rootDevice) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000617 logger.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530618 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400619 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000620 logger.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400621 }
622 } else { // Should we be reconciling the root's children instead?
623 childManagedByAdapter:
624 for _, port := range rootDevice.Ports {
625 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530626 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400627 if childDevice.Adapter == adapter.Id {
628 if isOkToReconcile(childDevice) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000629 logger.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530630 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400631 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000632 logger.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400633 }
634 } else {
635 // All child devices under a parent device are typically managed by the same adapter type.
636 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
637 break childManagedByAdapter
638 }
639 }
640 }
641 }
642 }
643 }
644 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500645 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400646 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500647 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400648 return status.Errorf(codes.Aborted, "errors-%s", res)
649 }
650 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000651 logger.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400652 }
653 return nil
654}
655
npujar467fe752020-01-16 20:17:45 +0530656func (dMgr *DeviceManager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400657 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
658 // 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 +0530659 // 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 -0400660 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500661 response := utils.NewResponse()
khenaidoo442e7c72020-03-10 16:13:48 -0400662 ch, err := dMgr.adapterProxy.reconcileDevice(ctx, device)
663 if err != nil {
664 response.Error(err)
665 }
666 // Wait for adapter response in its own routine
667 go func() {
668 resp, ok := <-ch
669 if !ok {
670 response.Error(status.Errorf(codes.Aborted, "channel-closed-device: %s", device.Id))
671 } else if resp.Err != nil {
672 response.Error(resp.Err)
khenaidooba6b6c42019-08-02 09:11:56 -0400673 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500674 response.Done()
khenaidoo442e7c72020-03-10 16:13:48 -0400675 }()
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500676 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400677}
678
npujar467fe752020-01-16 20:17:45 +0530679func (dMgr *DeviceManager) reconcileChildDevices(ctx context.Context, parentDeviceID string) error {
680 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500681 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400682 for _, port := range parentDevice.Ports {
683 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530684 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
685 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400686 }
687 }
688 }
689 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500690 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400691 return status.Errorf(codes.Aborted, "errors-%s", res)
692 }
693 }
694 return nil
695}
696
npujar467fe752020-01-16 20:17:45 +0530697func (dMgr *DeviceManager) updateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000698 logger.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530699 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
700 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400701 }
702 return status.Errorf(codes.NotFound, "%s", device.Id)
703}
704
npujar467fe752020-01-16 20:17:45 +0530705func (dMgr *DeviceManager) addPort(ctx context.Context, deviceID string, port *voltha.Port) error {
706 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530707 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530708 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400709 return err
710 }
711 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530712 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400713 for _, peerPort := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530714 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
715 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000716 logger.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
khenaidoo92e62c52018-10-03 14:02:54 -0400717 return err
718 }
719 }
720 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400721 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
722 // then a logical port will be added to the logical device and the device graph generated. If the port is a
723 // PON port then only the device graph will be generated.
npujar467fe752020-01-16 20:17:45 +0530724 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530725 go func() {
npujar467fe752020-01-16 20:17:45 +0530726 err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port)
npujar1d86a522019-11-14 17:11:16 +0530727 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000728 logger.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530729 }
730 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400731 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000732 logger.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400733 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400734 }
khenaidoo92e62c52018-10-03 14:02:54 -0400735 return nil
khenaidoob9203542018-09-17 22:56:37 -0400736 }
npujar1d86a522019-11-14 17:11:16 +0530737 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400738}
739
npujar467fe752020-01-16 20:17:45 +0530740func (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 +0000741 logger.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530742 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
743 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400744 }
npujar1d86a522019-11-14 17:11:16 +0530745 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400746}
747
npujar467fe752020-01-16 20:17:45 +0530748func (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 +0000749 logger.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530750 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
751 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400752 }
npujar1d86a522019-11-14 17:11:16 +0530753 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400754}
755
npujar467fe752020-01-16 20:17:45 +0530756func (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 +0000757 logger.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530758 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
759 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400760 }
npujar1d86a522019-11-14 17:11:16 +0530761 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400762}
763
khenaidoob3127472019-07-24 21:04:55 -0400764// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
765// following a user action
766func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
767 var res interface{}
768 if pmConfigs.Id == "" {
769 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
npujar467fe752020-01-16 20:17:45 +0530770 } else if agent := dMgr.getDeviceAgent(ctx, pmConfigs.Id); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400771 res = agent.updatePmConfigs(ctx, pmConfigs)
772 } else {
773 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
774 }
775 sendResponse(ctx, ch, res)
776}
777
778// initPmConfigs initialize the pm configs as defined by the adapter.
npujar467fe752020-01-16 20:17:45 +0530779func (dMgr *DeviceManager) initPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400780 if pmConfigs.Id == "" {
781 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
782 }
npujar467fe752020-01-16 20:17:45 +0530783 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
784 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400785 }
npujar1d86a522019-11-14 17:11:16 +0530786 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400787}
788
npujar1d86a522019-11-14 17:11:16 +0530789func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
npujar467fe752020-01-16 20:17:45 +0530790 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400791 return agent.listPmConfigs(ctx)
792 }
npujar1d86a522019-11-14 17:11:16 +0530793 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400794}
795
npujar1d86a522019-11-14 17:11:16 +0530796func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000797 logger.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530798 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400799 return agent.getSwitchCapability(ctx)
800 }
npujar1d86a522019-11-14 17:11:16 +0530801 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400802}
803
npujar1d86a522019-11-14 17:11:16 +0530804func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000805 logger.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530806 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400807 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400808 }
npujar1d86a522019-11-14 17:11:16 +0530809 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400810}
811
npujar1d86a522019-11-14 17:11:16 +0530812func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000813 logger.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530814 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400815 return agent.getPortCapability(ctx, portNo)
816 }
npujar1d86a522019-11-14 17:11:16 +0530817 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400818}
819
npujar467fe752020-01-16 20:17:45 +0530820func (dMgr *DeviceManager) updateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000821 logger.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530822 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
823 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400824 }
npujar1d86a522019-11-14 17:11:16 +0530825 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400826}
827
npujar467fe752020-01-16 20:17:45 +0530828func (dMgr *DeviceManager) updateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000829 logger.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400830 var parentDevice *voltha.Device
831 var err error
npujar467fe752020-01-16 20:17:45 +0530832 if parentDevice, err = dMgr.GetDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400833 return status.Errorf(codes.Aborted, "%s", err.Error())
834 }
835 var childDeviceIds []string
836 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
837 return status.Errorf(codes.Aborted, "%s", err.Error())
838 }
839 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000840 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400841 }
npujar1d86a522019-11-14 17:11:16 +0530842 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530843 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
844 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530845 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400846 }
847 }
848 }
849 return nil
850}
851
npujar467fe752020-01-16 20:17:45 +0530852func (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 +0000853 logger.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530854 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
855 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000856 logger.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400857 return err
858 }
859 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800860 // Do this for NNI and UNIs only. PON ports are not known by logical device
861 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
862 go func() {
863 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
864 if err != nil {
865 // While we want to handle (catch) and log when
866 // an update to a port was not able to be
867 // propagated to the logical port, we can report
868 // it as a warning and not an error because it
869 // doesn't stop or modify processing.
870 // TODO: VOL-2707
Girish Kumarf56a4682020-03-20 20:07:46 +0000871 logger.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800872 }
873 }()
874 }
khenaidoo442e7c72020-03-10 16:13:48 -0400875 return nil
khenaidoob9203542018-09-17 22:56:37 -0400876 }
npujar1d86a522019-11-14 17:11:16 +0530877 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400878}
879
npujar467fe752020-01-16 20:17:45 +0530880func (dMgr *DeviceManager) deleteAllPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000881 logger.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530882 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
883 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400884 return err
885 }
886 // Notify the logical device manager to remove all logical ports, if needed.
887 // At this stage the device itself may gave been deleted already at a deleteAllPorts
888 // typically is part of a device deletion phase.
npujar467fe752020-01-16 20:17:45 +0530889 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530890 go func() {
npujar467fe752020-01-16 20:17:45 +0530891 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530892 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000893 logger.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530894 }
895 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400896 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000897 logger.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400898 return err
899 }
900 return nil
901 }
npujar1d86a522019-11-14 17:11:16 +0530902 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400903}
904
khenaidoo3ab34882019-05-02 21:33:30 -0400905//updatePortsState updates all ports on the device
npujar467fe752020-01-16 20:17:45 +0530906func (dMgr *DeviceManager) updatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000907 logger.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400908
npujar467fe752020-01-16 20:17:45 +0530909 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400910 switch state {
911 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500912 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000913 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400914 return err
915 }
916 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500917 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000918 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400919 return err
920 }
921 default:
922 return status.Error(codes.Unimplemented, "state-change-not-implemented")
923 }
924 // Notify the logical device about the state change
npujar467fe752020-01-16 20:17:45 +0530925 device, err := dMgr.GetDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530926 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000927 logger.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400928 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400929 }
kesavandbc2d1622020-01-21 00:42:01 -0500930 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000931 logger.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530932 return err
933 }
934 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400935 }
npujar1d86a522019-11-14 17:11:16 +0530936 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400937}
938
npujar467fe752020-01-16 20:17:45 +0530939func (dMgr *DeviceManager) childDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530940 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000941 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 -0700942
npujar1d86a522019-11-14 17:11:16 +0530943 if deviceType == "" && vendorID != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000944 logger.Debug("device-type-is-nil-fetching-device-type")
Kent Hagerman4f355f52020-03-30 16:01:33 -0400945 var deviceTypes []*voltha.DeviceType
946 if err := dMgr.adapterMgr.clusterDataProxy.List(ctx, "device_types", &deviceTypes); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000947 logger.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530948 return nil, err
949 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400950 OLoop:
951 for _, dType := range deviceTypes {
952 for _, v := range dType.VendorIds {
953 if v == vendorID {
954 deviceType = dType.Adapter
955 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700956 }
957 }
958 }
959 }
960 //if no match found for the vendorid,report adapter with the custom error message
961 if deviceType == "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000962 logger.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +0530963 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700964 }
khenaidoob9203542018-09-17 22:56:37 -0400965
966 // Create the ONU device
967 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400968 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530969 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400970 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530971 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500972 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400973 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400974
khenaidoo442e7c72020-03-10 16:13:48 -0400975 // Get parent device type
976 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
977 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +0530978 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400979 }
khenaidoo442e7c72020-03-10 16:13:48 -0400980 if pAgent.deviceType == "" {
981 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
982 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400983
npujar467fe752020-01-16 20:17:45 +0530984 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000985 logger.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700986 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500987 }
988
khenaidoo442e7c72020-03-10 16:13:48 -0400989 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -0400990
991 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400992 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -0400993 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -0800994 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000995 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 -0800996 return nil, err
997 }
khenaidoo442e7c72020-03-10 16:13:48 -0400998 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -0400999
1000 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301001 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301002 go func() {
npujar467fe752020-01-16 20:17:45 +05301003 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301004 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001005 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301006 }
1007 }()
khenaidoob9203542018-09-17 22:56:37 -04001008 }
1009
khenaidoo79232702018-12-04 11:00:41 -05001010 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301011 go func() {
1012 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1013 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001014 logger.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301015 }
1016 }()
khenaidoo79232702018-12-04 11:00:41 -05001017
Scott Baker80678602019-11-14 16:57:36 -08001018 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001019}
1020
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001021func (dMgr *DeviceManager) processTransition(ctx context.Context, device *voltha.Device, previousState *DeviceState) error {
1022 // This will be triggered on every state update
1023 logger.Debugw("state-transition", log.Fields{
1024 "device": device.Id,
1025 "prev-admin-state": previousState.Admin,
1026 "prev-oper-state": previousState.Operational,
1027 "prev-conn-state": previousState.Connection,
1028 "curr-admin-state": device.AdminState,
1029 "curr-oper-state": device.OperStatus,
1030 "curr-conn-state": device.ConnectStatus,
1031 })
1032 handlers := dMgr.stateTransitions.GetTransitionHandler(device, previousState)
khenaidoo92e62c52018-10-03 14:02:54 -04001033 if handlers == nil {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001034 logger.Debugw("no-op-transition", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001035 return nil
khenaidoob9203542018-09-17 22:56:37 -04001036 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001037 logger.Debugw("handler-found", log.Fields{"num-expectedHandlers": len(handlers), "isParent": device.Root, "current-data": device, "previous-state": previousState})
khenaidoo92e62c52018-10-03 14:02:54 -04001038 for _, handler := range handlers {
Girish Kumarf56a4682020-03-20 20:07:46 +00001039 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001040 if err := handler(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001041 logger.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001042 return err
1043 }
1044 }
khenaidoob9203542018-09-17 22:56:37 -04001045 return nil
1046}
1047
npujar467fe752020-01-16 20:17:45 +05301048func (dMgr *DeviceManager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001049 logger.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301050 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1051 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001052 }
npujar1d86a522019-11-14 17:11:16 +05301053 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001054}
1055
npujar1d86a522019-11-14 17:11:16 +05301056// PacketIn receives packet from adapter
npujar467fe752020-01-16 20:17:45 +05301057func (dMgr *DeviceManager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001058 logger.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001059 // Get the logical device Id based on the deviceId
1060 var device *voltha.Device
1061 var err error
npujar467fe752020-01-16 20:17:45 +05301062 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001063 logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001064 return err
1065 }
khenaidoo43c82122018-11-22 18:38:28 -05001066 if !device.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +00001067 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301068 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001069 }
1070
npujar467fe752020-01-16 20:17:45 +05301071 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001072 return err
1073 }
1074 return nil
1075}
1076
npujar467fe752020-01-16 20:17:45 +05301077func (dMgr *DeviceManager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001078 logger.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301079 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1080 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001081 }
1082 return status.Errorf(codes.NotFound, "%s", device.Id)
1083}
1084
npujar1d86a522019-11-14 17:11:16 +05301085// CreateLogicalDevice creates logical device in core
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001086func (dMgr *DeviceManager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001087 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001088 // Verify whether the logical device has already been created
1089 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001090 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001091 return nil
1092 }
khenaidoob9203542018-09-17 22:56:37 -04001093 var err error
npujar467fe752020-01-16 20:17:45 +05301094 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001095 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001096 return err
1097 }
khenaidoob9203542018-09-17 22:56:37 -04001098 return nil
1099}
1100
npujar1d86a522019-11-14 17:11:16 +05301101// DeleteLogicalDevice deletes logical device from core
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001102func (dMgr *DeviceManager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001103 logger.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001104 var err error
npujar467fe752020-01-16 20:17:45 +05301105 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001106 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001107 return err
1108 }
1109 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301110 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301111 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001112 return nil
1113}
1114
npujar1d86a522019-11-14 17:11:16 +05301115// DeleteLogicalPort removes the logical port associated with a device
npujar467fe752020-01-16 20:17:45 +05301116func (dMgr *DeviceManager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001117 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001118 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001119 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301120 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301121 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001122 logger.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001123 return err
1124 }
npujar467fe752020-01-16 20:17:45 +05301125 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001126 logger.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001127 return err
1128 }
khenaidoo92e62c52018-10-03 14:02:54 -04001129 return nil
1130}
1131
npujar1d86a522019-11-14 17:11:16 +05301132// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001133func (dMgr *DeviceManager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001134 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001135 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001136 // 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 +00001137 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001138 }
1139 return nil
1140}
1141
npujar467fe752020-01-16 20:17:45 +05301142func (dMgr *DeviceManager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001143 // Sanity check
1144 if childDevice.Root {
1145 // childDevice is the parent device
1146 return childDevice
1147 }
npujar467fe752020-01-16 20:17:45 +05301148 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001149 return parentDevice
1150}
1151
khenaidoo0a822f92019-05-08 15:15:57 -04001152//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1153//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar467fe752020-01-16 20:17:45 +05301154func (dMgr *DeviceManager) childDevicesLost(ctx context.Context, parentDeviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001155 logger.Debug("childDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001156 var err error
1157 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301158 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001159 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001160 return err
1161 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001162 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001163}
1164
1165//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1166// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar467fe752020-01-16 20:17:45 +05301167func (dMgr *DeviceManager) childDevicesDetected(ctx context.Context, parentDeviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001168 logger.Debug("childDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001169 var err error
1170 var parentDevice *voltha.Device
1171 var childDeviceIds []string
1172
npujar467fe752020-01-16 20:17:45 +05301173 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001174 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001175 return err
1176 }
1177
1178 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1179 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1180 }
1181 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001182 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001183 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001184 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301185 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301186 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001187 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301188 go func() {
npujar467fe752020-01-16 20:17:45 +05301189 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301190 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001191 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301192 }
1193 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001194 } else {
npujar1d86a522019-11-14 17:11:16 +05301195 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Girish Kumarf56a4682020-03-20 20:07:46 +00001196 logger.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001197 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001198 }
1199 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001200 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001201 return err
1202 }
1203 return nil
1204}
1205
khenaidoo4d4802d2018-10-04 21:59:49 -04001206/*
1207All the functions below are callback functions where they are invoked with the latest and previous data. We can
1208therefore use the data as is without trying to get the latest from the model.
1209*/
1210
khenaidoo0a822f92019-05-08 15:15:57 -04001211//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001212func (dMgr *DeviceManager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001213 logger.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001214 var childDeviceIds []string
1215 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001216 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1217 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001218 }
1219 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001220 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001221 }
npujar1d86a522019-11-14 17:11:16 +05301222 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301223 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1224 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001225 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001226 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001227 }
1228 }
1229 }
1230 return nil
1231}
1232
khenaidoo0a822f92019-05-08 15:15:57 -04001233//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001234func (dMgr *DeviceManager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001235 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001236 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001237 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001238 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1239 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001240 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001241 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001242 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001243 }
npujar1d86a522019-11-14 17:11:16 +05301244 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301245 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1246 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001247 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001248 }
khenaidoo49085352020-01-13 19:15:43 -05001249 // No further action is required here. The deleteDevice will change the device state where the resulting
1250 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001251 }
1252 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001253 return nil
1254}
1255
Hardik Windlassc704def2020-02-26 18:23:19 +00001256//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001257func (dMgr *DeviceManager) DeleteAllUNILogicalPorts(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001258 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": curr.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001259 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, curr); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001260 // Just log the error and let the remaining pipeline proceed - ports may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001261 logger.Warnw("delete-all-uni-logical-ports-failed", log.Fields{"parent-device-id": curr.Id, "error": err})
Hardik Windlassc704def2020-02-26 18:23:19 +00001262 }
1263 return nil
1264}
1265
Girish Gowdra408cd962020-03-11 14:31:31 -07001266//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001267func (dMgr *DeviceManager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001268 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001269 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001270 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001271 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001272 }
1273 return nil
1274}
1275
1276//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001277func (dMgr *DeviceManager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001278 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001279 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1280 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001281 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001282 return err
1283 }
1284 return nil
1285 }
1286 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1287}
1288
khenaidoo4d4802d2018-10-04 21:59:49 -04001289//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1290func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001291 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001292 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001293 if parentDevice != nil {
1294 for _, port := range parentDevice.Ports {
1295 for _, peer := range port.Peers {
1296 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1297 }
khenaidoo92e62c52018-10-03 14:02:54 -04001298 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001299 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001300 }
1301 return childDeviceIds, nil
1302}
1303
khenaidoo297cd252019-02-07 22:10:23 -05001304//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar467fe752020-01-16 20:17:45 +05301305func (dMgr *DeviceManager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001306 logger.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301307 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001308 childDevices := make([]*voltha.Device, 0)
1309 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301310 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301311 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001312 childDevices = append(childDevices, d)
1313 }
1314 }
1315 }
1316 return &voltha.Devices{Items: childDevices}, nil
1317 }
npujar1d86a522019-11-14 17:11:16 +05301318 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001319}
1320
npujar1d86a522019-11-14 17:11:16 +05301321// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001322func (dMgr *DeviceManager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001323 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301324 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001325 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001326 return err
1327 }
1328 return nil
1329}
1330
khenaidoof5a5bfa2019-01-23 22:20:29 -05001331func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001332 logger.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001333 var res interface{}
1334 var err error
npujar467fe752020-01-16 20:17:45 +05301335 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001336 if res, err = agent.downloadImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001337 logger.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001338 res = err
1339 }
1340 } else {
1341 res = status.Errorf(codes.NotFound, "%s", img.Id)
1342 }
1343 sendResponse(ctx, ch, res)
1344}
1345
1346func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001347 logger.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001348 var res interface{}
1349 var err error
npujar467fe752020-01-16 20:17:45 +05301350 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001351 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001352 logger.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001353 res = err
1354 }
1355 } else {
1356 res = status.Errorf(codes.NotFound, "%s", img.Id)
1357 }
1358 sendResponse(ctx, ch, res)
1359}
1360
1361func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001362 logger.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001363 var res interface{}
1364 var err error
npujar467fe752020-01-16 20:17:45 +05301365 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001366 if res, err = agent.activateImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001367 logger.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001368 res = err
1369 }
1370 } else {
1371 res = status.Errorf(codes.NotFound, "%s", img.Id)
1372 }
1373 sendResponse(ctx, ch, res)
1374}
1375
1376func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001377 logger.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001378 var res interface{}
1379 var err error
npujar467fe752020-01-16 20:17:45 +05301380 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001381 if res, err = agent.revertImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001382 logger.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001383 res = err
1384 }
1385 } else {
1386 res = status.Errorf(codes.NotFound, "%s", img.Id)
1387 }
1388 sendResponse(ctx, ch, res)
1389}
1390
1391func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001392 logger.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001393 var res interface{}
1394 var err error
npujar467fe752020-01-16 20:17:45 +05301395 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001396 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001397 logger.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001398 res = err
1399 }
1400 } else {
1401 res = status.Errorf(codes.NotFound, "%s", img.Id)
1402 }
1403 sendResponse(ctx, ch, res)
1404}
1405
npujar467fe752020-01-16 20:17:45 +05301406func (dMgr *DeviceManager) updateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001407 logger.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301408 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1409 if err := agent.updateImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001410 logger.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001411 return err
1412 }
1413 } else {
1414 return status.Errorf(codes.NotFound, "%s", img.Id)
1415 }
1416 return nil
1417}
1418
1419func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001420 logger.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301421 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001422 return agent.getImageDownload(ctx, img)
1423 }
1424 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1425}
1426
npujar1d86a522019-11-14 17:11:16 +05301427func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001428 logger.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301429 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301430 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001431 }
npujar1d86a522019-11-14 17:11:16 +05301432 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001433}
1434
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001435func (dMgr *DeviceManager) NotifyInvalidTransition(_ context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001436 logger.Errorw("NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001437 "device": device.Id,
1438 "curr-admin-state": device.AdminState,
1439 "curr-oper-state": device.OperStatus,
1440 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001441 })
khenaidoo0a822f92019-05-08 15:15:57 -04001442 //TODO: notify over kafka?
1443 return nil
1444}
1445
khenaidoob9203542018-09-17 22:56:37 -04001446func funcName(f interface{}) string {
1447 p := reflect.ValueOf(f).Pointer()
1448 rf := runtime.FuncForPC(p)
1449 return rf.Name()
1450}
1451
npujar1d86a522019-11-14 17:11:16 +05301452// UpdateDeviceAttribute updates value of particular device attribute
npujar467fe752020-01-16 20:17:45 +05301453func (dMgr *DeviceManager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301454 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
npujar467fe752020-01-16 20:17:45 +05301455 agent.(*DeviceAgent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001456 }
1457}
1458
npujar1d86a522019-11-14 17:11:16 +05301459// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +05301460func (dMgr *DeviceManager) GetParentDeviceID(ctx context.Context, deviceID string) string {
1461 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001462 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001463 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001464 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001465 return ""
khenaidoob9203542018-09-17 22:56:37 -04001466}
serkant.uluderya334479d2019-04-10 08:26:15 -07001467
1468func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001469 logger.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
serkant.uluderya334479d2019-04-10 08:26:15 -07001470 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1471 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1472 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301473 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001474 res = agent.simulateAlarm(ctx, simulatereq)
Girish Kumarf56a4682020-03-20 20:07:46 +00001475 logger.Debugw("simulateAlarm-result", log.Fields{"result": res})
serkant.uluderya334479d2019-04-10 08:26:15 -07001476 }
1477 //TODO CLI always get successful response
1478 sendResponse(ctx, ch, res)
1479}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001480
npujar467fe752020-01-16 20:17:45 +05301481func (dMgr *DeviceManager) updateDeviceReason(ctx context.Context, deviceID string, reason string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001482 logger.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301483 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1484 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001485 }
npujar1d86a522019-11-14 17:11:16 +05301486 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001487}
kesavandbc2d1622020-01-21 00:42:01 -05001488
1489func (dMgr *DeviceManager) enablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001490 logger.Debugw("enablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001491 var res interface{}
1492 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1493 res = agent.enablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001494 logger.Debugw("enablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001495 } else {
1496 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1497 }
1498
1499 sendResponse(ctx, ch, res)
1500}
1501
1502func (dMgr *DeviceManager) disablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001503 logger.Debugw("disablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001504 var res interface{}
1505 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1506 res = agent.disablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001507 logger.Debugw("disablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001508 } else {
1509 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1510 }
1511
1512 sendResponse(ctx, ch, res)
1513}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001514
khenaidoo442e7c72020-03-10 16:13:48 -04001515// childDeviceLost calls parent adapter to delete child device and all its references
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001516func (dMgr *DeviceManager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001517 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001518 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001519 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1520 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001521 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001522 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001523 }
khenaidooe132f522020-03-20 15:23:15 -04001524 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1525 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001526}
onkarkundargi87285252020-01-27 11:34:52 +05301527
1528func (dMgr *DeviceManager) startOmciTest(ctx context.Context, omcitestrequest *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001529 logger.Debugw("Omci_test_Request", log.Fields{"device-id": omcitestrequest.Id, "uuid": omcitestrequest.Uuid})
onkarkundargi87285252020-01-27 11:34:52 +05301530 if agent := dMgr.getDeviceAgent(ctx, omcitestrequest.Id); agent != nil {
1531 res, err := agent.startOmciTest(ctx, omcitestrequest)
1532 if err != nil {
1533 return nil, err
1534 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001535 logger.Debugw("Omci_test_Response_result-device-magnager", log.Fields{"result": res})
onkarkundargi87285252020-01-27 11:34:52 +05301536 return res, nil
1537 }
1538 return nil, status.Errorf(codes.NotFound, "%s", omcitestrequest.Id)
1539}