blob: 8f9847b5126aa482cca0cf2a0861147a71c252fb [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
npujar1d86a522019-11-14 17:11:16 +053016
khenaidoob9203542018-09-17 22:56:37 -040017package core
18
19import (
20 "context"
21 "errors"
David Bainbridged1afd662020-03-26 18:27:41 -070022 "reflect"
23 "runtime"
24 "sync"
25 "time"
26
sbarbari17d7e222019-11-05 10:02:29 -050027 "github.com/opencord/voltha-go/db/model"
khenaidoo3d3b8c22019-05-22 18:10:39 -040028 "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080029 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
30 "github.com/opencord/voltha-lib-go/v3/pkg/log"
31 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
32 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
33 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
34 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040035 "google.golang.org/grpc/codes"
36 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040037)
38
npujar1d86a522019-11-14 17:11:16 +053039// DeviceManager represent device manager attributes
khenaidoob9203542018-09-17 22:56:37 -040040type DeviceManager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040041 deviceAgents sync.Map
42 rootDevices map[string]bool
43 lockRootDeviceMap sync.RWMutex
44 core *Core
45 adapterProxy *AdapterProxy
46 adapterMgr *AdapterManager
47 logicalDeviceMgr *LogicalDeviceManager
npujar467fe752020-01-16 20:17:45 +053048 kafkaICProxy kafka.InterContainerProxy
khenaidoo4c9e5592019-09-09 16:20:41 -040049 stateTransitions *TransitionMap
50 clusterDataProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053051 coreInstanceID string
khenaidoo4c9e5592019-09-09 16:20:41 -040052 exitChannel chan int
khenaidoo442e7c72020-03-10 16:13:48 -040053 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040054 devicesLoadingLock sync.RWMutex
55 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040056}
57
Richard Jankowski199fd862019-03-18 14:49:51 -040058func newDeviceManager(core *Core) *DeviceManager {
Matteo Scandolod525ae32020-04-02 17:27:29 -070059
60 endpointManager := kafka.NewEndpointManager(&core.backend)
61
khenaidoob9203542018-09-17 22:56:37 -040062 var deviceMgr DeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040063 deviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040064 deviceMgr.exitChannel = make(chan int, 1)
khenaidoo2c6a0992019-04-29 13:46:56 -040065 deviceMgr.rootDevices = make(map[string]bool)
Richard Jankowski199fd862019-03-18 14:49:51 -040066 deviceMgr.kafkaICProxy = core.kmp
Matteo Scandolod525ae32020-04-02 17:27:29 -070067 deviceMgr.adapterProxy = NewAdapterProxy(core.kmp, core.config.CorePairTopic, endpointManager)
npujar1d86a522019-11-14 17:11:16 +053068 deviceMgr.coreInstanceID = core.instanceID
Richard Jankowski199fd862019-03-18 14:49:51 -040069 deviceMgr.clusterDataProxy = core.clusterDataProxy
70 deviceMgr.adapterMgr = core.adapterMgr
khenaidoo2c6a0992019-04-29 13:46:56 -040071 deviceMgr.lockRootDeviceMap = sync.RWMutex{}
khenaidoo442e7c72020-03-10 16:13:48 -040072 deviceMgr.defaultTimeout = time.Duration(core.config.DefaultCoreTimeout) * time.Millisecond
khenaidoo4c9e5592019-09-09 16:20:41 -040073 deviceMgr.devicesLoadingLock = sync.RWMutex{}
74 deviceMgr.deviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040075 return &deviceMgr
76}
77
khenaidoo4d4802d2018-10-04 21:59:49 -040078func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
Girish Kumarf56a4682020-03-20 20:07:46 +000079 logger.Info("starting-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040080 dMgr.logicalDeviceMgr = logicalDeviceMgr
81 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070082 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
Girish Kumarf56a4682020-03-20 20:07:46 +000083 logger.Info("device-manager-started")
khenaidoob9203542018-09-17 22:56:37 -040084}
85
khenaidoo4d4802d2018-10-04 21:59:49 -040086func (dMgr *DeviceManager) stop(ctx context.Context) {
Girish Kumarf56a4682020-03-20 20:07:46 +000087 logger.Info("stopping-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040088 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070089 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
Girish Kumarf56a4682020-03-20 20:07:46 +000090 logger.Info("device-manager-stopped")
khenaidoob9203542018-09-17 22:56:37 -040091}
92
93func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
94 if ctx.Err() == nil {
95 // Returned response only of the ctx has not been cancelled/timeout/etc
96 // Channel is automatically closed when a context is Done
97 ch <- result
Girish Kumarf56a4682020-03-20 20:07:46 +000098 logger.Debugw("sendResponse", log.Fields{"result": result})
khenaidoob9203542018-09-17 22:56:37 -040099 } else {
100 // Should the transaction be reverted back?
Girish Kumarf56a4682020-03-20 20:07:46 +0000101 logger.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
khenaidoob9203542018-09-17 22:56:37 -0400102 }
103}
104
105func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530106 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
107 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -0400108 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400109 dMgr.lockRootDeviceMap.Lock()
110 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530111 dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400112
khenaidoob9203542018-09-17 22:56:37 -0400113}
114
khenaidoo4c9e5592019-09-09 16:20:41 -0400115func (dMgr *DeviceManager) deleteDeviceAgentFromMap(agent *DeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +0530116 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400117 dMgr.lockRootDeviceMap.Lock()
118 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530119 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400120}
121
khenaidoo297cd252019-02-07 22:10:23 -0500122// getDeviceAgent returns the agent managing the device. If the device is not in memory, it will loads it, if it exists
npujar467fe752020-01-16 20:17:45 +0530123func (dMgr *DeviceManager) getDeviceAgent(ctx context.Context, deviceID string) *DeviceAgent {
npujar1d86a522019-11-14 17:11:16 +0530124 agent, ok := dMgr.deviceAgents.Load(deviceID)
125 if ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400126 return agent.(*DeviceAgent)
khenaidoob9203542018-09-17 22:56:37 -0400127 }
khenaidoo442e7c72020-03-10 16:13:48 -0400128 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530129 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530130 if err == nil {
131 agent, ok = dMgr.deviceAgents.Load(deviceID)
132 if !ok {
133 return nil
134 }
npujar1d86a522019-11-14 17:11:16 +0530135 return agent.(*DeviceAgent)
136 }
137 //TODO: Change the return params to return an error as well
Girish Kumarf56a4682020-03-20 20:07:46 +0000138 logger.Errorw("loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400139 return nil
140}
141
khenaidoo297cd252019-02-07 22:10:23 -0500142// listDeviceIdsFromMap returns the list of device IDs that are in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500143func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500144 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400145
146 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
147 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
148 return true
149 })
150
khenaidoo7ccedd52018-12-14 16:48:54 -0500151 return result
152}
153
khenaidoob9203542018-09-17 22:56:37 -0400154func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
npujar467fe752020-01-16 20:17:45 +0530155 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530156 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000157 logger.Errorf("Failed to fetch parent device info")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530158 sendResponse(ctx, ch, err)
159 return
160 }
161 if deviceExist {
Girish Kumarf56a4682020-03-20 20:07:46 +0000162 logger.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530163 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
164 return
165 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000166 logger.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400167
khenaidoo5e677ae2019-02-28 17:26:29 -0500168 // Ensure this device is set as root
169 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400170 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -0400171 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530172 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800173 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000174 logger.Errorw("Fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530175 sendResponse(ctx, ch, err)
Scott Baker80678602019-11-14 16:57:36 -0800176 return
177 }
khenaidoo442e7c72020-03-10 16:13:48 -0400178 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -0400179
Scott Baker80678602019-11-14 16:57:36 -0800180 sendResponse(ctx, ch, device)
khenaidoob9203542018-09-17 22:56:37 -0400181}
182
183func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000184 logger.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400185 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530186 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400187 res = agent.enableDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000188 logger.Debugw("EnableDevice-result", log.Fields{"result": res})
Hardik Windlassb9cfcb12020-02-03 15:59:46 +0000189 } else {
190 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400191 }
khenaidoob9203542018-09-17 22:56:37 -0400192 sendResponse(ctx, ch, res)
193}
194
khenaidoo92e62c52018-10-03 14:02:54 -0400195func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000196 logger.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400197 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530198 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400199 res = agent.disableDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000200 logger.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400201 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400202 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400203 }
khenaidoo92e62c52018-10-03 14:02:54 -0400204
205 sendResponse(ctx, ch, res)
206}
207
khenaidoo4d4802d2018-10-04 21:59:49 -0400208func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000209 logger.Debugw("rebootDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400210 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530211 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400212 res = agent.rebootDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000213 logger.Debugw("rebootDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400214 } else {
215 res = status.Errorf(codes.NotFound, "%s", id.Id)
216 }
217 sendResponse(ctx, ch, res)
218}
219
220func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000221 logger.Debugw("deleteDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400222 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530223 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400224 res = agent.deleteDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000225 logger.Debugw("deleteDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400226 } else {
227 res = status.Errorf(codes.NotFound, "%s", id.Id)
228 }
229 sendResponse(ctx, ch, res)
230}
231
khenaidoo6d62c002019-05-15 21:57:03 -0400232// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
233// This function is called only in the Core that does not own this device. In the Core that owns this device then a
234// deletion deletion also includes removal of any reference of this device.
npujar467fe752020-01-16 20:17:45 +0530235func (dMgr *DeviceManager) stopManagingDevice(ctx context.Context, id string) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000236 logger.Infow("stopManagingDevice", log.Fields{"deviceId": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400237 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530238 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400239 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700240 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400241 }
npujar467fe752020-01-16 20:17:45 +0530242 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400243 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000244 logger.Warnw("unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400245 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400246 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400247 }
248 }
249}
250
npujar1d86a522019-11-14 17:11:16 +0530251// RunPostDeviceDelete removes any reference of this device
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500252func (dMgr *DeviceManager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000253 logger.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530254 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400255 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400256}
257
khenaidoo297cd252019-02-07 22:10:23 -0500258// GetDevice will returns a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530259func (dMgr *DeviceManager) GetDevice(ctx context.Context, id string) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000260 logger.Debugw("GetDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530261 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400262 return agent.getDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400263 }
264 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400265}
266
npujar1d86a522019-11-14 17:11:16 +0530267// GetChildDevice will return a device, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +0530268func (dMgr *DeviceManager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000269 logger.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
npujar1d86a522019-11-14 17:11:16 +0530270 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500271
272 var parentDevice *voltha.Device
273 var err error
npujar467fe752020-01-16 20:17:45 +0530274 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500275 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
276 }
277 var childDeviceIds []string
278 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
279 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
280 }
281 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000282 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530283 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500284 }
285
286 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530287 for _, childDeviceID := range childDeviceIds {
288 var found bool
npujar467fe752020-01-16 20:17:45 +0530289 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500290
npujar1d86a522019-11-14 17:11:16 +0530291 foundOnuID := false
292 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500293 if searchDevice.ParentPortNo == uint32(parentPortNo) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000294 logger.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530295 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500296 }
297 }
298
299 foundSerialNumber := false
300 if searchDevice.SerialNumber == serialNumber {
Girish Kumarf56a4682020-03-20 20:07:46 +0000301 logger.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500302 foundSerialNumber = true
303 }
304
305 // if both onuId and serialNumber are provided both must be true for the device to be found
306 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530307 if onuID > 0 && serialNumber != "" {
308 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500309 } else {
npujar1d86a522019-11-14 17:11:16 +0530310 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500311 }
312
npujar1d86a522019-11-14 17:11:16 +0530313 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500314 foundChildDevice = searchDevice
315 break
316 }
317 }
318 }
319
320 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000321 logger.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500322 return foundChildDevice, nil
323 }
324
Girish Kumarf56a4682020-03-20 20:07:46 +0000325 logger.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530326 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
327 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500328}
329
npujar1d86a522019-11-14 17:11:16 +0530330// GetChildDeviceWithProxyAddress will return a device based on proxy address
npujar467fe752020-01-16 20:17:45 +0530331func (dMgr *DeviceManager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000332 logger.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500333
334 var parentDevice *voltha.Device
335 var err error
npujar467fe752020-01-16 20:17:45 +0530336 if parentDevice, err = dMgr.GetDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500337 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
338 }
339 var childDeviceIds []string
340 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
341 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
342 }
343 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000344 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500345 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
346 }
347
348 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530349 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530350 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500351 if searchDevice.ProxyAddress == proxyAddress {
352 foundChildDevice = searchDevice
353 break
354 }
355 }
356 }
357
358 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000359 logger.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500360 return foundChildDevice, nil
361 }
362
Girish Kumarf56a4682020-03-20 20:07:46 +0000363 logger.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500364 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
365}
366
npujar1d86a522019-11-14 17:11:16 +0530367// IsDeviceInCache returns true if device is found in the map
khenaidoo297cd252019-02-07 22:10:23 -0500368func (dMgr *DeviceManager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400369 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500370 return exist
371}
372
npujar1d86a522019-11-14 17:11:16 +0530373// IsRootDevice returns true if root device is found in the map
khenaidoo19d7b632018-10-30 10:49:50 -0400374func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400375 dMgr.lockRootDeviceMap.RLock()
376 defer dMgr.lockRootDeviceMap.RUnlock()
377 if exist := dMgr.rootDevices[id]; exist {
378 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400379 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400380 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400381}
382
Stephane Barbarieaa467942019-02-06 14:09:44 -0500383// ListDevices retrieves the latest devices from the data model
npujar467fe752020-01-16 20:17:45 +0530384func (dMgr *DeviceManager) ListDevices(ctx context.Context) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000385 logger.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400386 result := &voltha.Devices{}
Kent Hagerman4f355f52020-03-30 16:01:33 -0400387
388 var devices []*voltha.Device
389 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000390 logger.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530391 return nil, err
392 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400393
394 for _, device := range devices {
395 // If device is not in memory then set it up
396 if !dMgr.IsDeviceInCache(device.Id) {
397 logger.Debugw("loading-device-from-Model", log.Fields{"id": device.Id})
398 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
399 if _, err := agent.start(ctx, nil); err != nil {
400 logger.Warnw("failure-starting-agent", log.Fields{"deviceId": device.Id})
401 } else {
402 dMgr.addDeviceAgentToMap(agent)
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500403 }
khenaidoob9203542018-09-17 22:56:37 -0400404 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400405 result.Items = append(result.Items, device)
khenaidoob9203542018-09-17 22:56:37 -0400406 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000407 logger.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400408 return result, nil
409}
410
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530411//isParentDeviceExist checks whether device is already preprovisioned.
npujar467fe752020-01-16 20:17:45 +0530412func (dMgr *DeviceManager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530413 hostPort := newDevice.GetHostAndPort()
Kent Hagerman4f355f52020-03-30 16:01:33 -0400414 var devices []*voltha.Device
415 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000416 logger.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530417 return false, err
418 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400419 for _, device := range devices {
420 if !device.Root {
421 continue
422 }
423 if hostPort != "" && hostPort == device.GetHostAndPort() && device.AdminState != voltha.AdminState_DELETED {
424 return true, nil
425 }
426 if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress && device.AdminState != voltha.AdminState_DELETED {
427 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530428 }
429 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530430 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530431}
432
khenaidoo6d62c002019-05-15 21:57:03 -0400433//getDeviceFromModelretrieves the device data from the model.
npujar467fe752020-01-16 20:17:45 +0530434func (dMgr *DeviceManager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400435 device := &voltha.Device{}
436 if have, err := dMgr.clusterDataProxy.Get(ctx, "devices/"+deviceID, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000437 logger.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530438 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400439 } else if !have {
440 return nil, status.Error(codes.NotFound, deviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530441 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400442
443 return device, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400444}
445
npujar1d86a522019-11-14 17:11:16 +0530446// loadDevice loads the deviceID in memory, if not present
npujar467fe752020-01-16 20:17:45 +0530447func (dMgr *DeviceManager) loadDevice(ctx context.Context, deviceID string) (*DeviceAgent, error) {
npujar1d86a522019-11-14 17:11:16 +0530448 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500449 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
450 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400451 var err error
452 var device *voltha.Device
453 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530454 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
455 if !dMgr.IsDeviceInCache(deviceID) {
456 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400457 dMgr.devicesLoadingLock.Unlock()
458 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530459 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000460 logger.Debugw("loading-device", log.Fields{"deviceId": deviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400461 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530462 if _, err = agent.start(ctx, nil); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000463 logger.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400464 } else {
465 dMgr.addDeviceAgentToMap(agent)
466 }
467 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000468 logger.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400469 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400470 // announce completion of task to any number of waiting channels
471 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530472 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400473 for _, ch := range v {
474 close(ch)
475 }
npujar1d86a522019-11-14 17:11:16 +0530476 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400477 }
478 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400479 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400480 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500481 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400482 } else {
483 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530484 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400485 dMgr.devicesLoadingLock.Unlock()
486 // Wait for the channel to be closed, implying the process loading this device is done.
487 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500488 }
npujar1d86a522019-11-14 17:11:16 +0530489 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400490 return agent.(*DeviceAgent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500491 }
npujar1d86a522019-11-14 17:11:16 +0530492 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500493}
494
495// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
npujar467fe752020-01-16 20:17:45 +0530496func (dMgr *DeviceManager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000497 logger.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500498 if device.Root {
499 // Scenario A
500 if device.ParentId != "" {
501 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530502 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000503 logger.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500504 }
505 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000506 logger.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500507 }
508 // Load all child devices, if needed
509 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530510 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530511 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000512 logger.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500513 return err
514 }
515 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000516 logger.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500517 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000518 logger.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500519 }
520 }
521 return nil
522}
523
524// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
525// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
526// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
527// and the proceed with the request.
npujar467fe752020-01-16 20:17:45 +0530528func (dMgr *DeviceManager) load(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000529 logger.Debug("load...")
khenaidoo297cd252019-02-07 22:10:23 -0500530 // First load the device - this may fail in case the device was deleted intentionally by the other core
531 var dAgent *DeviceAgent
532 var err error
npujar467fe752020-01-16 20:17:45 +0530533 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500534 return err
535 }
536 // Get the loaded device details
khenaidoo442e7c72020-03-10 16:13:48 -0400537 device, err := dAgent.getDevice(ctx)
538 if err != nil {
539 return err
540 }
khenaidoo297cd252019-02-07 22:10:23 -0500541
542 // If the device is in Pre-provisioning or deleted state stop here
543 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
544 return nil
545 }
546
547 // Now we face two scenarios
548 if device.Root {
549 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530550 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000551 logger.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500552 return err
553 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000554 logger.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500555 } else {
556 // Scenario B - use the parentId of that device (root device) to trigger the loading
557 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530558 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500559 }
560 }
561 return nil
562}
563
khenaidoo7ccedd52018-12-14 16:48:54 -0500564// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
565func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000566 logger.Debug("ListDeviceIDs")
khenaidoo7ccedd52018-12-14 16:48:54 -0500567 // Report only device IDs that are in the device agent map
568 return dMgr.listDeviceIdsFromMap(), nil
569}
570
khenaidoo4c9e5592019-09-09 16:20:41 -0400571//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
572//trigger loading the devices along with their children and parent in memory
khenaidoo7ccedd52018-12-14 16:48:54 -0500573func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000574 logger.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500575 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400576 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500577 toReconcile := len(ids.Items)
578 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400579 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500580 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530581 if err = dMgr.load(ctx, id.Id); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000582 logger.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400583 } else {
npujar1d86a522019-11-14 17:11:16 +0530584 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500585 }
586 }
587 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400588 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500589 }
590 } else {
591 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
592 }
593 sendResponse(ctx, ch, res)
594}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500595
khenaidooba6b6c42019-08-02 09:11:56 -0400596// isOkToReconcile validates whether a device is in the correct status to be reconciled
597func isOkToReconcile(device *voltha.Device) bool {
598 if device == nil {
599 return false
600 }
601 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
602}
603
604// adapterRestarted is invoked whenever an adapter is restarted
npujar467fe752020-01-16 20:17:45 +0530605func (dMgr *DeviceManager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Matteo Scandolod525ae32020-04-02 17:27:29 -0700606 logger.Debugw("adapter-restarted", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
607 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidooba6b6c42019-08-02 09:11:56 -0400608
609 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700610 if len(dMgr.rootDevices) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000611 logger.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400612 return nil
613 }
614
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500615 responses := make([]utils.Response, 0)
David Bainbridged1afd662020-03-26 18:27:41 -0700616 for rootDeviceID := range dMgr.rootDevices {
npujar467fe752020-01-16 20:17:45 +0530617 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700618 isDeviceOwnedByService, err := dMgr.adapterProxy.endpointManager.IsDeviceOwnedByService(rootDeviceID, adapter.Type, adapter.CurrentReplica)
619 if err != nil {
620 logger.Warnw("is-device-owned-by-service", log.Fields{"error": err, "root-device-id": rootDeviceID, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
621 continue
622 }
623 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400624 if isOkToReconcile(rootDevice) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000625 logger.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530626 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400627 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000628 logger.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400629 }
630 } else { // Should we be reconciling the root's children instead?
631 childManagedByAdapter:
632 for _, port := range rootDevice.Ports {
633 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530634 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700635 isDeviceOwnedByService, err := dMgr.adapterProxy.endpointManager.IsDeviceOwnedByService(childDevice.Id, adapter.Type, adapter.CurrentReplica)
636 if err != nil {
637 logger.Warnw("is-device-owned-by-service", log.Fields{"error": err, "child-device-id": childDevice.Id, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
638 }
639 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400640 if isOkToReconcile(childDevice) {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700641 logger.Debugw("reconciling-child-device", log.Fields{"child-device-id": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530642 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400643 } else {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700644 logger.Debugw("not-reconciling-child-device", log.Fields{"child-device-id": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400645 }
646 } else {
647 // All child devices under a parent device are typically managed by the same adapter type.
648 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
649 break childManagedByAdapter
650 }
651 }
652 }
653 }
654 }
655 }
656 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500657 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400658 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500659 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400660 return status.Errorf(codes.Aborted, "errors-%s", res)
661 }
662 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000663 logger.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400664 }
665 return nil
666}
667
npujar467fe752020-01-16 20:17:45 +0530668func (dMgr *DeviceManager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400669 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
670 // 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 +0530671 // 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 -0400672 // the adapter_proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500673 response := utils.NewResponse()
khenaidoo442e7c72020-03-10 16:13:48 -0400674 ch, err := dMgr.adapterProxy.reconcileDevice(ctx, device)
675 if err != nil {
676 response.Error(err)
677 }
678 // Wait for adapter response in its own routine
679 go func() {
680 resp, ok := <-ch
681 if !ok {
682 response.Error(status.Errorf(codes.Aborted, "channel-closed-device: %s", device.Id))
683 } else if resp.Err != nil {
684 response.Error(resp.Err)
khenaidooba6b6c42019-08-02 09:11:56 -0400685 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500686 response.Done()
khenaidoo442e7c72020-03-10 16:13:48 -0400687 }()
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500688 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400689}
690
npujar467fe752020-01-16 20:17:45 +0530691func (dMgr *DeviceManager) reconcileChildDevices(ctx context.Context, parentDeviceID string) error {
692 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500693 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400694 for _, port := range parentDevice.Ports {
695 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530696 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
697 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400698 }
699 }
700 }
701 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500702 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400703 return status.Errorf(codes.Aborted, "errors-%s", res)
704 }
705 }
706 return nil
707}
708
npujar467fe752020-01-16 20:17:45 +0530709func (dMgr *DeviceManager) updateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000710 logger.Debugw("updateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530711 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
712 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400713 }
714 return status.Errorf(codes.NotFound, "%s", device.Id)
715}
716
npujar467fe752020-01-16 20:17:45 +0530717func (dMgr *DeviceManager) addPort(ctx context.Context, deviceID string, port *voltha.Port) error {
718 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530719 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530720 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400721 return err
722 }
723 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530724 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400725 for _, peerPort := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530726 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
727 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000728 logger.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
khenaidoo92e62c52018-10-03 14:02:54 -0400729 return err
730 }
731 }
732 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400733 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
734 // then a logical port will be added to the logical device and the device graph generated. If the port is a
735 // PON port then only the device graph will be generated.
npujar467fe752020-01-16 20:17:45 +0530736 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530737 go func() {
npujar467fe752020-01-16 20:17:45 +0530738 err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port)
npujar1d86a522019-11-14 17:11:16 +0530739 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000740 logger.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530741 }
742 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400743 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000744 logger.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400745 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400746 }
khenaidoo92e62c52018-10-03 14:02:54 -0400747 return nil
khenaidoob9203542018-09-17 22:56:37 -0400748 }
npujar1d86a522019-11-14 17:11:16 +0530749 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400750}
751
npujar467fe752020-01-16 20:17:45 +0530752func (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 +0000753 logger.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530754 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
755 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400756 }
npujar1d86a522019-11-14 17:11:16 +0530757 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400758}
759
npujar467fe752020-01-16 20:17:45 +0530760func (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 +0000761 logger.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530762 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
763 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400764 }
npujar1d86a522019-11-14 17:11:16 +0530765 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400766}
767
npujar467fe752020-01-16 20:17:45 +0530768func (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 +0000769 logger.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530770 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
771 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400772 }
npujar1d86a522019-11-14 17:11:16 +0530773 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400774}
775
khenaidoob3127472019-07-24 21:04:55 -0400776// updatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
777// following a user action
778func (dMgr *DeviceManager) updatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
779 var res interface{}
780 if pmConfigs.Id == "" {
781 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
npujar467fe752020-01-16 20:17:45 +0530782 } else if agent := dMgr.getDeviceAgent(ctx, pmConfigs.Id); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400783 res = agent.updatePmConfigs(ctx, pmConfigs)
784 } else {
785 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
786 }
787 sendResponse(ctx, ch, res)
788}
789
790// initPmConfigs initialize the pm configs as defined by the adapter.
npujar467fe752020-01-16 20:17:45 +0530791func (dMgr *DeviceManager) initPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400792 if pmConfigs.Id == "" {
793 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
794 }
npujar467fe752020-01-16 20:17:45 +0530795 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
796 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400797 }
npujar1d86a522019-11-14 17:11:16 +0530798 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400799}
800
npujar1d86a522019-11-14 17:11:16 +0530801func (dMgr *DeviceManager) listPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
npujar467fe752020-01-16 20:17:45 +0530802 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400803 return agent.listPmConfigs(ctx)
804 }
npujar1d86a522019-11-14 17:11:16 +0530805 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400806}
807
npujar1d86a522019-11-14 17:11:16 +0530808func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000809 logger.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530810 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400811 return agent.getSwitchCapability(ctx)
812 }
npujar1d86a522019-11-14 17:11:16 +0530813 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400814}
815
npujar1d86a522019-11-14 17:11:16 +0530816func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000817 logger.Debugw("getPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530818 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400819 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400820 }
npujar1d86a522019-11-14 17:11:16 +0530821 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400822}
823
npujar1d86a522019-11-14 17:11:16 +0530824func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000825 logger.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530826 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400827 return agent.getPortCapability(ctx, portNo)
828 }
npujar1d86a522019-11-14 17:11:16 +0530829 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400830}
831
npujar467fe752020-01-16 20:17:45 +0530832func (dMgr *DeviceManager) updateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000833 logger.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530834 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
835 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400836 }
npujar1d86a522019-11-14 17:11:16 +0530837 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400838}
839
npujar467fe752020-01-16 20:17:45 +0530840func (dMgr *DeviceManager) updateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000841 logger.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400842 var parentDevice *voltha.Device
843 var err error
npujar467fe752020-01-16 20:17:45 +0530844 if parentDevice, err = dMgr.GetDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400845 return status.Errorf(codes.Aborted, "%s", err.Error())
846 }
847 var childDeviceIds []string
848 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
849 return status.Errorf(codes.Aborted, "%s", err.Error())
850 }
851 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000852 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400853 }
npujar1d86a522019-11-14 17:11:16 +0530854 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530855 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
856 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530857 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400858 }
859 }
860 }
861 return nil
862}
863
npujar467fe752020-01-16 20:17:45 +0530864func (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 +0000865 logger.Debugw("updatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530866 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
867 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000868 logger.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400869 return err
870 }
871 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800872 // Do this for NNI and UNIs only. PON ports are not known by logical device
873 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
874 go func() {
875 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
876 if err != nil {
877 // While we want to handle (catch) and log when
878 // an update to a port was not able to be
879 // propagated to the logical port, we can report
880 // it as a warning and not an error because it
881 // doesn't stop or modify processing.
882 // TODO: VOL-2707
Girish Kumarf56a4682020-03-20 20:07:46 +0000883 logger.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800884 }
885 }()
886 }
khenaidoo442e7c72020-03-10 16:13:48 -0400887 return nil
khenaidoob9203542018-09-17 22:56:37 -0400888 }
npujar1d86a522019-11-14 17:11:16 +0530889 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400890}
891
npujar467fe752020-01-16 20:17:45 +0530892func (dMgr *DeviceManager) deleteAllPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000893 logger.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530894 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
895 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400896 return err
897 }
898 // Notify the logical device manager to remove all logical ports, if needed.
899 // At this stage the device itself may gave been deleted already at a deleteAllPorts
900 // typically is part of a device deletion phase.
npujar467fe752020-01-16 20:17:45 +0530901 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530902 go func() {
npujar467fe752020-01-16 20:17:45 +0530903 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530904 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000905 logger.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530906 }
907 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400908 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000909 logger.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400910 return err
911 }
912 return nil
913 }
npujar1d86a522019-11-14 17:11:16 +0530914 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400915}
916
khenaidoo3ab34882019-05-02 21:33:30 -0400917//updatePortsState updates all ports on the device
npujar467fe752020-01-16 20:17:45 +0530918func (dMgr *DeviceManager) updatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000919 logger.Debugw("updatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400920
npujar467fe752020-01-16 20:17:45 +0530921 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400922 switch state {
923 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500924 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000925 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400926 return err
927 }
928 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500929 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000930 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400931 return err
932 }
933 default:
934 return status.Error(codes.Unimplemented, "state-change-not-implemented")
935 }
936 // Notify the logical device about the state change
npujar467fe752020-01-16 20:17:45 +0530937 device, err := dMgr.GetDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530938 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000939 logger.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400940 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400941 }
kesavandbc2d1622020-01-21 00:42:01 -0500942 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000943 logger.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530944 return err
945 }
946 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400947 }
npujar1d86a522019-11-14 17:11:16 +0530948 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400949}
950
npujar467fe752020-01-16 20:17:45 +0530951func (dMgr *DeviceManager) childDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530952 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000953 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 -0700954
npujar1d86a522019-11-14 17:11:16 +0530955 if deviceType == "" && vendorID != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000956 logger.Debug("device-type-is-nil-fetching-device-type")
Kent Hagerman4f355f52020-03-30 16:01:33 -0400957 var deviceTypes []*voltha.DeviceType
958 if err := dMgr.adapterMgr.clusterDataProxy.List(ctx, "device_types", &deviceTypes); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000959 logger.Errorw("failed-to-get-device-type-info", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530960 return nil, err
961 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400962 OLoop:
963 for _, dType := range deviceTypes {
964 for _, v := range dType.VendorIds {
965 if v == vendorID {
966 deviceType = dType.Adapter
967 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700968 }
969 }
970 }
971 }
972 //if no match found for the vendorid,report adapter with the custom error message
973 if deviceType == "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000974 logger.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +0530975 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700976 }
khenaidoob9203542018-09-17 22:56:37 -0400977
978 // Create the ONU device
979 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400980 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530981 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400982 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530983 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500984 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400985 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400986
khenaidoo442e7c72020-03-10 16:13:48 -0400987 // Get parent device type
988 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
989 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +0530990 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400991 }
khenaidoo442e7c72020-03-10 16:13:48 -0400992 if pAgent.deviceType == "" {
993 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
994 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400995
npujar467fe752020-01-16 20:17:45 +0530996 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000997 logger.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -0700998 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500999 }
1000
khenaidoo442e7c72020-03-10 16:13:48 -04001001 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001002
1003 // Create and start a device agent for that device
khenaidoo2c6a0992019-04-29 13:46:56 -04001004 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -04001005 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001006 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001007 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 -08001008 return nil, err
1009 }
khenaidoo442e7c72020-03-10 16:13:48 -04001010 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001011
1012 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301013 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301014 go func() {
npujar467fe752020-01-16 20:17:45 +05301015 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301016 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001017 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301018 }
1019 }()
khenaidoob9203542018-09-17 22:56:37 -04001020 }
1021
khenaidoo79232702018-12-04 11:00:41 -05001022 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301023 go func() {
1024 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1025 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001026 logger.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301027 }
1028 }()
khenaidoo79232702018-12-04 11:00:41 -05001029
Scott Baker80678602019-11-14 16:57:36 -08001030 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001031}
1032
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001033func (dMgr *DeviceManager) processTransition(ctx context.Context, device *voltha.Device, previousState *DeviceState) error {
1034 // This will be triggered on every state update
1035 logger.Debugw("state-transition", log.Fields{
1036 "device": device.Id,
1037 "prev-admin-state": previousState.Admin,
1038 "prev-oper-state": previousState.Operational,
1039 "prev-conn-state": previousState.Connection,
1040 "curr-admin-state": device.AdminState,
1041 "curr-oper-state": device.OperStatus,
1042 "curr-conn-state": device.ConnectStatus,
1043 })
1044 handlers := dMgr.stateTransitions.GetTransitionHandler(device, previousState)
khenaidoo92e62c52018-10-03 14:02:54 -04001045 if handlers == nil {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001046 logger.Debugw("no-op-transition", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001047 return nil
khenaidoob9203542018-09-17 22:56:37 -04001048 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001049 logger.Debugw("handler-found", log.Fields{"num-expectedHandlers": len(handlers), "isParent": device.Root, "current-data": device, "previous-state": previousState})
khenaidoo92e62c52018-10-03 14:02:54 -04001050 for _, handler := range handlers {
Girish Kumarf56a4682020-03-20 20:07:46 +00001051 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001052 if err := handler(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001053 logger.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001054 return err
1055 }
1056 }
khenaidoob9203542018-09-17 22:56:37 -04001057 return nil
1058}
1059
npujar467fe752020-01-16 20:17:45 +05301060func (dMgr *DeviceManager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001061 logger.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301062 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1063 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001064 }
npujar1d86a522019-11-14 17:11:16 +05301065 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001066}
1067
npujar1d86a522019-11-14 17:11:16 +05301068// PacketIn receives packet from adapter
npujar467fe752020-01-16 20:17:45 +05301069func (dMgr *DeviceManager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001070 logger.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001071 // Get the logical device Id based on the deviceId
1072 var device *voltha.Device
1073 var err error
npujar467fe752020-01-16 20:17:45 +05301074 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001075 logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001076 return err
1077 }
khenaidoo43c82122018-11-22 18:38:28 -05001078 if !device.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +00001079 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301080 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001081 }
1082
npujar467fe752020-01-16 20:17:45 +05301083 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001084 return err
1085 }
1086 return nil
1087}
1088
npujar467fe752020-01-16 20:17:45 +05301089func (dMgr *DeviceManager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001090 logger.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301091 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1092 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001093 }
1094 return status.Errorf(codes.NotFound, "%s", device.Id)
1095}
1096
npujar1d86a522019-11-14 17:11:16 +05301097// CreateLogicalDevice creates logical device in core
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001098func (dMgr *DeviceManager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001099 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001100 // Verify whether the logical device has already been created
1101 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001102 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001103 return nil
1104 }
khenaidoob9203542018-09-17 22:56:37 -04001105 var err error
npujar467fe752020-01-16 20:17:45 +05301106 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001107 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001108 return err
1109 }
khenaidoob9203542018-09-17 22:56:37 -04001110 return nil
1111}
1112
npujar1d86a522019-11-14 17:11:16 +05301113// DeleteLogicalDevice deletes logical device from core
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001114func (dMgr *DeviceManager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001115 logger.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001116 var err error
npujar467fe752020-01-16 20:17:45 +05301117 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001118 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001119 return err
1120 }
1121 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301122 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301123 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001124 return nil
1125}
1126
npujar1d86a522019-11-14 17:11:16 +05301127// DeleteLogicalPort removes the logical port associated with a device
npujar467fe752020-01-16 20:17:45 +05301128func (dMgr *DeviceManager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001129 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001130 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001131 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301132 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301133 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001134 logger.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001135 return err
1136 }
npujar467fe752020-01-16 20:17:45 +05301137 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001138 logger.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001139 return err
1140 }
khenaidoo92e62c52018-10-03 14:02:54 -04001141 return nil
1142}
1143
npujar1d86a522019-11-14 17:11:16 +05301144// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001145func (dMgr *DeviceManager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001146 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001147 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001148 // 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 +00001149 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001150 }
1151 return nil
1152}
1153
npujar467fe752020-01-16 20:17:45 +05301154func (dMgr *DeviceManager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001155 // Sanity check
1156 if childDevice.Root {
1157 // childDevice is the parent device
1158 return childDevice
1159 }
npujar467fe752020-01-16 20:17:45 +05301160 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001161 return parentDevice
1162}
1163
khenaidoo0a822f92019-05-08 15:15:57 -04001164//childDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
1165//cannot manage the child devices. This will trigger the Core to disable all the child devices.
npujar467fe752020-01-16 20:17:45 +05301166func (dMgr *DeviceManager) childDevicesLost(ctx context.Context, parentDeviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001167 logger.Debug("childDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001168 var err error
1169 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301170 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001171 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001172 return err
1173 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001174 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001175}
1176
1177//childDevicesDetected is invoked by an adapter when child devices are found, typically after after a
1178// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
npujar467fe752020-01-16 20:17:45 +05301179func (dMgr *DeviceManager) childDevicesDetected(ctx context.Context, parentDeviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001180 logger.Debug("childDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001181 var err error
1182 var parentDevice *voltha.Device
1183 var childDeviceIds []string
1184
npujar467fe752020-01-16 20:17:45 +05301185 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001186 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001187 return err
1188 }
1189
1190 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1191 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1192 }
1193 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001194 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001195 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001196 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301197 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301198 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001199 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301200 go func() {
npujar467fe752020-01-16 20:17:45 +05301201 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301202 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001203 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301204 }
1205 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001206 } else {
npujar1d86a522019-11-14 17:11:16 +05301207 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Girish Kumarf56a4682020-03-20 20:07:46 +00001208 logger.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001209 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001210 }
1211 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001212 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001213 return err
1214 }
1215 return nil
1216}
1217
khenaidoo4d4802d2018-10-04 21:59:49 -04001218/*
1219All the functions below are callback functions where they are invoked with the latest and previous data. We can
1220therefore use the data as is without trying to get the latest from the model.
1221*/
1222
khenaidoo0a822f92019-05-08 15:15:57 -04001223//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001224func (dMgr *DeviceManager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001225 logger.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001226 var childDeviceIds []string
1227 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001228 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1229 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001230 }
1231 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001232 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001233 }
npujar1d86a522019-11-14 17:11:16 +05301234 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301235 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1236 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001237 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001238 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001239 }
1240 }
1241 }
1242 return nil
1243}
1244
khenaidoo0a822f92019-05-08 15:15:57 -04001245//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001246func (dMgr *DeviceManager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001247 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001248 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001249 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001250 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1251 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001252 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001253 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001254 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001255 }
npujar1d86a522019-11-14 17:11:16 +05301256 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301257 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1258 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001259 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001260 }
khenaidoo49085352020-01-13 19:15:43 -05001261 // No further action is required here. The deleteDevice will change the device state where the resulting
1262 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001263 }
1264 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001265 return nil
1266}
1267
Hardik Windlassc704def2020-02-26 18:23:19 +00001268//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001269func (dMgr *DeviceManager) DeleteAllUNILogicalPorts(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001270 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": curr.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001271 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, curr); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001272 // Just log the error and let the remaining pipeline proceed - ports may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001273 logger.Warnw("delete-all-uni-logical-ports-failed", log.Fields{"parent-device-id": curr.Id, "error": err})
Hardik Windlassc704def2020-02-26 18:23:19 +00001274 }
1275 return nil
1276}
1277
Girish Gowdra408cd962020-03-11 14:31:31 -07001278//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001279func (dMgr *DeviceManager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001280 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001281 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001282 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001283 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001284 }
1285 return nil
1286}
1287
1288//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001289func (dMgr *DeviceManager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001290 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001291 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1292 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001293 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001294 return err
1295 }
1296 return nil
1297 }
1298 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1299}
1300
khenaidoo4d4802d2018-10-04 21:59:49 -04001301//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
1302func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001303 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001304 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001305 if parentDevice != nil {
1306 for _, port := range parentDevice.Ports {
1307 for _, peer := range port.Peers {
1308 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1309 }
khenaidoo92e62c52018-10-03 14:02:54 -04001310 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001311 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001312 }
1313 return childDeviceIds, nil
1314}
1315
khenaidoo297cd252019-02-07 22:10:23 -05001316//getAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
npujar467fe752020-01-16 20:17:45 +05301317func (dMgr *DeviceManager) getAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001318 logger.Debugw("getAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301319 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001320 childDevices := make([]*voltha.Device, 0)
1321 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301322 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301323 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001324 childDevices = append(childDevices, d)
1325 }
1326 }
1327 }
1328 return &voltha.Devices{Items: childDevices}, nil
1329 }
npujar1d86a522019-11-14 17:11:16 +05301330 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001331}
1332
npujar1d86a522019-11-14 17:11:16 +05301333// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001334func (dMgr *DeviceManager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001335 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301336 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001337 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001338 return err
1339 }
1340 return nil
1341}
1342
khenaidoof5a5bfa2019-01-23 22:20:29 -05001343func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001344 logger.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001345 var res interface{}
1346 var err error
npujar467fe752020-01-16 20:17:45 +05301347 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001348 if res, err = agent.downloadImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001349 logger.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001350 res = err
1351 }
1352 } else {
1353 res = status.Errorf(codes.NotFound, "%s", img.Id)
1354 }
1355 sendResponse(ctx, ch, res)
1356}
1357
1358func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001359 logger.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001360 var res interface{}
1361 var err error
npujar467fe752020-01-16 20:17:45 +05301362 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001363 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001364 logger.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001365 res = err
1366 }
1367 } else {
1368 res = status.Errorf(codes.NotFound, "%s", img.Id)
1369 }
1370 sendResponse(ctx, ch, res)
1371}
1372
1373func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001374 logger.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001375 var res interface{}
1376 var err error
npujar467fe752020-01-16 20:17:45 +05301377 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001378 if res, err = agent.activateImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001379 logger.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001380 res = err
1381 }
1382 } else {
1383 res = status.Errorf(codes.NotFound, "%s", img.Id)
1384 }
1385 sendResponse(ctx, ch, res)
1386}
1387
1388func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001389 logger.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001390 var res interface{}
1391 var err error
npujar467fe752020-01-16 20:17:45 +05301392 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001393 if res, err = agent.revertImage(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001394 logger.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001395 res = err
1396 }
1397 } else {
1398 res = status.Errorf(codes.NotFound, "%s", img.Id)
1399 }
1400 sendResponse(ctx, ch, res)
1401}
1402
1403func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001404 logger.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001405 var res interface{}
1406 var err error
npujar467fe752020-01-16 20:17:45 +05301407 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001408 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001409 logger.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001410 res = err
1411 }
1412 } else {
1413 res = status.Errorf(codes.NotFound, "%s", img.Id)
1414 }
1415 sendResponse(ctx, ch, res)
1416}
1417
npujar467fe752020-01-16 20:17:45 +05301418func (dMgr *DeviceManager) updateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001419 logger.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301420 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1421 if err := agent.updateImageDownload(ctx, img); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001422 logger.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001423 return err
1424 }
1425 } else {
1426 return status.Errorf(codes.NotFound, "%s", img.Id)
1427 }
1428 return nil
1429}
1430
1431func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001432 logger.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301433 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001434 return agent.getImageDownload(ctx, img)
1435 }
1436 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1437}
1438
npujar1d86a522019-11-14 17:11:16 +05301439func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001440 logger.Debugw("listImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301441 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301442 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001443 }
npujar1d86a522019-11-14 17:11:16 +05301444 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001445}
1446
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001447func (dMgr *DeviceManager) NotifyInvalidTransition(_ context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001448 logger.Errorw("NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001449 "device": device.Id,
1450 "curr-admin-state": device.AdminState,
1451 "curr-oper-state": device.OperStatus,
1452 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001453 })
khenaidoo0a822f92019-05-08 15:15:57 -04001454 //TODO: notify over kafka?
1455 return nil
1456}
1457
khenaidoob9203542018-09-17 22:56:37 -04001458func funcName(f interface{}) string {
1459 p := reflect.ValueOf(f).Pointer()
1460 rf := runtime.FuncForPC(p)
1461 return rf.Name()
1462}
1463
npujar1d86a522019-11-14 17:11:16 +05301464// UpdateDeviceAttribute updates value of particular device attribute
npujar467fe752020-01-16 20:17:45 +05301465func (dMgr *DeviceManager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301466 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
npujar467fe752020-01-16 20:17:45 +05301467 agent.(*DeviceAgent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001468 }
1469}
1470
npujar1d86a522019-11-14 17:11:16 +05301471// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
npujar467fe752020-01-16 20:17:45 +05301472func (dMgr *DeviceManager) GetParentDeviceID(ctx context.Context, deviceID string) string {
1473 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001474 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001475 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001476 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001477 return ""
khenaidoob9203542018-09-17 22:56:37 -04001478}
serkant.uluderya334479d2019-04-10 08:26:15 -07001479
1480func (dMgr *DeviceManager) simulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001481 logger.Debugw("simulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
serkant.uluderya334479d2019-04-10 08:26:15 -07001482 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1483 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1484 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301485 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001486 res = agent.simulateAlarm(ctx, simulatereq)
Girish Kumarf56a4682020-03-20 20:07:46 +00001487 logger.Debugw("simulateAlarm-result", log.Fields{"result": res})
serkant.uluderya334479d2019-04-10 08:26:15 -07001488 }
1489 //TODO CLI always get successful response
1490 sendResponse(ctx, ch, res)
1491}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001492
npujar467fe752020-01-16 20:17:45 +05301493func (dMgr *DeviceManager) updateDeviceReason(ctx context.Context, deviceID string, reason string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001494 logger.Debugw("updateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301495 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1496 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001497 }
npujar1d86a522019-11-14 17:11:16 +05301498 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001499}
kesavandbc2d1622020-01-21 00:42:01 -05001500
1501func (dMgr *DeviceManager) enablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001502 logger.Debugw("enablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001503 var res interface{}
1504 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1505 res = agent.enablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001506 logger.Debugw("enablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001507 } else {
1508 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1509 }
1510
1511 sendResponse(ctx, ch, res)
1512}
1513
1514func (dMgr *DeviceManager) disablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001515 logger.Debugw("disablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001516 var res interface{}
1517 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1518 res = agent.disablePort(ctx, port)
Girish Kumarf56a4682020-03-20 20:07:46 +00001519 logger.Debugw("disablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001520 } else {
1521 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1522 }
1523
1524 sendResponse(ctx, ch, res)
1525}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001526
khenaidoo442e7c72020-03-10 16:13:48 -04001527// childDeviceLost calls parent adapter to delete child device and all its references
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001528func (dMgr *DeviceManager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001529 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001530 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001531 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1532 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001533 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001534 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001535 }
khenaidooe132f522020-03-20 15:23:15 -04001536 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1537 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001538}
onkarkundargi87285252020-01-27 11:34:52 +05301539
1540func (dMgr *DeviceManager) startOmciTest(ctx context.Context, omcitestrequest *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001541 logger.Debugw("Omci_test_Request", log.Fields{"device-id": omcitestrequest.Id, "uuid": omcitestrequest.Uuid})
onkarkundargi87285252020-01-27 11:34:52 +05301542 if agent := dMgr.getDeviceAgent(ctx, omcitestrequest.Id); agent != nil {
1543 res, err := agent.startOmciTest(ctx, omcitestrequest)
1544 if err != nil {
1545 return nil, err
1546 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001547 logger.Debugw("Omci_test_Response_result-device-magnager", log.Fields{"result": res})
onkarkundargi87285252020-01-27 11:34:52 +05301548 return res, nil
1549 }
1550 return nil, status.Errorf(codes.NotFound, "%s", omcitestrequest.Id)
1551}