blob: 18593d8e3780b5200e2b196a242f69a6346f69a3 [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 {
Matteo Scandolod525ae32020-04-02 17:27:29 -070059
60 endpointManager := kafka.NewEndpointManager(&core.backend)
61
khenaidoob9203542018-09-17 22:56:37 -040062 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040063 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040064 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040065 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040066 deviceMgr.kafkaICProxy = core.kmp
Matteo Scandolod525ae32020-04-02 17:27:29 -070067 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic, endpointManager)
npujar1d86a522019-11-14 17:11:16 +053068 deviceMgr.coreInstanceID = core.instanceID
Richard Jankowski199fd862019-03-18 14:49:51 -040069 deviceMgr.clusterDataProxy = core.clusterDataProxy
70 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040071 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
khenaidoo442e7c72020-03-10 16:13:48 -040072 deviceMgr.defaultTimeout = time.Duration(core.config.DefaultCoreTimeout) * time.Millisecond
khenaidoo4c9e5592019-09-09 16:20:41 -040073 deviceMgr.devicesLoadingLock = sync.RWMutex{}
74 deviceMgr.deviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040075 return &deviceMgr
76}
77
khenaidoo4d4802d2018-10-04 21:59:49 -040078func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
Girish Kumarf56a4682020-03-20 20:07:46 +000079 logger.Info("starting-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040080 dMgr.logicalDeviceMgr = logicalDeviceMgr
81 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070082 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
Girish Kumarf56a4682020-03-20 20:07:46 +000083 logger.Info("device-manager-started")
khenaidoob9203542018-09-17 22:56:37 -040084}
85
khenaidoo4d4802d2018-10-04 21:59:49 -040086func (dMgr *DeviceManager) stop(ctx context.Context) {
Girish Kumarf56a4682020-03-20 20:07:46 +000087 logger.Info("stopping-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040088 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070089 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
Girish Kumarf56a4682020-03-20 20:07:46 +000090 logger.Info("device-manager-stopped")
khenaidoob9203542018-09-17 22:56:37 -040091}
92
93func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
94 if ctx.Err() == nil {
95 // Returned response only of the ctx has not been cancelled/timeout/etc
96 // Channel is automatically closed when a context is Done
97 ch <- result
Girish Kumarf56a4682020-03-20 20:07:46 +000098 logger.Debugw("sendResponse", log.Fields{"result": result})
khenaidoob9203542018-09-17 22:56:37 -040099 } else {
100 // Should the transaction be reverted back?
Girish Kumarf56a4682020-03-20 20:07:46 +0000101 logger.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
khenaidoob9203542018-09-17 22:56:37 -0400102 }
103}
104
105func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530106 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
107 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -0400108 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400109 dMgr.lockRootDeviceMap.Lock()
110 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530111 dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400112
khenaidoob9203542018-09-17 22:56:37 -0400113}
114
khenaidoo4c9e5592019-09-09 16:20:41 -0400115func (dMgr *DeviceManager) deleteDeviceAgentFromMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530116 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400117 dMgr.lockRootDeviceMap.Lock()
118 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530119 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400120}
121
khenaidoo297cd252019-02-07 22:10:23 -0500122// 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 +0530123func (dMgr *DeviceManager) getDeviceAgent(ctx context.Context, deviceID string) *DeviceAgent {
npujar1d86a522019-11-14 17:11:16 +0530124 agent, ok := dMgr.deviceAgents.Load(deviceID)
125 if ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400126 return agent.(*DeviceAgent)
khenaidoob9203542018-09-17 22:56:37 -0400127 }
khenaidoo442e7c72020-03-10 16:13:48 -0400128 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530129 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530130 if err == nil {
131 agent, ok = dMgr.deviceAgents.Load(deviceID)
132 if !ok {
133 return nil
134 }
npujar1d86a522019-11-14 17:11:16 +0530135 return agent.(*DeviceAgent)
136 }
137 //TODO: Change the return params to return an error as well
Girish Kumarf56a4682020-03-20 20:07:46 +0000138 logger.Errorw("loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400139 return nil
140}
141
khenaidoo297cd252019-02-07 22:10:23 -0500142// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500143func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500144 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400145
146 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
147 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
148 return true
149 })
150
khenaidoo7ccedd52018-12-14 16:48:54 -0500151 return result
152}
153
khenaidoob9203542018-09-17 22:56:37 -0400154func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
npujar467fe752020-01-16 20:17:45 +0530155 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530156 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000157 logger.Errorf("Failed to fetch parent device info")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530158 sendResponse(ctx, ch, err)
159 return
160 }
161 if deviceExist {
Girish Kumarf56a4682020-03-20 20:07:46 +0000162 logger.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530163 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
164 return
165 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000166 logger.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400167
khenaidoo5e677ae2019-02-28 17:26:29 -0500168 // Ensure this device is set as root
169 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400170 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400171 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530172 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800173 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000174 logger.Errorw("Fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530175 sendResponse(ctx, ch, err)
Scott Baker80678602019-11-14 16:57:36 -0800176 return
177 }
khenaidoo442e7c72020-03-10 16:13:48 -0400178 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -0400179
Scott Baker80678602019-11-14 16:57:36 -0800180 sendResponse(ctx, ch, device)
khenaidoob9203542018-09-17 22:56:37 -0400181}
182
183func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000184 logger.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400185 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530186 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400187 res = agent.enableDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000188 logger.Debugw("EnableDevice-result", log.Fields{"result": res})
Hardik Windlassb9cfcb12020-02-03 15:59:46 +0000189 } else {
190 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400191 }
khenaidoob9203542018-09-17 22:56:37 -0400192 sendResponse(ctx, ch, res)
193}
194
khenaidoo92e62c52018-10-03 14:02:54 -0400195func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000196 logger.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400197 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530198 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400199 res = agent.disableDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000200 logger.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400201 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400202 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400203 }
khenaidoo92e62c52018-10-03 14:02:54 -0400204
205 sendResponse(ctx, ch, res)
206}
207
khenaidoo4d4802d2018-10-04 21:59:49 -0400208func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000209 logger.Debugw("rebootDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400210 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530211 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400212 res = agent.rebootDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000213 logger.Debugw("rebootDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400214 } else {
215 res = status.Errorf(codes.NotFound, "%s", id.Id)
216 }
217 sendResponse(ctx, ch, res)
218}
219
220func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000221 logger.Debugw("deleteDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400222 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530223 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400224 res = agent.deleteDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000225 logger.Debugw("deleteDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400226 } else {
227 res = status.Errorf(codes.NotFound, "%s", id.Id)
228 }
229 sendResponse(ctx, ch, res)
230}
231
khenaidoo6d62c002019-05-15 21:57:03 -0400232// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
233// This function is called only in the Core that does not own this device. In the Core that owns this device then a
234// deletion deletion also includes removal of any reference of this device.
npujar467fe752020-01-16 20:17:45 +0530235func (dMgr *DeviceManager) stopManagingDevice(ctx context.Context, id string) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000236 logger.Infow("stopManagingDevice", log.Fields{"deviceId": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400237 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530238 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400239 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700240 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400241 }
npujar467fe752020-01-16 20:17:45 +0530242 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400243 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000244 logger.Warnw("unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400245 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400246 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400247 }
248 }
249}
250
npujar1d86a522019-11-14 17:11:16 +0530251// RunPostDeviceDelete removes any reference of this device
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500252func (dMgr *DeviceManager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000253 logger.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530254 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400255 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400256}
257
khenaidoo297cd252019-02-07 22:10:23 -0500258// GetDevice will returns a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530259func (dMgr *DeviceManager) GetDevice(ctx context.Context, id string) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000260 logger.Debugw("GetDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530261 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400262 return agent.getDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400263 }
264 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400265}
266
npujar1d86a522019-11-14 17:11:16 +0530267// GetChildDevice will return a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530268func (dMgr *DeviceManager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000269 logger.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
npujar1d86a522019-11-14 17:11:16 +0530270 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500271
272 var parentDevice *voltha.Device
273 var err error
npujar467fe752020-01-16 20:17:45 +0530274 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500275 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
276 }
277 var childDeviceIds []string
278 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
279 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
280 }
281 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000282 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530283 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500284 }
285
286 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530287 for _, childDeviceID := range childDeviceIds {
288 var found bool
npujar467fe752020-01-16 20:17:45 +0530289 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500290
npujar1d86a522019-11-14 17:11:16 +0530291 foundOnuID := false
292 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500293 if searchDevice.ParentPortNo == uint32(parentPortNo) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000294 logger.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530295 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500296 }
297 }
298
299 foundSerialNumber := false
300 if searchDevice.SerialNumber == serialNumber {
Girish Kumarf56a4682020-03-20 20:07:46 +0000301 logger.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500302 foundSerialNumber = true
303 }
304
305 // if both onuId and serialNumber are provided both must be true for the device to be found
306 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530307 if onuID > 0 && serialNumber != "" {
308 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500309 } else {
npujar1d86a522019-11-14 17:11:16 +0530310 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500311 }
312
npujar1d86a522019-11-14 17:11:16 +0530313 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500314 foundChildDevice = searchDevice
315 break
316 }
317 }
318 }
319
320 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000321 logger.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500322 return foundChildDevice, nil
323 }
324
Girish Kumarf56a4682020-03-20 20:07:46 +0000325 logger.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530326 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
327 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500328}
329
npujar1d86a522019-11-14 17:11:16 +0530330// GetChildDeviceWithProxyAddress will return a device based on proxy address
npujar467fe752020-01-16 20:17:45 +0530331func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000332 logger.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500333
334 var parentDevice *voltha.Device
335 var err error
npujar467fe752020-01-16 20:17:45 +0530336 if parentDevice, err = dMgr.GetDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500337 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
338 }
339 var childDeviceIds []string
340 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
341 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
342 }
343 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000344 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500345 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
346 }
347
348 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530349 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530350 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500351 if searchDevice.ProxyAddress == proxyAddress {
352 foundChildDevice = searchDevice
353 break
354 }
355 }
356 }
357
358 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000359 logger.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500360 return foundChildDevice, nil
361 }
362
Girish Kumarf56a4682020-03-20 20:07:46 +0000363 logger.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500364 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
365}
366
npujar1d86a522019-11-14 17:11:16 +0530367// IsDeviceInCache returns true if device is found in the map
khenaidoo297cd252019-02-07 22:10:23 -0500368func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400369 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500370 return exist
371}
372
npujar1d86a522019-11-14 17:11:16 +0530373// IsRootDevice returns true if root device is found in the map
khenaidoo19d7b632018-10-30 10:49:50 -0400374func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400375 dMgr.lockRootDeviceMap.RLock()
376 defer dMgr.lockRootDeviceMap.RUnlock()
377 if exist := dMgr.rootDevices[id]; exist {
378 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400379 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400380 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400381}
382
Stephane Barbarieaa467942019-02-06 14:09:44 -0500383// ListDevices retrieves the latest devices from the data model
npujar467fe752020-01-16 20:17:45 +0530384func (dMgr *DeviceManager) ListDevices(ctx context.Context) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000385 logger.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400386 result := &voltha.Devices{}
Kent Hagerman4f355f52020-03-30 16:01:33 -0400387
388 var devices []*voltha.Device
389 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000390 logger.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530391 return nil, err
392 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400393
394 for _, device := range devices {
395 // If device is not in memory then set it up
396 if !dMgr.IsDeviceInCache(device.Id) {
397 logger.Debugw("loading-device-from-Model", log.Fields{"id": device.Id})
398 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
399 if _, err := agent.start(ctx, nil); err != nil {
400 logger.Warnw("failure-starting-agent", log.Fields{"deviceId": device.Id})
401 } else {
402 dMgr.addDeviceAgentToMap(agent)
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500403 }
khenaidoob9203542018-09-17 22:56:37 -0400404 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400405 result.Items = append(result.Items, device)
khenaidoob9203542018-09-17 22:56:37 -0400406 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000407 logger.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400408 return result, nil
409}
410
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530411//isParentDeviceExist checks whether device is already preprovisioned.
npujar467fe752020-01-16 20:17:45 +0530412func (dMgr *DeviceManager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530413 hostPort := newDevice.GetHostAndPort()
Kent Hagerman4f355f52020-03-30 16:01:33 -0400414 var devices []*voltha.Device
415 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000416 logger.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530417 return false, err
418 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400419 for _, device := range devices {
420 if !device.Root {
421 continue
422 }
423 if hostPort != "" && hostPort == device.GetHostAndPort() && device.AdminState != voltha.AdminState_DELETED {
424 return true, nil
425 }
426 if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress && device.AdminState != voltha.AdminState_DELETED {
427 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530428 }
429 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530430 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530431}
432
khenaidoo6d62c002019-05-15 21:57:03 -0400433//getDeviceFromModelretrieves the device data from the model.
npujar467fe752020-01-16 20:17:45 +0530434func (dMgr *DeviceManager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400435 device := &voltha.Device{}
436 if have, err := dMgr.clusterDataProxy.Get(ctx, "devices/"+deviceID, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000437 logger.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530438 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400439 } else if !have {
440 return nil, status.Error(codes.NotFound, deviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530441 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400442
443 return device, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400444}
445
npujar1d86a522019-11-14 17:11:16 +0530446// loadDevice loads the deviceID in memory, if not present
npujar467fe752020-01-16 20:17:45 +0530447func (dMgr *DeviceManager) loadDevice(ctx context.Context, deviceID string) (*DeviceAgent, error) {
npujar1d86a522019-11-14 17:11:16 +0530448 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500449 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
450 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400451 var err error
452 var device *voltha.Device
453 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530454 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
455 if !dMgr.IsDeviceInCache(deviceID) {
456 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400457 dMgr.devicesLoadingLock.Unlock()
458 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530459 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000460 logger.Debugw("loading-device", log.Fields{"deviceId": deviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400461 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530462 if _, err = agent.start(ctx, nil); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000463 logger.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400464 } else {
465 dMgr.addDeviceAgentToMap(agent)
466 }
467 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000468 logger.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400469 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400470 // announce completion of task to any number of waiting channels
471 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530472 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400473 for _, ch := range v {
474 close(ch)
475 }
npujar1d86a522019-11-14 17:11:16 +0530476 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400477 }
478 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400479 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400480 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500481 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400482 } else {
483 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530484 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400485 dMgr.devicesLoadingLock.Unlock()
486 // Wait for the channel to be closed, implying the process loading this device is done.
487 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500488 }
npujar1d86a522019-11-14 17:11:16 +0530489 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400490 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500491 }
npujar1d86a522019-11-14 17:11:16 +0530492 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500493}
494
495// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
npujar467fe752020-01-16 20:17:45 +0530496func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000497 logger.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500498 if device.Root {
499 // Scenario A
500 if device.ParentId != "" {
501 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530502 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000503 logger.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500504 }
505 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000506 logger.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500507 }
508 // Load all child devices, if needed
509 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530510 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530511 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000512 logger.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500513 return err
514 }
515 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000516 logger.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500517 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000518 logger.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500519 }
520 }
521 return nil
522}
523
524// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
525// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
526// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
527// and the proceed with the request.
npujar467fe752020-01-16 20:17:45 +0530528func (dMgr *DeviceManager) load(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000529 logger.Debug("load...")
khenaidoo297cd252019-02-07 22:10:23 -0500530 // First load the device - this may fail in case the device was deleted intentionally by the other core
531 var dAgent *DeviceAgent
532 var err error
npujar467fe752020-01-16 20:17:45 +0530533 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500534 return err
535 }
536 // Get the loaded device details
khenaidoo442e7c72020-03-10 16:13:48 -0400537 device, err := dAgent.getDevice(ctx)
538 if err != nil {
539 return err
540 }
khenaidoo297cd252019-02-07 22:10:23 -0500541
542 // If the device is in Pre-provisioning or deleted state stop here
543 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
544 return nil
545 }
546
547 // Now we face two scenarios
548 if device.Root {
549 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530550 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000551 logger.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500552 return err
553 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000554 logger.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500555 } else {
556 // Scenario B - use the parentId of that device (root device) to trigger the loading
557 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530558 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500559 }
560 }
561 return nil
562}
563
khenaidoo7ccedd52018-12-14 16:48:54 -0500564// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
565func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000566 logger.Debug("ListDeviceIDs")
khenaidoo7ccedd52018-12-14 16:48:54 -0500567 // Report only device IDs that are in the device agent map
568 return dMgr.listDeviceIdsFromMap(), nil
569}
570
khenaidoo4c9e5592019-09-09 16:20:41 -0400571//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
572//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500573func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000574 logger.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500575 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400576 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500577 toReconcile := len(ids.Items)
578 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400579 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500580 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530581 if err = dMgr.load(ctx, id.Id); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000582 logger.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400583 } else {
npujar1d86a522019-11-14 17:11:16 +0530584 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500585 }
586 }
587 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400588 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500589 }
590 } else {
591 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
592 }
593 sendResponse(ctx, ch, res)
594}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500595
khenaidooba6b6c42019-08-02 09:11:56 -0400596// isOkToReconcile validates whether a device is in the correct status to be reconciled
597func isOkToReconcile(device *voltha.Device) bool {
598 if device == nil {
599 return false
600 }
601 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
602}
603
604// adapterRestarted is invoked whenever an adapter is restarted
npujar467fe752020-01-16 20:17:45 +0530605func (dMgr *DeviceManager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Matteo Scandolod525ae32020-04-02 17:27:29 -0700606 logger.Debugw("adapter-restarted", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
607 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidooba6b6c42019-08-02 09:11:56 -0400608
609 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700610 if len(dMgr.rootDevices) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000611 logger.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400612 return nil
613 }
614
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500615 responses := make([]utils.Response, 0)
David Bainbridged1afd662020-03-26 18:27:41 -0700616 for rootDeviceID := range dMgr.rootDevices {
npujar467fe752020-01-16 20:17:45 +0530617 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400618 if rootDevice.Adapter == adapter.Id {
619 if isOkToReconcile(rootDevice) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000620 logger.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530621 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400622 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000623 logger.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400624 }
625 } else { // Should we be reconciling the root's children instead?
626 childManagedByAdapter:
627 for _, port := range rootDevice.Ports {
628 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530629 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400630 if childDevice.Adapter == adapter.Id {
631 if isOkToReconcile(childDevice) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000632 logger.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530633 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400634 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000635 logger.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400636 }
637 } else {
638 // All child devices under a parent device are typically managed by the same adapter type.
639 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
640 break childManagedByAdapter
641 }
642 }
643 }
644 }
645 }
646 }
647 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500648 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400649 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500650 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400651 return status.Errorf(codes.Aborted, "errors-%s", res)
652 }
653 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000654 logger.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400655 }
656 return nil
657}
658
npujar467fe752020-01-16 20:17:45 +0530659func (dMgr *DeviceManager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400660 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
661 // 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 +0530662 // 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 -0400663 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500664 response := utils.NewResponse()
khenaidoo442e7c72020-03-10 16:13:48 -0400665 ch, err := dMgr.adapterProxy.reconcileDevice(ctx, device)
666 if err != nil {
667 response.Error(err)
668 }
669 // Wait for adapter response in its own routine
670 go func() {
671 resp, ok := <-ch
672 if !ok {
673 response.Error(status.Errorf(codes.Aborted, "channel-closed-device: %s", device.Id))
674 } else if resp.Err != nil {
675 response.Error(resp.Err)
khenaidooba6b6c42019-08-02 09:11:56 -0400676 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500677 response.Done()
khenaidoo442e7c72020-03-10 16:13:48 -0400678 }()
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500679 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400680}
681
npujar467fe752020-01-16 20:17:45 +0530682func (dMgr *DeviceManager) reconcileChildDevices(ctx context.Context, parentDeviceID string) error {
683 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500684 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400685 for _, port := range parentDevice.Ports {
686 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530687 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
688 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400689 }
690 }
691 }
692 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500693 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400694 return status.Errorf(codes.Aborted, "errors-%s", res)
695 }
696 }
697 return nil
698}
699
npujar467fe752020-01-16 20:17:45 +0530700func (dMgr *DeviceManager) updateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000701 logger.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530702 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
703 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400704 }
705 return status.Errorf(codes.NotFound, "%s", device.Id)
706}
707
npujar467fe752020-01-16 20:17:45 +0530708func (dMgr *DeviceManager) addPort(ctx context.Context, deviceID string, port *voltha.Port) error {
709 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530710 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530711 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400712 return err
713 }
714 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530715 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400716 for _, peerPort := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530717 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
718 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000719 logger.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
khenaidoo92e62c52018-10-03 14:02:54 -0400720 return err
721 }
722 }
723 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400724 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
725 // then a logical port will be added to the logical device and the device graph generated. If the port is a
726 // PON port then only the device graph will be generated.
npujar467fe752020-01-16 20:17:45 +0530727 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530728 go func() {
npujar467fe752020-01-16 20:17:45 +0530729 err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port)
npujar1d86a522019-11-14 17:11:16 +0530730 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000731 logger.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530732 }
733 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400734 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000735 logger.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400736 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400737 }
khenaidoo92e62c52018-10-03 14:02:54 -0400738 return nil
khenaidoob9203542018-09-17 22:56:37 -0400739 }
npujar1d86a522019-11-14 17:11:16 +0530740 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400741}
742
npujar467fe752020-01-16 20:17:45 +0530743func (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 +0000744 logger.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530745 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
746 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400747 }
npujar1d86a522019-11-14 17:11:16 +0530748 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400749}
750
npujar467fe752020-01-16 20:17:45 +0530751func (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 +0000752 logger.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530753 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
754 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400755 }
npujar1d86a522019-11-14 17:11:16 +0530756 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400757}
758
npujar467fe752020-01-16 20:17:45 +0530759func (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 +0000760 logger.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530761 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
762 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400763 }
npujar1d86a522019-11-14 17:11:16 +0530764 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400765}
766
khenaidoob3127472019-07-24 21:04:55 -0400767// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
768// following a user action
769func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
770 var res interface{}
771 if pmConfigs.Id == "" {
772 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
npujar467fe752020-01-16 20:17:45 +0530773 } else if agent := dMgr.getDeviceAgent(ctx, pmConfigs.Id); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400774 res = agent.updatePmConfigs(ctx, pmConfigs)
775 } else {
776 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
777 }
778 sendResponse(ctx, ch, res)
779}
780
781// initPmConfigs initialize the pm configs as defined by the adapter.
npujar467fe752020-01-16 20:17:45 +0530782func (dMgr *DeviceManager) initPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400783 if pmConfigs.Id == "" {
784 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
785 }
npujar467fe752020-01-16 20:17:45 +0530786 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
787 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400788 }
npujar1d86a522019-11-14 17:11:16 +0530789 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400790}
791
npujar1d86a522019-11-14 17:11:16 +0530792func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
npujar467fe752020-01-16 20:17:45 +0530793 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400794 return agent.listPmConfigs(ctx)
795 }
npujar1d86a522019-11-14 17:11:16 +0530796 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400797}
798
npujar1d86a522019-11-14 17:11:16 +0530799func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000800 logger.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530801 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400802 return agent.getSwitchCapability(ctx)
803 }
npujar1d86a522019-11-14 17:11:16 +0530804 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400805}
806
npujar1d86a522019-11-14 17:11:16 +0530807func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000808 logger.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530809 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400810 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400811 }
npujar1d86a522019-11-14 17:11:16 +0530812 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400813}
814
npujar1d86a522019-11-14 17:11:16 +0530815func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000816 logger.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530817 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400818 return agent.getPortCapability(ctx, portNo)
819 }
npujar1d86a522019-11-14 17:11:16 +0530820 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400821}
822
npujar467fe752020-01-16 20:17:45 +0530823func (dMgr *DeviceManager) updateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000824 logger.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530825 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
826 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400827 }
npujar1d86a522019-11-14 17:11:16 +0530828 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400829}
830
npujar467fe752020-01-16 20:17:45 +0530831func (dMgr *DeviceManager) updateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000832 logger.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400833 var parentDevice *voltha.Device
834 var err error
npujar467fe752020-01-16 20:17:45 +0530835 if parentDevice, err = dMgr.GetDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400836 return status.Errorf(codes.Aborted, "%s", err.Error())
837 }
838 var childDeviceIds []string
839 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
840 return status.Errorf(codes.Aborted, "%s", err.Error())
841 }
842 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000843 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400844 }
npujar1d86a522019-11-14 17:11:16 +0530845 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530846 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
847 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530848 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400849 }
850 }
851 }
852 return nil
853}
854
npujar467fe752020-01-16 20:17:45 +0530855func (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 +0000856 logger.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530857 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
858 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000859 logger.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400860 return err
861 }
862 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800863 // Do this for NNI and UNIs only. PON ports are not known by logical device
864 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
865 go func() {
866 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
867 if err != nil {
868 // While we want to handle (catch) and log when
869 // an update to a port was not able to be
870 // propagated to the logical port, we can report
871 // it as a warning and not an error because it
872 // doesn't stop or modify processing.
873 // TODO: VOL-2707
Girish Kumarf56a4682020-03-20 20:07:46 +0000874 logger.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800875 }
876 }()
877 }
khenaidoo442e7c72020-03-10 16:13:48 -0400878 return nil
khenaidoob9203542018-09-17 22:56:37 -0400879 }
npujar1d86a522019-11-14 17:11:16 +0530880 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400881}
882
npujar467fe752020-01-16 20:17:45 +0530883func (dMgr *DeviceManager) deleteAllPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000884 logger.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530885 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
886 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400887 return err
888 }
889 // Notify the logical device manager to remove all logical ports, if needed.
890 // At this stage the device itself may gave been deleted already at a deleteAllPorts
891 // typically is part of a device deletion phase.
npujar467fe752020-01-16 20:17:45 +0530892 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530893 go func() {
npujar467fe752020-01-16 20:17:45 +0530894 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530895 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000896 logger.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530897 }
898 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400899 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000900 logger.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400901 return err
902 }
903 return nil
904 }
npujar1d86a522019-11-14 17:11:16 +0530905 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400906}
907
khenaidoo3ab34882019-05-02 21:33:30 -0400908//updatePortsState updates all ports on the device
npujar467fe752020-01-16 20:17:45 +0530909func (dMgr *DeviceManager) updatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000910 logger.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400911
npujar467fe752020-01-16 20:17:45 +0530912 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400913 switch state {
914 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500915 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000916 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400917 return err
918 }
919 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500920 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000921 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400922 return err
923 }
924 default:
925 return status.Error(codes.Unimplemented, "state-change-not-implemented")
926 }
927 // Notify the logical device about the state change
npujar467fe752020-01-16 20:17:45 +0530928 device, err := dMgr.GetDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530929 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000930 logger.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400931 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400932 }
kesavandbc2d1622020-01-21 00:42:01 -0500933 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000934 logger.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530935 return err
936 }
937 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400938 }
npujar1d86a522019-11-14 17:11:16 +0530939 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400940}
941
npujar467fe752020-01-16 20:17:45 +0530942func (dMgr *DeviceManager) childDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530943 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000944 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 -0700945
npujar1d86a522019-11-14 17:11:16 +0530946 if deviceType == "" && vendorID != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000947 logger.Debug("device-type-is-nil-fetching-device-type")
Kent Hagerman4f355f52020-03-30 16:01:33 -0400948 var deviceTypes []*voltha.DeviceType
949 if err := dMgr.adapterMgr.clusterDataProxy.List(ctx, "device_types", &deviceTypes); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000950 logger.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530951 return nil, err
952 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400953 OLoop:
954 for _, dType := range deviceTypes {
955 for _, v := range dType.VendorIds {
956 if v == vendorID {
957 deviceType = dType.Adapter
958 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700959 }
960 }
961 }
962 }
963 //if no match found for the vendorid,report adapter with the custom error message
964 if deviceType == "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000965 logger.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +0530966 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700967 }
khenaidoob9203542018-09-17 22:56:37 -0400968
969 // Create the ONU device
970 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400971 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530972 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400973 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530974 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500975 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400976 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400977
khenaidoo442e7c72020-03-10 16:13:48 -0400978 // Get parent device type
979 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
980 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +0530981 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400982 }
khenaidoo442e7c72020-03-10 16:13:48 -0400983 if pAgent.deviceType == "" {
984 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
985 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400986
npujar467fe752020-01-16 20:17:45 +0530987 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000988 logger.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700989 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500990 }
991
khenaidoo442e7c72020-03-10 16:13:48 -0400992 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -0400993
994 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400995 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -0400996 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -0800997 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000998 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 -0800999 return nil, err
1000 }
khenaidoo442e7c72020-03-10 16:13:48 -04001001 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001002
1003 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301004 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301005 go func() {
npujar467fe752020-01-16 20:17:45 +05301006 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301007 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001008 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301009 }
1010 }()
khenaidoob9203542018-09-17 22:56:37 -04001011 }
1012
khenaidoo79232702018-12-04 11:00:41 -05001013 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301014 go func() {
1015 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1016 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001017 logger.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301018 }
1019 }()
khenaidoo79232702018-12-04 11:00:41 -05001020
Scott Baker80678602019-11-14 16:57:36 -08001021 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001022}
1023
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001024func (dMgr *DeviceManager) processTransition(ctx context.Context, device *voltha.Device, previousState *DeviceState) error {
1025 // This will be triggered on every state update
1026 logger.Debugw("state-transition", log.Fields{
1027 "device": device.Id,
1028 "prev-admin-state": previousState.Admin,
1029 "prev-oper-state": previousState.Operational,
1030 "prev-conn-state": previousState.Connection,
1031 "curr-admin-state": device.AdminState,
1032 "curr-oper-state": device.OperStatus,
1033 "curr-conn-state": device.ConnectStatus,
1034 })
1035 handlers := dMgr.stateTransitions.GetTransitionHandler(device, previousState)
khenaidoo92e62c52018-10-03 14:02:54 -04001036 if handlers == nil {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001037 logger.Debugw("no-op-transition", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001038 return nil
khenaidoob9203542018-09-17 22:56:37 -04001039 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001040 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 -04001041 for _, handler := range handlers {
Girish Kumarf56a4682020-03-20 20:07:46 +00001042 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001043 if err := handler(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001044 logger.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001045 return err
1046 }
1047 }
khenaidoob9203542018-09-17 22:56:37 -04001048 return nil
1049}
1050
npujar467fe752020-01-16 20:17:45 +05301051func (dMgr *DeviceManager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001052 logger.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301053 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1054 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001055 }
npujar1d86a522019-11-14 17:11:16 +05301056 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001057}
1058
npujar1d86a522019-11-14 17:11:16 +05301059// PacketIn receives packet from adapter
npujar467fe752020-01-16 20:17:45 +05301060func (dMgr *DeviceManager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001061 logger.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001062 // Get the logical device Id based on the deviceId
1063 var device *voltha.Device
1064 var err error
npujar467fe752020-01-16 20:17:45 +05301065 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001066 logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001067 return err
1068 }
khenaidoo43c82122018-11-22 18:38:28 -05001069 if !device.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +00001070 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301071 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001072 }
1073
npujar467fe752020-01-16 20:17:45 +05301074 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001075 return err
1076 }
1077 return nil
1078}
1079
npujar467fe752020-01-16 20:17:45 +05301080func (dMgr *DeviceManager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001081 logger.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301082 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1083 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001084 }
1085 return status.Errorf(codes.NotFound, "%s", device.Id)
1086}
1087
npujar1d86a522019-11-14 17:11:16 +05301088// CreateLogicalDevice creates logical device in core
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001089func (dMgr *DeviceManager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001090 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001091 // Verify whether the logical device has already been created
1092 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001093 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001094 return nil
1095 }
khenaidoob9203542018-09-17 22:56:37 -04001096 var err error
npujar467fe752020-01-16 20:17:45 +05301097 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001098 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001099 return err
1100 }
khenaidoob9203542018-09-17 22:56:37 -04001101 return nil
1102}
1103
npujar1d86a522019-11-14 17:11:16 +05301104// DeleteLogicalDevice deletes logical device from core
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001105func (dMgr *DeviceManager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001106 logger.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001107 var err error
npujar467fe752020-01-16 20:17:45 +05301108 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001109 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001110 return err
1111 }
1112 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301113 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301114 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001115 return nil
1116}
1117
npujar1d86a522019-11-14 17:11:16 +05301118// DeleteLogicalPort removes the logical port associated with a device
npujar467fe752020-01-16 20:17:45 +05301119func (dMgr *DeviceManager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001120 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001121 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001122 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301123 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301124 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001125 logger.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001126 return err
1127 }
npujar467fe752020-01-16 20:17:45 +05301128 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001129 logger.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001130 return err
1131 }
khenaidoo92e62c52018-10-03 14:02:54 -04001132 return nil
1133}
1134
npujar1d86a522019-11-14 17:11:16 +05301135// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001136func (dMgr *DeviceManager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001137 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001138 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001139 // 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 +00001140 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001141 }
1142 return nil
1143}
1144
npujar467fe752020-01-16 20:17:45 +05301145func (dMgr *DeviceManager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001146 // Sanity check
1147 if childDevice.Root {
1148 // childDevice is the parent device
1149 return childDevice
1150 }
npujar467fe752020-01-16 20:17:45 +05301151 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001152 return parentDevice
1153}
1154
khenaidoo0a822f92019-05-08 15:15:57 -04001155//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1156//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar467fe752020-01-16 20:17:45 +05301157func (dMgr *DeviceManager) childDevicesLost(ctx context.Context, parentDeviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001158 logger.Debug("childDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001159 var err error
1160 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301161 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001162 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001163 return err
1164 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001165 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001166}
1167
1168//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1169// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar467fe752020-01-16 20:17:45 +05301170func (dMgr *DeviceManager) childDevicesDetected(ctx context.Context, parentDeviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001171 logger.Debug("childDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001172 var err error
1173 var parentDevice *voltha.Device
1174 var childDeviceIds []string
1175
npujar467fe752020-01-16 20:17:45 +05301176 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001177 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001178 return err
1179 }
1180
1181 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1182 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1183 }
1184 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001185 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001186 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001187 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301188 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301189 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001190 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301191 go func() {
npujar467fe752020-01-16 20:17:45 +05301192 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301193 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001194 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301195 }
1196 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001197 } else {
npujar1d86a522019-11-14 17:11:16 +05301198 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Girish Kumarf56a4682020-03-20 20:07:46 +00001199 logger.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001200 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001201 }
1202 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001203 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001204 return err
1205 }
1206 return nil
1207}
1208
khenaidoo4d4802d2018-10-04 21:59:49 -04001209/*
1210All the functions below are callback functions where they are invoked with the latest and previous data. We can
1211therefore use the data as is without trying to get the latest from the model.
1212*/
1213
khenaidoo0a822f92019-05-08 15:15:57 -04001214//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001215func (dMgr *DeviceManager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001216 logger.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001217 var childDeviceIds []string
1218 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001219 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1220 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001221 }
1222 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001223 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001224 }
npujar1d86a522019-11-14 17:11:16 +05301225 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301226 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1227 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001228 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001229 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001230 }
1231 }
1232 }
1233 return nil
1234}
1235
khenaidoo0a822f92019-05-08 15:15:57 -04001236//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001237func (dMgr *DeviceManager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001238 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001239 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001240 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001241 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1242 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001243 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001244 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001245 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001246 }
npujar1d86a522019-11-14 17:11:16 +05301247 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301248 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1249 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001250 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001251 }
khenaidoo49085352020-01-13 19:15:43 -05001252 // No further action is required here. The deleteDevice will change the device state where the resulting
1253 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001254 }
1255 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001256 return nil
1257}
1258
Hardik Windlassc704def2020-02-26 18:23:19 +00001259//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001260func (dMgr *DeviceManager) DeleteAllUNILogicalPorts(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001261 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": curr.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001262 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, curr); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001263 // Just log the error and let the remaining pipeline proceed - ports may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001264 logger.Warnw("delete-all-uni-logical-ports-failed", log.Fields{"parent-device-id": curr.Id, "error": err})
Hardik Windlassc704def2020-02-26 18:23:19 +00001265 }
1266 return nil
1267}
1268
Girish Gowdra408cd962020-03-11 14:31:31 -07001269//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001270func (dMgr *DeviceManager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001271 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001272 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001273 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001274 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001275 }
1276 return nil
1277}
1278
1279//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001280func (dMgr *DeviceManager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001281 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001282 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1283 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001284 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001285 return err
1286 }
1287 return nil
1288 }
1289 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1290}
1291
khenaidoo4d4802d2018-10-04 21:59:49 -04001292//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1293func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001294 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001295 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001296 if parentDevice != nil {
1297 for _, port := range parentDevice.Ports {
1298 for _, peer := range port.Peers {
1299 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1300 }
khenaidoo92e62c52018-10-03 14:02:54 -04001301 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001302 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001303 }
1304 return childDeviceIds, nil
1305}
1306
khenaidoo297cd252019-02-07 22:10:23 -05001307//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar467fe752020-01-16 20:17:45 +05301308func (dMgr *DeviceManager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001309 logger.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301310 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001311 childDevices := make([]*voltha.Device, 0)
1312 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301313 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301314 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001315 childDevices = append(childDevices, d)
1316 }
1317 }
1318 }
1319 return &voltha.Devices{Items: childDevices}, nil
1320 }
npujar1d86a522019-11-14 17:11:16 +05301321 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001322}
1323
npujar1d86a522019-11-14 17:11:16 +05301324// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001325func (dMgr *DeviceManager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001326 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301327 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001328 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001329 return err
1330 }
1331 return nil
1332}
1333
khenaidoof5a5bfa2019-01-23 22:20:29 -05001334func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001335 logger.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001336 var res interface{}
1337 var err error
npujar467fe752020-01-16 20:17:45 +05301338 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001339 if res, err = agent.downloadImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001340 logger.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001341 res = err
1342 }
1343 } else {
1344 res = status.Errorf(codes.NotFound, "%s", img.Id)
1345 }
1346 sendResponse(ctx, ch, res)
1347}
1348
1349func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001350 logger.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001351 var res interface{}
1352 var err error
npujar467fe752020-01-16 20:17:45 +05301353 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001354 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001355 logger.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001356 res = err
1357 }
1358 } else {
1359 res = status.Errorf(codes.NotFound, "%s", img.Id)
1360 }
1361 sendResponse(ctx, ch, res)
1362}
1363
1364func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001365 logger.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001366 var res interface{}
1367 var err error
npujar467fe752020-01-16 20:17:45 +05301368 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001369 if res, err = agent.activateImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001370 logger.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001371 res = err
1372 }
1373 } else {
1374 res = status.Errorf(codes.NotFound, "%s", img.Id)
1375 }
1376 sendResponse(ctx, ch, res)
1377}
1378
1379func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001380 logger.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001381 var res interface{}
1382 var err error
npujar467fe752020-01-16 20:17:45 +05301383 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001384 if res, err = agent.revertImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001385 logger.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001386 res = err
1387 }
1388 } else {
1389 res = status.Errorf(codes.NotFound, "%s", img.Id)
1390 }
1391 sendResponse(ctx, ch, res)
1392}
1393
1394func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001395 logger.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001396 var res interface{}
1397 var err error
npujar467fe752020-01-16 20:17:45 +05301398 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001399 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001400 logger.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001401 res = err
1402 }
1403 } else {
1404 res = status.Errorf(codes.NotFound, "%s", img.Id)
1405 }
1406 sendResponse(ctx, ch, res)
1407}
1408
npujar467fe752020-01-16 20:17:45 +05301409func (dMgr *DeviceManager) updateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001410 logger.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301411 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1412 if err := agent.updateImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001413 logger.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001414 return err
1415 }
1416 } else {
1417 return status.Errorf(codes.NotFound, "%s", img.Id)
1418 }
1419 return nil
1420}
1421
1422func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001423 logger.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301424 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001425 return agent.getImageDownload(ctx, img)
1426 }
1427 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1428}
1429
npujar1d86a522019-11-14 17:11:16 +05301430func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001431 logger.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301432 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301433 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001434 }
npujar1d86a522019-11-14 17:11:16 +05301435 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001436}
1437
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001438func (dMgr *DeviceManager) NotifyInvalidTransition(_ context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001439 logger.Errorw("NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001440 "device": device.Id,
1441 "curr-admin-state": device.AdminState,
1442 "curr-oper-state": device.OperStatus,
1443 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001444 })
khenaidoo0a822f92019-05-08 15:15:57 -04001445 //TODO: notify over kafka?
1446 return nil
1447}
1448
khenaidoob9203542018-09-17 22:56:37 -04001449func funcName(f interface{}) string {
1450 p := reflect.ValueOf(f).Pointer()
1451 rf := runtime.FuncForPC(p)
1452 return rf.Name()
1453}
1454
npujar1d86a522019-11-14 17:11:16 +05301455// UpdateDeviceAttribute updates value of particular device attribute
npujar467fe752020-01-16 20:17:45 +05301456func (dMgr *DeviceManager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301457 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
npujar467fe752020-01-16 20:17:45 +05301458 agent.(*DeviceAgent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001459 }
1460}
1461
npujar1d86a522019-11-14 17:11:16 +05301462// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +05301463func (dMgr *DeviceManager) GetParentDeviceID(ctx context.Context, deviceID string) string {
1464 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001465 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001466 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001467 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001468 return ""
khenaidoob9203542018-09-17 22:56:37 -04001469}
serkant.uluderya334479d2019-04-10 08:26:15 -07001470
1471func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001472 logger.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
serkant.uluderya334479d2019-04-10 08:26:15 -07001473 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1474 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1475 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301476 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001477 res = agent.simulateAlarm(ctx, simulatereq)
Girish Kumarf56a4682020-03-20 20:07:46 +00001478 logger.Debugw("simulateAlarm-result", log.Fields{"result": res})
serkant.uluderya334479d2019-04-10 08:26:15 -07001479 }
1480 //TODO CLI always get successful response
1481 sendResponse(ctx, ch, res)
1482}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001483
npujar467fe752020-01-16 20:17:45 +05301484func (dMgr *DeviceManager) updateDeviceReason(ctx context.Context, deviceID string, reason string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001485 logger.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301486 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1487 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001488 }
npujar1d86a522019-11-14 17:11:16 +05301489 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001490}
kesavandbc2d1622020-01-21 00:42:01 -05001491
1492func (dMgr *DeviceManager) enablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001493 logger.Debugw("enablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001494 var res interface{}
1495 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1496 res = agent.enablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001497 logger.Debugw("enablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001498 } else {
1499 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1500 }
1501
1502 sendResponse(ctx, ch, res)
1503}
1504
1505func (dMgr *DeviceManager) disablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001506 logger.Debugw("disablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001507 var res interface{}
1508 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1509 res = agent.disablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001510 logger.Debugw("disablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001511 } else {
1512 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1513 }
1514
1515 sendResponse(ctx, ch, res)
1516}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001517
khenaidoo442e7c72020-03-10 16:13:48 -04001518// childDeviceLost calls parent adapter to delete child device and all its references
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001519func (dMgr *DeviceManager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001520 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001521 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001522 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1523 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001524 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001525 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001526 }
khenaidooe132f522020-03-20 15:23:15 -04001527 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1528 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001529}
onkarkundargi87285252020-01-27 11:34:52 +05301530
1531func (dMgr *DeviceManager) startOmciTest(ctx context.Context, omcitestrequest *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001532 logger.Debugw("Omci_test_Request", log.Fields{"device-id": omcitestrequest.Id, "uuid": omcitestrequest.Uuid})
onkarkundargi87285252020-01-27 11:34:52 +05301533 if agent := dMgr.getDeviceAgent(ctx, omcitestrequest.Id); agent != nil {
1534 res, err := agent.startOmciTest(ctx, omcitestrequest)
1535 if err != nil {
1536 return nil, err
1537 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001538 logger.Debugw("Omci_test_Response_result-device-magnager", log.Fields{"result": res})
onkarkundargi87285252020-01-27 11:34:52 +05301539 return res, nil
1540 }
1541 return nil, status.Errorf(codes.NotFound, "%s", omcitestrequest.Id)
1542}