blob: 1a1b773a6a4a818428d1fc66f21f755137efcc65 [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
khenaidoo442e7c72020-03-10 16:13:48 -0400250func (dMgr *DeviceManager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device, pDevice *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
npujar467fe752020-01-16 20:17:45 +05301030func (dMgr *DeviceManager) processTransition(ctx context.Context, previous *voltha.Device, current *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -04001031 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -04001032 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
1033 if handlers == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001034 logger.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001035 return nil
khenaidoob9203542018-09-17 22:56:37 -04001036 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001037 logger.Debugw("handler-found", log.Fields{"num-expectedHandlers": len(handlers), "isParent": current.Root, "current-data": current})
khenaidoo92e62c52018-10-03 14:02:54 -04001038 for _, handler := range handlers {
Girish Kumarf56a4682020-03-20 20:07:46 +00001039 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
khenaidoo442e7c72020-03-10 16:13:48 -04001040 if err := handler(ctx, current, previous); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001041 logger.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001042 return err
1043 }
1044 }
khenaidoob9203542018-09-17 22:56:37 -04001045 return nil
1046}
1047
npujar467fe752020-01-16 20:17:45 +05301048func (dMgr *DeviceManager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001049 logger.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301050 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1051 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001052 }
npujar1d86a522019-11-14 17:11:16 +05301053 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001054}
1055
npujar1d86a522019-11-14 17:11:16 +05301056// PacketIn receives packet from adapter
npujar467fe752020-01-16 20:17:45 +05301057func (dMgr *DeviceManager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001058 logger.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001059 // Get the logical device Id based on the deviceId
1060 var device *voltha.Device
1061 var err error
npujar467fe752020-01-16 20:17:45 +05301062 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001063 logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001064 return err
1065 }
khenaidoo43c82122018-11-22 18:38:28 -05001066 if !device.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +00001067 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301068 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001069 }
1070
npujar467fe752020-01-16 20:17:45 +05301071 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001072 return err
1073 }
1074 return nil
1075}
1076
npujar467fe752020-01-16 20:17:45 +05301077func (dMgr *DeviceManager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001078 logger.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301079 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1080 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001081 }
1082 return status.Errorf(codes.NotFound, "%s", device.Id)
1083}
1084
npujar1d86a522019-11-14 17:11:16 +05301085// CreateLogicalDevice creates logical device in core
khenaidoo442e7c72020-03-10 16:13:48 -04001086func (dMgr *DeviceManager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001087 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001088 // Verify whether the logical device has already been created
1089 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001090 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001091 return nil
1092 }
khenaidoob9203542018-09-17 22:56:37 -04001093 var err error
npujar467fe752020-01-16 20:17:45 +05301094 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001095 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001096 return err
1097 }
khenaidoob9203542018-09-17 22:56:37 -04001098 return nil
1099}
1100
npujar1d86a522019-11-14 17:11:16 +05301101// DeleteLogicalDevice deletes logical device from core
khenaidoo442e7c72020-03-10 16:13:48 -04001102func (dMgr *DeviceManager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001103 logger.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001104 var err error
npujar467fe752020-01-16 20:17:45 +05301105 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001106 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001107 return err
1108 }
1109 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301110 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301111 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001112 return nil
1113}
1114
npujar1d86a522019-11-14 17:11:16 +05301115// DeleteLogicalPort removes the logical port associated with a device
npujar467fe752020-01-16 20:17:45 +05301116func (dMgr *DeviceManager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001117 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001118 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001119 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301120 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301121 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001122 logger.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001123 return err
1124 }
npujar467fe752020-01-16 20:17:45 +05301125 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001126 logger.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001127 return err
1128 }
khenaidoo92e62c52018-10-03 14:02:54 -04001129 return nil
1130}
1131
npujar1d86a522019-11-14 17:11:16 +05301132// DeleteLogicalPorts removes the logical ports associated with that deviceId
khenaidoo442e7c72020-03-10 16:13:48 -04001133func (dMgr *DeviceManager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001134 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001135 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001136 // Just log the error. The logical device or port may already have been deleted before this callback is invoked.
Girish Kumarf56a4682020-03-20 20:07:46 +00001137 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001138 }
1139 return nil
1140}
1141
npujar467fe752020-01-16 20:17:45 +05301142func (dMgr *DeviceManager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001143 // Sanity check
1144 if childDevice.Root {
1145 // childDevice is the parent device
1146 return childDevice
1147 }
npujar467fe752020-01-16 20:17:45 +05301148 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001149 return parentDevice
1150}
1151
khenaidoo0a822f92019-05-08 15:15:57 -04001152//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1153//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar467fe752020-01-16 20:17:45 +05301154func (dMgr *DeviceManager) childDevicesLost(ctx context.Context, parentDeviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001155 logger.Debug("childDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001156 var err error
1157 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301158 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001159 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001160 return err
1161 }
khenaidoo442e7c72020-03-10 16:13:48 -04001162 return dMgr.DisableAllChildDevices(ctx, parentDevice, nil)
khenaidoo0a822f92019-05-08 15:15:57 -04001163}
1164
1165//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1166// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar467fe752020-01-16 20:17:45 +05301167func (dMgr *DeviceManager) childDevicesDetected(ctx context.Context, parentDeviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001168 logger.Debug("childDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001169 var err error
1170 var parentDevice *voltha.Device
1171 var childDeviceIds []string
1172
npujar467fe752020-01-16 20:17:45 +05301173 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001174 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001175 return err
1176 }
1177
1178 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1179 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1180 }
1181 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001182 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001183 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001184 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301185 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301186 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001187 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301188 go func() {
npujar467fe752020-01-16 20:17:45 +05301189 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301190 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001191 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301192 }
1193 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001194 } else {
npujar1d86a522019-11-14 17:11:16 +05301195 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Girish Kumarf56a4682020-03-20 20:07:46 +00001196 logger.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001197 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001198 }
1199 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001200 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001201 return err
1202 }
1203 return nil
1204}
1205
khenaidoo4d4802d2018-10-04 21:59:49 -04001206/*
1207All the functions below are callback functions where they are invoked with the latest and previous data. We can
1208therefore use the data as is without trying to get the latest from the model.
1209*/
1210
khenaidoo0a822f92019-05-08 15:15:57 -04001211//DisableAllChildDevices is invoked as a callback when the parent device is disabled
khenaidoo442e7c72020-03-10 16:13:48 -04001212func (dMgr *DeviceManager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device, parentPrevDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001213 logger.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001214 var childDeviceIds []string
1215 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001216 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1217 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001218 }
1219 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001220 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001221 }
npujar1d86a522019-11-14 17:11:16 +05301222 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301223 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1224 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001225 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001226 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001227 }
1228 }
1229 }
1230 return nil
1231}
1232
khenaidoo0a822f92019-05-08 15:15:57 -04001233//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
khenaidoo442e7c72020-03-10 16:13:48 -04001234func (dMgr *DeviceManager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device, parentPrevDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001235 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001236 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001237 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001238 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1239 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001240 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001241 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001242 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001243 }
npujar1d86a522019-11-14 17:11:16 +05301244 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301245 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1246 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001247 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001248 }
khenaidoo49085352020-01-13 19:15:43 -05001249 // No further action is required here. The deleteDevice will change the device state where the resulting
1250 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001251 }
1252 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001253 return nil
1254}
1255
Hardik Windlassc704def2020-02-26 18:23:19 +00001256//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
khenaidoo442e7c72020-03-10 16:13:48 -04001257func (dMgr *DeviceManager) DeleteAllUNILogicalPorts(ctx context.Context, curr *voltha.Device, prev *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001258 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": curr.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001259 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, curr); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001260 // Just log the error and let the remaining pipeline proceed - ports may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001261 logger.Warnw("delete-all-uni-logical-ports-failed", log.Fields{"parent-device-id": curr.Id, "error": err})
Hardik Windlassc704def2020-02-26 18:23:19 +00001262 }
1263 return nil
1264}
1265
Girish Gowdra408cd962020-03-11 14:31:31 -07001266//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
1267func (dMgr *DeviceManager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device, prev *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001268 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001269 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001270 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001271 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001272 }
1273 return nil
1274}
1275
1276//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
1277func (dMgr *DeviceManager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device, prev *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001278 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001279 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1280 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001281 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001282 return err
1283 }
1284 return nil
1285 }
1286 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1287}
1288
khenaidoo4d4802d2018-10-04 21:59:49 -04001289//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1290func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001291 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001292 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001293 if parentDevice != nil {
1294 for _, port := range parentDevice.Ports {
1295 for _, peer := range port.Peers {
1296 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1297 }
khenaidoo92e62c52018-10-03 14:02:54 -04001298 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001299 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001300 }
1301 return childDeviceIds, nil
1302}
1303
khenaidoo297cd252019-02-07 22:10:23 -05001304//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar467fe752020-01-16 20:17:45 +05301305func (dMgr *DeviceManager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001306 logger.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301307 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001308 childDevices := make([]*voltha.Device, 0)
1309 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301310 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301311 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001312 childDevices = append(childDevices, d)
1313 }
1314 }
1315 }
1316 return &voltha.Devices{Items: childDevices}, nil
1317 }
npujar1d86a522019-11-14 17:11:16 +05301318 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001319}
1320
npujar1d86a522019-11-14 17:11:16 +05301321// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
khenaidoo442e7c72020-03-10 16:13:48 -04001322func (dMgr *DeviceManager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001323 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301324 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001325 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001326 return err
1327 }
1328 return nil
1329}
1330
khenaidoof5a5bfa2019-01-23 22:20:29 -05001331func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001332 logger.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001333 var res interface{}
1334 var err error
npujar467fe752020-01-16 20:17:45 +05301335 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001336 if res, err = agent.downloadImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001337 logger.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001338 res = err
1339 }
1340 } else {
1341 res = status.Errorf(codes.NotFound, "%s", img.Id)
1342 }
1343 sendResponse(ctx, ch, res)
1344}
1345
1346func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001347 logger.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001348 var res interface{}
1349 var err error
npujar467fe752020-01-16 20:17:45 +05301350 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001351 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001352 logger.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001353 res = err
1354 }
1355 } else {
1356 res = status.Errorf(codes.NotFound, "%s", img.Id)
1357 }
1358 sendResponse(ctx, ch, res)
1359}
1360
1361func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001362 logger.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001363 var res interface{}
1364 var err error
npujar467fe752020-01-16 20:17:45 +05301365 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001366 if res, err = agent.activateImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001367 logger.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001368 res = err
1369 }
1370 } else {
1371 res = status.Errorf(codes.NotFound, "%s", img.Id)
1372 }
1373 sendResponse(ctx, ch, res)
1374}
1375
1376func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001377 logger.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001378 var res interface{}
1379 var err error
npujar467fe752020-01-16 20:17:45 +05301380 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001381 if res, err = agent.revertImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001382 logger.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001383 res = err
1384 }
1385 } else {
1386 res = status.Errorf(codes.NotFound, "%s", img.Id)
1387 }
1388 sendResponse(ctx, ch, res)
1389}
1390
1391func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001392 logger.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001393 var res interface{}
1394 var err error
npujar467fe752020-01-16 20:17:45 +05301395 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001396 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001397 logger.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001398 res = err
1399 }
1400 } else {
1401 res = status.Errorf(codes.NotFound, "%s", img.Id)
1402 }
1403 sendResponse(ctx, ch, res)
1404}
1405
npujar467fe752020-01-16 20:17:45 +05301406func (dMgr *DeviceManager) updateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001407 logger.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301408 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1409 if err := agent.updateImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001410 logger.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001411 return err
1412 }
1413 } else {
1414 return status.Errorf(codes.NotFound, "%s", img.Id)
1415 }
1416 return nil
1417}
1418
1419func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001420 logger.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301421 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001422 return agent.getImageDownload(ctx, img)
1423 }
1424 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1425}
1426
npujar1d86a522019-11-14 17:11:16 +05301427func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001428 logger.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301429 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301430 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001431 }
npujar1d86a522019-11-14 17:11:16 +05301432 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001433}
1434
khenaidoo442e7c72020-03-10 16:13:48 -04001435func (dMgr *DeviceManager) NotifyInvalidTransition(ctx context.Context, cDevice *voltha.Device, pDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001436 logger.Errorw("NotifyInvalidTransition", log.Fields{
khenaidoo442e7c72020-03-10 16:13:48 -04001437 "device": cDevice.Id,
1438 "prev-admin-state": pDevice.AdminState,
1439 "prev-oper-state": pDevice.OperStatus,
1440 "prev-conn-state": pDevice.ConnectStatus,
1441 "curr-admin-state": cDevice.AdminState,
1442 "curr-oper-state": cDevice.OperStatus,
1443 "curr-conn-state": cDevice.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001444 })
khenaidoo0a822f92019-05-08 15:15:57 -04001445 //TODO: notify over kafka?
1446 return nil
1447}
1448
khenaidoob9203542018-09-17 22:56:37 -04001449func funcName(f interface{}) string {
1450 p := reflect.ValueOf(f).Pointer()
1451 rf := runtime.FuncForPC(p)
1452 return rf.Name()
1453}
1454
npujar1d86a522019-11-14 17:11:16 +05301455// UpdateDeviceAttribute updates value of particular device attribute
npujar467fe752020-01-16 20:17:45 +05301456func (dMgr *DeviceManager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301457 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
npujar467fe752020-01-16 20:17:45 +05301458 agent.(*DeviceAgent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001459 }
1460}
1461
npujar1d86a522019-11-14 17:11:16 +05301462// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +05301463func (dMgr *DeviceManager) GetParentDeviceID(ctx context.Context, deviceID string) string {
1464 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001465 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001466 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001467 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001468 return ""
khenaidoob9203542018-09-17 22:56:37 -04001469}
serkant.uluderya334479d2019-04-10 08:26:15 -07001470
1471func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001472 logger.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
serkant.uluderya334479d2019-04-10 08:26:15 -07001473 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1474 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1475 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301476 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001477 res = agent.simulateAlarm(ctx, simulatereq)
Girish Kumarf56a4682020-03-20 20:07:46 +00001478 logger.Debugw("simulateAlarm-result", log.Fields{"result": res})
serkant.uluderya334479d2019-04-10 08:26:15 -07001479 }
1480 //TODO CLI always get successful response
1481 sendResponse(ctx, ch, res)
1482}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001483
npujar467fe752020-01-16 20:17:45 +05301484func (dMgr *DeviceManager) updateDeviceReason(ctx context.Context, deviceID string, reason string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001485 logger.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301486 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1487 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001488 }
npujar1d86a522019-11-14 17:11:16 +05301489 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001490}
kesavandbc2d1622020-01-21 00:42:01 -05001491
1492func (dMgr *DeviceManager) enablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001493 logger.Debugw("enablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001494 var res interface{}
1495 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1496 res = agent.enablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001497 logger.Debugw("enablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001498 } else {
1499 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1500 }
1501
1502 sendResponse(ctx, ch, res)
1503}
1504
1505func (dMgr *DeviceManager) disablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001506 logger.Debugw("disablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001507 var res interface{}
1508 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1509 res = agent.disablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001510 logger.Debugw("disablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001511 } else {
1512 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1513 }
1514
1515 sendResponse(ctx, ch, res)
1516}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001517
khenaidoo442e7c72020-03-10 16:13:48 -04001518// childDeviceLost calls parent adapter to delete child device and all its references
1519func (dMgr *DeviceManager) ChildDeviceLost(ctx context.Context, curr *voltha.Device, prev *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001520 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001521 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001522 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1523 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001524 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001525 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001526 }
khenaidooe132f522020-03-20 15:23:15 -04001527 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1528 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001529}
onkarkundargi87285252020-01-27 11:34:52 +05301530
1531func (dMgr *DeviceManager) startOmciTest(ctx context.Context, omcitestrequest *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001532 logger.Debugw("Omci_test_Request", log.Fields{"device-id": omcitestrequest.Id, "uuid": omcitestrequest.Uuid})
onkarkundargi87285252020-01-27 11:34:52 +05301533 if agent := dMgr.getDeviceAgent(ctx, omcitestrequest.Id); agent != nil {
1534 res, err := agent.startOmciTest(ctx, omcitestrequest)
1535 if err != nil {
1536 return nil, err
1537 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001538 logger.Debugw("Omci_test_Response_result-device-magnager", log.Fields{"result": res})
onkarkundargi87285252020-01-27 11:34:52 +05301539 return res, nil
1540 }
1541 return nil, status.Errorf(codes.NotFound, "%s", omcitestrequest.Id)
1542}