blob: b88f38b35632082e729e3f06e4b884986fc5e81e [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
npujar1d86a522019-11-14 17:11:16 +053016
khenaidoob9203542018-09-17 22:56:37 -040017package core
18
19import (
20 "context"
21 "errors"
David Bainbridged1afd662020-03-26 18:27:41 -070022 "reflect"
23 "runtime"
24 "sync"
25 "time"
26
sbarbari17d7e222019-11-05 10:02:29 -050027 "github.com/opencord/voltha-go/db/model"
khenaidoo3d3b8c22019-05-22 18:10:39 -040028 "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080029 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
30 "github.com/opencord/voltha-lib-go/v3/pkg/log"
31 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
32 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
33 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
34 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040035 "google.golang.org/grpc/codes"
36 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040037)
38
npujar1d86a522019-11-14 17:11:16 +053039// DeviceManager represent device manager attributes
khenaidoob9203542018-09-17 22:56:37 -040040type DeviceManager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040041 deviceAgents sync.Map
42 rootDevices map[string]bool
43 lockRootDeviceMap sync.RWMutex
44 core *Core
45 adapterProxy *AdapterProxy
46 adapterMgr *AdapterManager
47 logicalDeviceMgr *LogicalDeviceManager
npujar467fe752020-01-16 20:17:45 +053048 kafkaICProxy kafka.InterContainerProxy
khenaidoo4c9e5592019-09-09 16:20:41 -040049 stateTransitions *TransitionMap
50 clusterDataProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053051 coreInstanceID string
khenaidoo4c9e5592019-09-09 16:20:41 -040052 exitChannel chan int
khenaidoo442e7c72020-03-10 16:13:48 -040053 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040054 devicesLoadingLock sync.RWMutex
55 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040056}
57
Richard Jankowski199fd862019-03-18 14:49:51 -040058func newDeviceManager(core *Core) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040059 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040060 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040061 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040062 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040063 deviceMgr.kafkaICProxy = core.kmp
Kent Hagermana6d0c362019-07-30 12:50:21 -040064 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic)
npujar1d86a522019-11-14 17:11:16 +053065 deviceMgr.coreInstanceID = core.instanceID
Richard Jankowski199fd862019-03-18 14:49:51 -040066 deviceMgr.clusterDataProxy = core.clusterDataProxy
67 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040068 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
khenaidoo442e7c72020-03-10 16:13:48 -040069 deviceMgr.defaultTimeout = time.Duration(core.config.DefaultCoreTimeout) * time.Millisecond
khenaidoo4c9e5592019-09-09 16:20:41 -040070 deviceMgr.devicesLoadingLock = sync.RWMutex{}
71 deviceMgr.deviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040072 return &deviceMgr
73}
74
khenaidoo4d4802d2018-10-04 21:59:49 -040075func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
Girish Kumarf56a4682020-03-20 20:07:46 +000076 logger.Info("starting-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040077 dMgr.logicalDeviceMgr = logicalDeviceMgr
78 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070079 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
Girish Kumarf56a4682020-03-20 20:07:46 +000080 logger.Info("device-manager-started")
khenaidoob9203542018-09-17 22:56:37 -040081}
82
khenaidoo4d4802d2018-10-04 21:59:49 -040083func (dMgr *DeviceManager) stop(ctx context.Context) {
Girish Kumarf56a4682020-03-20 20:07:46 +000084 logger.Info("stopping-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040085 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070086 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
Girish Kumarf56a4682020-03-20 20:07:46 +000087 logger.Info("device-manager-stopped")
khenaidoob9203542018-09-17 22:56:37 -040088}
89
90func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
91 if ctx.Err() == nil {
92 // Returned response only of the ctx has not been cancelled/timeout/etc
93 // Channel is automatically closed when a context is Done
94 ch <- result
Girish Kumarf56a4682020-03-20 20:07:46 +000095 logger.Debugw("sendResponse", log.Fields{"result": result})
khenaidoob9203542018-09-17 22:56:37 -040096 } else {
97 // Should the transaction be reverted back?
Girish Kumarf56a4682020-03-20 20:07:46 +000098 logger.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
khenaidoob9203542018-09-17 22:56:37 -040099 }
100}
101
102func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530103 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
104 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -0400105 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400106 dMgr.lockRootDeviceMap.Lock()
107 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530108 dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400109
khenaidoob9203542018-09-17 22:56:37 -0400110}
111
khenaidoo4c9e5592019-09-09 16:20:41 -0400112func (dMgr *DeviceManager) deleteDeviceAgentFromMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530113 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400114 dMgr.lockRootDeviceMap.Lock()
115 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530116 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400117}
118
khenaidoo297cd252019-02-07 22:10:23 -0500119// getDeviceAgent returns the agent managing the device. If the device is not in memory, it will loads it, if it exists
npujar467fe752020-01-16 20:17:45 +0530120func (dMgr *DeviceManager) getDeviceAgent(ctx context.Context, deviceID string) *DeviceAgent {
npujar1d86a522019-11-14 17:11:16 +0530121 agent, ok := dMgr.deviceAgents.Load(deviceID)
122 if ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400123 return agent.(*DeviceAgent)
khenaidoob9203542018-09-17 22:56:37 -0400124 }
khenaidoo442e7c72020-03-10 16:13:48 -0400125 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530126 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530127 if err == nil {
128 agent, ok = dMgr.deviceAgents.Load(deviceID)
129 if !ok {
130 return nil
131 }
npujar1d86a522019-11-14 17:11:16 +0530132 return agent.(*DeviceAgent)
133 }
134 //TODO: Change the return params to return an error as well
Girish Kumarf56a4682020-03-20 20:07:46 +0000135 logger.Errorw("loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400136 return nil
137}
138
khenaidoo297cd252019-02-07 22:10:23 -0500139// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500140func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500141 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400142
143 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
144 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
145 return true
146 })
147
khenaidoo7ccedd52018-12-14 16:48:54 -0500148 return result
149}
150
khenaidoob9203542018-09-17 22:56:37 -0400151func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
npujar467fe752020-01-16 20:17:45 +0530152 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530153 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000154 logger.Errorf("Failed to fetch parent device info")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530155 sendResponse(ctx, ch, err)
156 return
157 }
158 if deviceExist {
Girish Kumarf56a4682020-03-20 20:07:46 +0000159 logger.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530160 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
161 return
162 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000163 logger.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400164
khenaidoo5e677ae2019-02-28 17:26:29 -0500165 // Ensure this device is set as root
166 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400167 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400168 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530169 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800170 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000171 logger.Errorw("Fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530172 sendResponse(ctx, ch, err)
Scott Baker80678602019-11-14 16:57:36 -0800173 return
174 }
khenaidoo442e7c72020-03-10 16:13:48 -0400175 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -0400176
Scott Baker80678602019-11-14 16:57:36 -0800177 sendResponse(ctx, ch, device)
khenaidoob9203542018-09-17 22:56:37 -0400178}
179
180func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000181 logger.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400182 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530183 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400184 res = agent.enableDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000185 logger.Debugw("EnableDevice-result", log.Fields{"result": res})
Hardik Windlassb9cfcb12020-02-03 15:59:46 +0000186 } else {
187 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400188 }
189
190 sendResponse(ctx, ch, res)
191}
192
khenaidoo92e62c52018-10-03 14:02:54 -0400193func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000194 logger.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400195 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530196 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400197 res = agent.disableDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000198 logger.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400199 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400200 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400201 }
khenaidoo92e62c52018-10-03 14:02:54 -0400202
203 sendResponse(ctx, ch, res)
204}
205
khenaidoo4d4802d2018-10-04 21:59:49 -0400206func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000207 logger.Debugw("rebootDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400208 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530209 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400210 res = agent.rebootDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000211 logger.Debugw("rebootDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400212 } else {
213 res = status.Errorf(codes.NotFound, "%s", id.Id)
214 }
215 sendResponse(ctx, ch, res)
216}
217
218func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000219 logger.Debugw("deleteDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400220 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530221 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400222 res = agent.deleteDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000223 logger.Debugw("deleteDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400224 } else {
225 res = status.Errorf(codes.NotFound, "%s", id.Id)
226 }
227 sendResponse(ctx, ch, res)
228}
229
khenaidoo6d62c002019-05-15 21:57:03 -0400230// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
231// This function is called only in the Core that does not own this device. In the Core that owns this device then a
232// deletion deletion also includes removal of any reference of this device.
npujar467fe752020-01-16 20:17:45 +0530233func (dMgr *DeviceManager) stopManagingDevice(ctx context.Context, id string) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000234 logger.Infow("stopManagingDevice", log.Fields{"deviceId": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400235 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530236 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400237 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700238 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400239 }
npujar467fe752020-01-16 20:17:45 +0530240 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400241 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000242 logger.Warnw("unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400243 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400244 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400245 }
246 }
247}
248
npujar1d86a522019-11-14 17:11:16 +0530249// RunPostDeviceDelete removes any reference of this device
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500250func (dMgr *DeviceManager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000251 logger.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530252 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400253 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400254}
255
khenaidoo297cd252019-02-07 22:10:23 -0500256// GetDevice will returns a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530257func (dMgr *DeviceManager) GetDevice(ctx context.Context, id string) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000258 logger.Debugw("GetDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530259 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400260 return agent.getDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400261 }
262 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400263}
264
npujar1d86a522019-11-14 17:11:16 +0530265// GetChildDevice will return a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530266func (dMgr *DeviceManager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000267 logger.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
npujar1d86a522019-11-14 17:11:16 +0530268 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500269
270 var parentDevice *voltha.Device
271 var err error
npujar467fe752020-01-16 20:17:45 +0530272 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500273 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
274 }
275 var childDeviceIds []string
276 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
277 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
278 }
279 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000280 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530281 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500282 }
283
284 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530285 for _, childDeviceID := range childDeviceIds {
286 var found bool
npujar467fe752020-01-16 20:17:45 +0530287 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500288
npujar1d86a522019-11-14 17:11:16 +0530289 foundOnuID := false
290 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500291 if searchDevice.ParentPortNo == uint32(parentPortNo) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000292 logger.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530293 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500294 }
295 }
296
297 foundSerialNumber := false
298 if searchDevice.SerialNumber == serialNumber {
Girish Kumarf56a4682020-03-20 20:07:46 +0000299 logger.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500300 foundSerialNumber = true
301 }
302
303 // if both onuId and serialNumber are provided both must be true for the device to be found
304 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530305 if onuID > 0 && serialNumber != "" {
306 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500307 } else {
npujar1d86a522019-11-14 17:11:16 +0530308 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500309 }
310
npujar1d86a522019-11-14 17:11:16 +0530311 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500312 foundChildDevice = searchDevice
313 break
314 }
315 }
316 }
317
318 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000319 logger.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500320 return foundChildDevice, nil
321 }
322
Girish Kumarf56a4682020-03-20 20:07:46 +0000323 logger.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530324 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
325 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500326}
327
npujar1d86a522019-11-14 17:11:16 +0530328// GetChildDeviceWithProxyAddress will return a device based on proxy address
npujar467fe752020-01-16 20:17:45 +0530329func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000330 logger.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500331
332 var parentDevice *voltha.Device
333 var err error
npujar467fe752020-01-16 20:17:45 +0530334 if parentDevice, err = dMgr.GetDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500335 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
336 }
337 var childDeviceIds []string
338 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
339 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
340 }
341 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000342 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500343 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
344 }
345
346 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530347 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530348 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500349 if searchDevice.ProxyAddress == proxyAddress {
350 foundChildDevice = searchDevice
351 break
352 }
353 }
354 }
355
356 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000357 logger.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500358 return foundChildDevice, nil
359 }
360
Girish Kumarf56a4682020-03-20 20:07:46 +0000361 logger.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500362 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
363}
364
npujar1d86a522019-11-14 17:11:16 +0530365// IsDeviceInCache returns true if device is found in the map
khenaidoo297cd252019-02-07 22:10:23 -0500366func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400367 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500368 return exist
369}
370
npujar1d86a522019-11-14 17:11:16 +0530371// IsRootDevice returns true if root device is found in the map
khenaidoo19d7b632018-10-30 10:49:50 -0400372func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400373 dMgr.lockRootDeviceMap.RLock()
374 defer dMgr.lockRootDeviceMap.RUnlock()
375 if exist := dMgr.rootDevices[id]; exist {
376 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400377 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400378 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400379}
380
Stephane Barbarieaa467942019-02-06 14:09:44 -0500381// ListDevices retrieves the latest devices from the data model
npujar467fe752020-01-16 20:17:45 +0530382func (dMgr *DeviceManager) ListDevices(ctx context.Context) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000383 logger.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400384 result := &voltha.Devices{}
npujar467fe752020-01-16 20:17:45 +0530385 devices, err := dMgr.clusterDataProxy.List(ctx, "/devices", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530386 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000387 logger.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530388 return nil, err
389 }
390 if devices != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400391 for _, d := range devices.([]interface{}) {
392 device := d.(*voltha.Device)
khenaidoo297cd252019-02-07 22:10:23 -0500393 // If device is not in memory then set it up
khenaidoo442e7c72020-03-10 16:13:48 -0400394 if !dMgr.IsDeviceInCache(device.Id) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000395 logger.Debugw("loading-device-from-Model", log.Fields{"id": device.Id})
khenaidoo442e7c72020-03-10 16:13:48 -0400396 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530397 if _, err := agent.start(ctx, nil); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000398 logger.Warnw("failure-starting-agent", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500399 } else {
400 dMgr.addDeviceAgentToMap(agent)
401 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500402 }
khenaidoo442e7c72020-03-10 16:13:48 -0400403 result.Items = append(result.Items, device)
khenaidoob9203542018-09-17 22:56:37 -0400404 }
405 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000406 logger.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400407 return result, nil
408}
409
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530410//isParentDeviceExist checks whether device is already preprovisioned.
npujar467fe752020-01-16 20:17:45 +0530411func (dMgr *DeviceManager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530412 hostPort := newDevice.GetHostAndPort()
npujar467fe752020-01-16 20:17:45 +0530413 devices, err := dMgr.clusterDataProxy.List(ctx, "/devices", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530414 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000415 logger.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530416 return false, err
417 }
418 if devices != nil {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530419 for _, device := range devices.([]interface{}) {
420 if !device.(*voltha.Device).Root {
421 continue
422 }
David Bainbridged1afd662020-03-26 18:27:41 -0700423 if hostPort != "" && hostPort == device.(*voltha.Device).GetHostAndPort() && device.(*voltha.Device).AdminState != voltha.AdminState_DELETED {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530424 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530425 }
David Bainbridged1afd662020-03-26 18:27:41 -0700426 if newDevice.MacAddress != "" && newDevice.MacAddress == device.(*voltha.Device).MacAddress && device.(*voltha.Device).AdminState != voltha.AdminState_DELETED {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530427 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530428 }
429 }
430 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530431 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530432}
433
khenaidoo6d62c002019-05-15 21:57:03 -0400434//getDeviceFromModelretrieves the device data from the model.
npujar467fe752020-01-16 20:17:45 +0530435func (dMgr *DeviceManager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
436 device, err := dMgr.clusterDataProxy.Get(ctx, "/devices/"+deviceID, 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530437 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000438 logger.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530439 return nil, err
440 }
441 if device != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400442 if d, ok := device.(*voltha.Device); ok {
443 return d, nil
444 }
445 }
npujar1d86a522019-11-14 17:11:16 +0530446 return nil, status.Error(codes.NotFound, deviceID)
khenaidoo6d62c002019-05-15 21:57:03 -0400447}
448
npujar1d86a522019-11-14 17:11:16 +0530449// loadDevice loads the deviceID in memory, if not present
npujar467fe752020-01-16 20:17:45 +0530450func (dMgr *DeviceManager) loadDevice(ctx context.Context, deviceID string) (*DeviceAgent, error) {
npujar1d86a522019-11-14 17:11:16 +0530451 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500452 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
453 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400454 var err error
455 var device *voltha.Device
456 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530457 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
458 if !dMgr.IsDeviceInCache(deviceID) {
459 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400460 dMgr.devicesLoadingLock.Unlock()
461 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530462 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000463 logger.Debugw("loading-device", log.Fields{"deviceId": deviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400464 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530465 if _, err = agent.start(ctx, nil); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000466 logger.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400467 } else {
468 dMgr.addDeviceAgentToMap(agent)
469 }
470 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000471 logger.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400472 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400473 // announce completion of task to any number of waiting channels
474 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530475 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400476 for _, ch := range v {
477 close(ch)
478 }
npujar1d86a522019-11-14 17:11:16 +0530479 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400480 }
481 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400482 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400483 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500484 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400485 } else {
486 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530487 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400488 dMgr.devicesLoadingLock.Unlock()
489 // Wait for the channel to be closed, implying the process loading this device is done.
490 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500491 }
npujar1d86a522019-11-14 17:11:16 +0530492 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400493 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500494 }
npujar1d86a522019-11-14 17:11:16 +0530495 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500496}
497
498// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
npujar467fe752020-01-16 20:17:45 +0530499func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000500 logger.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500501 if device.Root {
502 // Scenario A
503 if device.ParentId != "" {
504 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530505 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000506 logger.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500507 }
508 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000509 logger.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500510 }
511 // Load all child devices, if needed
512 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530513 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530514 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000515 logger.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500516 return err
517 }
518 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000519 logger.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500520 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000521 logger.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500522 }
523 }
524 return nil
525}
526
527// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
528// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
529// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
530// and the proceed with the request.
npujar467fe752020-01-16 20:17:45 +0530531func (dMgr *DeviceManager) load(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000532 logger.Debug("load...")
khenaidoo297cd252019-02-07 22:10:23 -0500533 // First load the device - this may fail in case the device was deleted intentionally by the other core
534 var dAgent *DeviceAgent
535 var err error
npujar467fe752020-01-16 20:17:45 +0530536 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500537 return err
538 }
539 // Get the loaded device details
khenaidoo442e7c72020-03-10 16:13:48 -0400540 device, err := dAgent.getDevice(ctx)
541 if err != nil {
542 return err
543 }
khenaidoo297cd252019-02-07 22:10:23 -0500544
545 // If the device is in Pre-provisioning or deleted state stop here
546 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
547 return nil
548 }
549
550 // Now we face two scenarios
551 if device.Root {
552 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530553 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000554 logger.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500555 return err
556 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000557 logger.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500558 } else {
559 // Scenario B - use the parentId of that device (root device) to trigger the loading
560 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530561 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500562 }
563 }
564 return nil
565}
566
khenaidoo7ccedd52018-12-14 16:48:54 -0500567// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
568func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000569 logger.Debug("ListDeviceIDs")
khenaidoo7ccedd52018-12-14 16:48:54 -0500570 // Report only device IDs that are in the device agent map
571 return dMgr.listDeviceIdsFromMap(), nil
572}
573
khenaidoo4c9e5592019-09-09 16:20:41 -0400574//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
575//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500576func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000577 logger.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500578 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400579 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500580 toReconcile := len(ids.Items)
581 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400582 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500583 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530584 if err = dMgr.load(ctx, id.Id); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000585 logger.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400586 } else {
npujar1d86a522019-11-14 17:11:16 +0530587 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500588 }
589 }
590 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400591 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500592 }
593 } else {
594 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
595 }
596 sendResponse(ctx, ch, res)
597}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500598
khenaidooba6b6c42019-08-02 09:11:56 -0400599// isOkToReconcile validates whether a device is in the correct status to be reconciled
600func isOkToReconcile(device *voltha.Device) bool {
601 if device == nil {
602 return false
603 }
604 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
605}
606
607// adapterRestarted is invoked whenever an adapter is restarted
npujar467fe752020-01-16 20:17:45 +0530608func (dMgr *DeviceManager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000609 logger.Debugw("adapter-restarted", log.Fields{"adapter": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400610
611 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700612 if len(dMgr.rootDevices) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000613 logger.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400614 return nil
615 }
616
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500617 responses := make([]utils.Response, 0)
David Bainbridged1afd662020-03-26 18:27:41 -0700618 for rootDeviceID := range dMgr.rootDevices {
npujar467fe752020-01-16 20:17:45 +0530619 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400620 if rootDevice.Adapter == adapter.Id {
621 if isOkToReconcile(rootDevice) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000622 logger.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530623 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400624 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000625 logger.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400626 }
627 } else { // Should we be reconciling the root's children instead?
628 childManagedByAdapter:
629 for _, port := range rootDevice.Ports {
630 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530631 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400632 if childDevice.Adapter == adapter.Id {
633 if isOkToReconcile(childDevice) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000634 logger.Debugw("reconciling-child-device", log.Fields{"childId": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530635 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400636 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000637 logger.Debugw("not-reconciling-child-device", log.Fields{"childId": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400638 }
639 } else {
640 // All child devices under a parent device are typically managed by the same adapter type.
641 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
642 break childManagedByAdapter
643 }
644 }
645 }
646 }
647 }
648 }
649 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500650 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400651 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500652 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400653 return status.Errorf(codes.Aborted, "errors-%s", res)
654 }
655 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000656 logger.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400657 }
658 return nil
659}
660
npujar467fe752020-01-16 20:17:45 +0530661func (dMgr *DeviceManager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400662 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
663 // 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 +0530664 // 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 -0400665 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500666 response := utils.NewResponse()
khenaidoo442e7c72020-03-10 16:13:48 -0400667 ch, err := dMgr.adapterProxy.reconcileDevice(ctx, device)
668 if err != nil {
669 response.Error(err)
670 }
671 // Wait for adapter response in its own routine
672 go func() {
673 resp, ok := <-ch
674 if !ok {
675 response.Error(status.Errorf(codes.Aborted, "channel-closed-device: %s", device.Id))
676 } else if resp.Err != nil {
677 response.Error(resp.Err)
khenaidooba6b6c42019-08-02 09:11:56 -0400678 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500679 response.Done()
khenaidoo442e7c72020-03-10 16:13:48 -0400680 }()
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500681 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400682}
683
npujar467fe752020-01-16 20:17:45 +0530684func (dMgr *DeviceManager) reconcileChildDevices(ctx context.Context, parentDeviceID string) error {
685 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500686 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400687 for _, port := range parentDevice.Ports {
688 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530689 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
690 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400691 }
692 }
693 }
694 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500695 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400696 return status.Errorf(codes.Aborted, "errors-%s", res)
697 }
698 }
699 return nil
700}
701
npujar467fe752020-01-16 20:17:45 +0530702func (dMgr *DeviceManager) updateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000703 logger.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530704 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
705 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400706 }
707 return status.Errorf(codes.NotFound, "%s", device.Id)
708}
709
npujar467fe752020-01-16 20:17:45 +0530710func (dMgr *DeviceManager) addPort(ctx context.Context, deviceID string, port *voltha.Port) error {
711 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530712 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530713 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400714 return err
715 }
716 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530717 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400718 for _, peerPort := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530719 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
720 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000721 logger.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
khenaidoo92e62c52018-10-03 14:02:54 -0400722 return err
723 }
724 }
725 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400726 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
727 // then a logical port will be added to the logical device and the device graph generated. If the port is a
728 // PON port then only the device graph will be generated.
npujar467fe752020-01-16 20:17:45 +0530729 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530730 go func() {
npujar467fe752020-01-16 20:17:45 +0530731 err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port)
npujar1d86a522019-11-14 17:11:16 +0530732 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000733 logger.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530734 }
735 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400736 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000737 logger.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400738 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400739 }
khenaidoo92e62c52018-10-03 14:02:54 -0400740 return nil
khenaidoob9203542018-09-17 22:56:37 -0400741 }
npujar1d86a522019-11-14 17:11:16 +0530742 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400743}
744
npujar467fe752020-01-16 20:17:45 +0530745func (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 +0000746 logger.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530747 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
748 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400749 }
npujar1d86a522019-11-14 17:11:16 +0530750 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400751}
752
npujar467fe752020-01-16 20:17:45 +0530753func (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 +0000754 logger.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530755 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
756 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400757 }
npujar1d86a522019-11-14 17:11:16 +0530758 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400759}
760
npujar467fe752020-01-16 20:17:45 +0530761func (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 +0000762 logger.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530763 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
764 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400765 }
npujar1d86a522019-11-14 17:11:16 +0530766 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400767}
768
khenaidoob3127472019-07-24 21:04:55 -0400769// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
770// following a user action
771func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
772 var res interface{}
773 if pmConfigs.Id == "" {
774 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
npujar467fe752020-01-16 20:17:45 +0530775 } else if agent := dMgr.getDeviceAgent(ctx, pmConfigs.Id); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400776 res = agent.updatePmConfigs(ctx, pmConfigs)
777 } else {
778 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
779 }
780 sendResponse(ctx, ch, res)
781}
782
783// initPmConfigs initialize the pm configs as defined by the adapter.
npujar467fe752020-01-16 20:17:45 +0530784func (dMgr *DeviceManager) initPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400785 if pmConfigs.Id == "" {
786 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
787 }
npujar467fe752020-01-16 20:17:45 +0530788 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
789 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400790 }
npujar1d86a522019-11-14 17:11:16 +0530791 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400792}
793
npujar1d86a522019-11-14 17:11:16 +0530794func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
npujar467fe752020-01-16 20:17:45 +0530795 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400796 return agent.listPmConfigs(ctx)
797 }
npujar1d86a522019-11-14 17:11:16 +0530798 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400799}
800
npujar1d86a522019-11-14 17:11:16 +0530801func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000802 logger.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530803 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400804 return agent.getSwitchCapability(ctx)
805 }
npujar1d86a522019-11-14 17:11:16 +0530806 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400807}
808
npujar1d86a522019-11-14 17:11:16 +0530809func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000810 logger.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530811 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400812 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400813 }
npujar1d86a522019-11-14 17:11:16 +0530814 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400815}
816
npujar1d86a522019-11-14 17:11:16 +0530817func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000818 logger.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530819 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400820 return agent.getPortCapability(ctx, portNo)
821 }
npujar1d86a522019-11-14 17:11:16 +0530822 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400823}
824
npujar467fe752020-01-16 20:17:45 +0530825func (dMgr *DeviceManager) updateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000826 logger.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530827 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
828 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400829 }
npujar1d86a522019-11-14 17:11:16 +0530830 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400831}
832
npujar467fe752020-01-16 20:17:45 +0530833func (dMgr *DeviceManager) updateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000834 logger.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400835 var parentDevice *voltha.Device
836 var err error
npujar467fe752020-01-16 20:17:45 +0530837 if parentDevice, err = dMgr.GetDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400838 return status.Errorf(codes.Aborted, "%s", err.Error())
839 }
840 var childDeviceIds []string
841 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
842 return status.Errorf(codes.Aborted, "%s", err.Error())
843 }
844 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000845 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400846 }
npujar1d86a522019-11-14 17:11:16 +0530847 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530848 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
849 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530850 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400851 }
852 }
853 }
854 return nil
855}
856
npujar467fe752020-01-16 20:17:45 +0530857func (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 +0000858 logger.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530859 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
860 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000861 logger.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400862 return err
863 }
864 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800865 // Do this for NNI and UNIs only. PON ports are not known by logical device
866 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
867 go func() {
868 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
869 if err != nil {
870 // While we want to handle (catch) and log when
871 // an update to a port was not able to be
872 // propagated to the logical port, we can report
873 // it as a warning and not an error because it
874 // doesn't stop or modify processing.
875 // TODO: VOL-2707
Girish Kumarf56a4682020-03-20 20:07:46 +0000876 logger.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800877 }
878 }()
879 }
khenaidoo442e7c72020-03-10 16:13:48 -0400880 return nil
khenaidoob9203542018-09-17 22:56:37 -0400881 }
npujar1d86a522019-11-14 17:11:16 +0530882 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400883}
884
npujar467fe752020-01-16 20:17:45 +0530885func (dMgr *DeviceManager) deleteAllPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000886 logger.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530887 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
888 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400889 return err
890 }
891 // Notify the logical device manager to remove all logical ports, if needed.
892 // At this stage the device itself may gave been deleted already at a deleteAllPorts
893 // typically is part of a device deletion phase.
npujar467fe752020-01-16 20:17:45 +0530894 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530895 go func() {
npujar467fe752020-01-16 20:17:45 +0530896 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530897 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000898 logger.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530899 }
900 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400901 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000902 logger.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400903 return err
904 }
905 return nil
906 }
npujar1d86a522019-11-14 17:11:16 +0530907 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400908}
909
khenaidoo3ab34882019-05-02 21:33:30 -0400910//updatePortsState updates all ports on the device
npujar467fe752020-01-16 20:17:45 +0530911func (dMgr *DeviceManager) updatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000912 logger.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400913
npujar467fe752020-01-16 20:17:45 +0530914 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400915 switch state {
916 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500917 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000918 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400919 return err
920 }
921 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500922 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000923 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400924 return err
925 }
926 default:
927 return status.Error(codes.Unimplemented, "state-change-not-implemented")
928 }
929 // Notify the logical device about the state change
npujar467fe752020-01-16 20:17:45 +0530930 device, err := dMgr.GetDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530931 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000932 logger.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400933 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400934 }
kesavandbc2d1622020-01-21 00:42:01 -0500935 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000936 logger.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530937 return err
938 }
939 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400940 }
npujar1d86a522019-11-14 17:11:16 +0530941 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400942}
943
npujar467fe752020-01-16 20:17:45 +0530944func (dMgr *DeviceManager) childDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530945 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000946 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 -0700947
npujar1d86a522019-11-14 17:11:16 +0530948 if deviceType == "" && vendorID != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000949 logger.Debug("device-type-is-nil-fetching-device-type")
npujar467fe752020-01-16 20:17:45 +0530950 deviceTypesIf, err := dMgr.adapterMgr.clusterDataProxy.List(ctx, "/device_types", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530951 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000952 logger.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530953 return nil, err
954 }
955 if deviceTypesIf != nil {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700956 OLoop:
957 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
958 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
959 for _, v := range dType.VendorIds {
npujar1d86a522019-11-14 17:11:16 +0530960 if v == vendorID {
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700961 deviceType = dType.Adapter
962 break OLoop
963 }
964 }
965 }
966 }
967 }
968 }
969 //if no match found for the vendorid,report adapter with the custom error message
970 if deviceType == "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000971 logger.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +0530972 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700973 }
khenaidoob9203542018-09-17 22:56:37 -0400974
975 // Create the ONU device
976 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400977 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530978 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400979 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530980 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500981 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400982 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400983
khenaidoo442e7c72020-03-10 16:13:48 -0400984 // Get parent device type
985 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
986 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +0530987 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400988 }
khenaidoo442e7c72020-03-10 16:13:48 -0400989 if pAgent.deviceType == "" {
990 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
991 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400992
npujar467fe752020-01-16 20:17:45 +0530993 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000994 logger.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700995 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500996 }
997
khenaidoo442e7c72020-03-10 16:13:48 -0400998 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -0400999
1000 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -04001001 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -04001002 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001003 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001004 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 -08001005 return nil, err
1006 }
khenaidoo442e7c72020-03-10 16:13:48 -04001007 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001008
1009 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301010 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301011 go func() {
npujar467fe752020-01-16 20:17:45 +05301012 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301013 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001014 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301015 }
1016 }()
khenaidoob9203542018-09-17 22:56:37 -04001017 }
1018
khenaidoo79232702018-12-04 11:00:41 -05001019 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301020 go func() {
1021 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1022 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001023 logger.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301024 }
1025 }()
khenaidoo79232702018-12-04 11:00:41 -05001026
Scott Baker80678602019-11-14 16:57:36 -08001027 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001028}
1029
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001030func (dMgr *DeviceManager) processTransition(ctx context.Context, device *voltha.Device, previousState *DeviceState) error {
1031 // This will be triggered on every state update
1032 logger.Debugw("state-transition", log.Fields{
1033 "device": device.Id,
1034 "prev-admin-state": previousState.Admin,
1035 "prev-oper-state": previousState.Operational,
1036 "prev-conn-state": previousState.Connection,
1037 "curr-admin-state": device.AdminState,
1038 "curr-oper-state": device.OperStatus,
1039 "curr-conn-state": device.ConnectStatus,
1040 })
1041 handlers := dMgr.stateTransitions.GetTransitionHandler(device, previousState)
khenaidoo92e62c52018-10-03 14:02:54 -04001042 if handlers == nil {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001043 logger.Debugw("no-op-transition", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001044 return nil
khenaidoob9203542018-09-17 22:56:37 -04001045 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001046 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 -04001047 for _, handler := range handlers {
Girish Kumarf56a4682020-03-20 20:07:46 +00001048 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001049 if err := handler(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001050 logger.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001051 return err
1052 }
1053 }
khenaidoob9203542018-09-17 22:56:37 -04001054 return nil
1055}
1056
npujar467fe752020-01-16 20:17:45 +05301057func (dMgr *DeviceManager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001058 logger.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301059 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1060 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001061 }
npujar1d86a522019-11-14 17:11:16 +05301062 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001063}
1064
npujar1d86a522019-11-14 17:11:16 +05301065// PacketIn receives packet from adapter
npujar467fe752020-01-16 20:17:45 +05301066func (dMgr *DeviceManager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001067 logger.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001068 // Get the logical device Id based on the deviceId
1069 var device *voltha.Device
1070 var err error
npujar467fe752020-01-16 20:17:45 +05301071 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001072 logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001073 return err
1074 }
khenaidoo43c82122018-11-22 18:38:28 -05001075 if !device.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +00001076 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301077 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001078 }
1079
npujar467fe752020-01-16 20:17:45 +05301080 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001081 return err
1082 }
1083 return nil
1084}
1085
npujar467fe752020-01-16 20:17:45 +05301086func (dMgr *DeviceManager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001087 logger.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301088 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1089 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001090 }
1091 return status.Errorf(codes.NotFound, "%s", device.Id)
1092}
1093
npujar1d86a522019-11-14 17:11:16 +05301094// CreateLogicalDevice creates logical device in core
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001095func (dMgr *DeviceManager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001096 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001097 // Verify whether the logical device has already been created
1098 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001099 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001100 return nil
1101 }
khenaidoob9203542018-09-17 22:56:37 -04001102 var err error
npujar467fe752020-01-16 20:17:45 +05301103 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001104 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001105 return err
1106 }
khenaidoob9203542018-09-17 22:56:37 -04001107 return nil
1108}
1109
npujar1d86a522019-11-14 17:11:16 +05301110// DeleteLogicalDevice deletes logical device from core
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001111func (dMgr *DeviceManager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001112 logger.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001113 var err error
npujar467fe752020-01-16 20:17:45 +05301114 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001115 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001116 return err
1117 }
1118 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301119 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301120 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001121 return nil
1122}
1123
npujar1d86a522019-11-14 17:11:16 +05301124// DeleteLogicalPort removes the logical port associated with a device
npujar467fe752020-01-16 20:17:45 +05301125func (dMgr *DeviceManager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001126 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001127 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001128 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301129 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301130 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001131 logger.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001132 return err
1133 }
npujar467fe752020-01-16 20:17:45 +05301134 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001135 logger.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001136 return err
1137 }
khenaidoo92e62c52018-10-03 14:02:54 -04001138 return nil
1139}
1140
npujar1d86a522019-11-14 17:11:16 +05301141// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001142func (dMgr *DeviceManager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001143 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001144 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001145 // 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 +00001146 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001147 }
1148 return nil
1149}
1150
npujar467fe752020-01-16 20:17:45 +05301151func (dMgr *DeviceManager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001152 // Sanity check
1153 if childDevice.Root {
1154 // childDevice is the parent device
1155 return childDevice
1156 }
npujar467fe752020-01-16 20:17:45 +05301157 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001158 return parentDevice
1159}
1160
khenaidoo0a822f92019-05-08 15:15:57 -04001161//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1162//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar467fe752020-01-16 20:17:45 +05301163func (dMgr *DeviceManager) childDevicesLost(ctx context.Context, parentDeviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001164 logger.Debug("childDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001165 var err error
1166 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301167 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001168 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001169 return err
1170 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001171 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001172}
1173
1174//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1175// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar467fe752020-01-16 20:17:45 +05301176func (dMgr *DeviceManager) childDevicesDetected(ctx context.Context, parentDeviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001177 logger.Debug("childDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001178 var err error
1179 var parentDevice *voltha.Device
1180 var childDeviceIds []string
1181
npujar467fe752020-01-16 20:17:45 +05301182 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001183 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001184 return err
1185 }
1186
1187 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1188 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1189 }
1190 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001191 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001192 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001193 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301194 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301195 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001196 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301197 go func() {
npujar467fe752020-01-16 20:17:45 +05301198 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301199 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001200 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301201 }
1202 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001203 } else {
npujar1d86a522019-11-14 17:11:16 +05301204 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Girish Kumarf56a4682020-03-20 20:07:46 +00001205 logger.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001206 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001207 }
1208 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001209 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001210 return err
1211 }
1212 return nil
1213}
1214
khenaidoo4d4802d2018-10-04 21:59:49 -04001215/*
1216All the functions below are callback functions where they are invoked with the latest and previous data. We can
1217therefore use the data as is without trying to get the latest from the model.
1218*/
1219
khenaidoo0a822f92019-05-08 15:15:57 -04001220//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001221func (dMgr *DeviceManager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001222 logger.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001223 var childDeviceIds []string
1224 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001225 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1226 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001227 }
1228 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001229 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001230 }
npujar1d86a522019-11-14 17:11:16 +05301231 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301232 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1233 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001234 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001235 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001236 }
1237 }
1238 }
1239 return nil
1240}
1241
khenaidoo0a822f92019-05-08 15:15:57 -04001242//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001243func (dMgr *DeviceManager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001244 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001245 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001246 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001247 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1248 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001249 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001250 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001251 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001252 }
npujar1d86a522019-11-14 17:11:16 +05301253 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301254 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1255 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001256 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001257 }
khenaidoo49085352020-01-13 19:15:43 -05001258 // No further action is required here. The deleteDevice will change the device state where the resulting
1259 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001260 }
1261 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001262 return nil
1263}
1264
Hardik Windlassc704def2020-02-26 18:23:19 +00001265//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001266func (dMgr *DeviceManager) DeleteAllUNILogicalPorts(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001267 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": curr.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001268 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, curr); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001269 // Just log the error and let the remaining pipeline proceed - ports may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001270 logger.Warnw("delete-all-uni-logical-ports-failed", log.Fields{"parent-device-id": curr.Id, "error": err})
Hardik Windlassc704def2020-02-26 18:23:19 +00001271 }
1272 return nil
1273}
1274
Girish Gowdra408cd962020-03-11 14:31:31 -07001275//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001276func (dMgr *DeviceManager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001277 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001278 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001279 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001280 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001281 }
1282 return nil
1283}
1284
1285//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001286func (dMgr *DeviceManager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001287 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001288 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1289 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001290 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001291 return err
1292 }
1293 return nil
1294 }
1295 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1296}
1297
khenaidoo4d4802d2018-10-04 21:59:49 -04001298//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1299func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001300 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001301 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001302 if parentDevice != nil {
1303 for _, port := range parentDevice.Ports {
1304 for _, peer := range port.Peers {
1305 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1306 }
khenaidoo92e62c52018-10-03 14:02:54 -04001307 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001308 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001309 }
1310 return childDeviceIds, nil
1311}
1312
khenaidoo297cd252019-02-07 22:10:23 -05001313//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar467fe752020-01-16 20:17:45 +05301314func (dMgr *DeviceManager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001315 logger.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301316 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001317 childDevices := make([]*voltha.Device, 0)
1318 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301319 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301320 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001321 childDevices = append(childDevices, d)
1322 }
1323 }
1324 }
1325 return &voltha.Devices{Items: childDevices}, nil
1326 }
npujar1d86a522019-11-14 17:11:16 +05301327 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001328}
1329
npujar1d86a522019-11-14 17:11:16 +05301330// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001331func (dMgr *DeviceManager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001332 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301333 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001334 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001335 return err
1336 }
1337 return nil
1338}
1339
khenaidoof5a5bfa2019-01-23 22:20:29 -05001340func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001341 logger.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001342 var res interface{}
1343 var err error
npujar467fe752020-01-16 20:17:45 +05301344 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001345 if res, err = agent.downloadImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001346 logger.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001347 res = err
1348 }
1349 } else {
1350 res = status.Errorf(codes.NotFound, "%s", img.Id)
1351 }
1352 sendResponse(ctx, ch, res)
1353}
1354
1355func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001356 logger.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001357 var res interface{}
1358 var err error
npujar467fe752020-01-16 20:17:45 +05301359 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001360 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001361 logger.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001362 res = err
1363 }
1364 } else {
1365 res = status.Errorf(codes.NotFound, "%s", img.Id)
1366 }
1367 sendResponse(ctx, ch, res)
1368}
1369
1370func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001371 logger.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001372 var res interface{}
1373 var err error
npujar467fe752020-01-16 20:17:45 +05301374 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001375 if res, err = agent.activateImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001376 logger.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001377 res = err
1378 }
1379 } else {
1380 res = status.Errorf(codes.NotFound, "%s", img.Id)
1381 }
1382 sendResponse(ctx, ch, res)
1383}
1384
1385func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001386 logger.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001387 var res interface{}
1388 var err error
npujar467fe752020-01-16 20:17:45 +05301389 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001390 if res, err = agent.revertImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001391 logger.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001392 res = err
1393 }
1394 } else {
1395 res = status.Errorf(codes.NotFound, "%s", img.Id)
1396 }
1397 sendResponse(ctx, ch, res)
1398}
1399
1400func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001401 logger.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001402 var res interface{}
1403 var err error
npujar467fe752020-01-16 20:17:45 +05301404 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001405 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001406 logger.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001407 res = err
1408 }
1409 } else {
1410 res = status.Errorf(codes.NotFound, "%s", img.Id)
1411 }
1412 sendResponse(ctx, ch, res)
1413}
1414
npujar467fe752020-01-16 20:17:45 +05301415func (dMgr *DeviceManager) updateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001416 logger.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301417 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1418 if err := agent.updateImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001419 logger.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001420 return err
1421 }
1422 } else {
1423 return status.Errorf(codes.NotFound, "%s", img.Id)
1424 }
1425 return nil
1426}
1427
1428func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001429 logger.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301430 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001431 return agent.getImageDownload(ctx, img)
1432 }
1433 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1434}
1435
npujar1d86a522019-11-14 17:11:16 +05301436func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001437 logger.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301438 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301439 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001440 }
npujar1d86a522019-11-14 17:11:16 +05301441 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001442}
1443
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001444func (dMgr *DeviceManager) NotifyInvalidTransition(_ context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001445 logger.Errorw("NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001446 "device": device.Id,
1447 "curr-admin-state": device.AdminState,
1448 "curr-oper-state": device.OperStatus,
1449 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001450 })
khenaidoo0a822f92019-05-08 15:15:57 -04001451 //TODO: notify over kafka?
1452 return nil
1453}
1454
khenaidoob9203542018-09-17 22:56:37 -04001455func funcName(f interface{}) string {
1456 p := reflect.ValueOf(f).Pointer()
1457 rf := runtime.FuncForPC(p)
1458 return rf.Name()
1459}
1460
npujar1d86a522019-11-14 17:11:16 +05301461// UpdateDeviceAttribute updates value of particular device attribute
npujar467fe752020-01-16 20:17:45 +05301462func (dMgr *DeviceManager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301463 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
npujar467fe752020-01-16 20:17:45 +05301464 agent.(*DeviceAgent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001465 }
1466}
1467
npujar1d86a522019-11-14 17:11:16 +05301468// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +05301469func (dMgr *DeviceManager) GetParentDeviceID(ctx context.Context, deviceID string) string {
1470 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001471 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001472 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001473 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001474 return ""
khenaidoob9203542018-09-17 22:56:37 -04001475}
serkant.uluderya334479d2019-04-10 08:26:15 -07001476
1477func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001478 logger.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
serkant.uluderya334479d2019-04-10 08:26:15 -07001479 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1480 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1481 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301482 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001483 res = agent.simulateAlarm(ctx, simulatereq)
Girish Kumarf56a4682020-03-20 20:07:46 +00001484 logger.Debugw("simulateAlarm-result", log.Fields{"result": res})
serkant.uluderya334479d2019-04-10 08:26:15 -07001485 }
1486 //TODO CLI always get successful response
1487 sendResponse(ctx, ch, res)
1488}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001489
npujar467fe752020-01-16 20:17:45 +05301490func (dMgr *DeviceManager) updateDeviceReason(ctx context.Context, deviceID string, reason string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001491 logger.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301492 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1493 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001494 }
npujar1d86a522019-11-14 17:11:16 +05301495 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001496}
kesavandbc2d1622020-01-21 00:42:01 -05001497
1498func (dMgr *DeviceManager) enablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001499 logger.Debugw("enablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001500 var res interface{}
1501 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1502 res = agent.enablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001503 logger.Debugw("enablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001504 } else {
1505 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1506 }
1507
1508 sendResponse(ctx, ch, res)
1509}
1510
1511func (dMgr *DeviceManager) disablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001512 logger.Debugw("disablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001513 var res interface{}
1514 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1515 res = agent.disablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001516 logger.Debugw("disablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001517 } else {
1518 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1519 }
1520
1521 sendResponse(ctx, ch, res)
1522}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001523
khenaidoo442e7c72020-03-10 16:13:48 -04001524// childDeviceLost calls parent adapter to delete child device and all its references
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001525func (dMgr *DeviceManager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001526 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001527 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001528 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1529 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001530 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001531 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001532 }
khenaidooe132f522020-03-20 15:23:15 -04001533 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1534 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001535}
onkarkundargi87285252020-01-27 11:34:52 +05301536
1537func (dMgr *DeviceManager) startOmciTest(ctx context.Context, omcitestrequest *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001538 logger.Debugw("Omci_test_Request", log.Fields{"device-id": omcitestrequest.Id, "uuid": omcitestrequest.Uuid})
onkarkundargi87285252020-01-27 11:34:52 +05301539 if agent := dMgr.getDeviceAgent(ctx, omcitestrequest.Id); agent != nil {
1540 res, err := agent.startOmciTest(ctx, omcitestrequest)
1541 if err != nil {
1542 return nil, err
1543 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001544 logger.Debugw("Omci_test_Response_result-device-magnager", log.Fields{"result": res})
onkarkundargi87285252020-01-27 11:34:52 +05301545 return res, nil
1546 }
1547 return nil, status.Errorf(codes.NotFound, "%s", omcitestrequest.Id)
1548}