blob: 48edc5bab2be98a912f01984eb8336f238069cd7 [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
Kent Hagerman2b216042020-04-03 18:28:56 -040017package device
khenaidoob9203542018-09-17 22:56:37 -040018
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"
Kent Hagerman2b216042020-04-03 18:28:56 -040028 "github.com/opencord/voltha-go/rw_core/core/adapter"
29 "github.com/opencord/voltha-go/rw_core/core/device/remote"
khenaidoo3d3b8c22019-05-22 18:10:39 -040030 "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080031 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
32 "github.com/opencord/voltha-lib-go/v3/pkg/log"
33 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
34 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
35 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
36 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040037 "google.golang.org/grpc/codes"
38 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040039)
40
Kent Hagerman2b216042020-04-03 18:28:56 -040041// Manager represent device manager attributes
42type Manager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040043 deviceAgents sync.Map
44 rootDevices map[string]bool
45 lockRootDeviceMap sync.RWMutex
Kent Hagerman2b216042020-04-03 18:28:56 -040046 adapterProxy *remote.AdapterProxy
47 adapterMgr *adapter.Manager
48 logicalDeviceMgr *LogicalManager
npujar467fe752020-01-16 20:17:45 +053049 kafkaICProxy kafka.InterContainerProxy
khenaidoo4c9e5592019-09-09 16:20:41 -040050 stateTransitions *TransitionMap
51 clusterDataProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053052 coreInstanceID string
khenaidoo4c9e5592019-09-09 16:20:41 -040053 exitChannel chan int
khenaidoo442e7c72020-03-10 16:13:48 -040054 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040055 devicesLoadingLock sync.RWMutex
56 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040057}
58
Kent Hagerman2b216042020-04-03 18:28:56 -040059func NewDeviceManagers(proxy *model.Proxy, adapterMgr *adapter.Manager, kmp kafka.InterContainerProxy, endpointMgr kafka.EndpointManager, corePairTopic, coreInstanceID string, defaultCoreTimeout time.Duration) (*Manager, *LogicalManager) {
60 deviceMgr := &Manager{
61 exitChannel: make(chan int, 1),
62 rootDevices: make(map[string]bool),
63 kafkaICProxy: kmp,
64 adapterProxy: remote.NewAdapterProxy(kmp, corePairTopic, endpointMgr),
65 coreInstanceID: coreInstanceID,
66 clusterDataProxy: proxy,
67 adapterMgr: adapterMgr,
68 defaultTimeout: defaultCoreTimeout * time.Millisecond,
69 deviceLoadingInProgress: make(map[string][]chan int),
70 }
71 logicalDeviceMgr := &LogicalManager{
72 exitChannel: make(chan int, 1),
73 deviceMgr: deviceMgr,
74 kafkaICProxy: kmp,
75 clusterDataProxy: proxy,
76 defaultTimeout: defaultCoreTimeout,
77 logicalDeviceLoadingInProgress: make(map[string][]chan int),
78 }
79 deviceMgr.logicalDeviceMgr = logicalDeviceMgr
Matteo Scandolod525ae32020-04-02 17:27:29 -070080
Kent Hagerman2b216042020-04-03 18:28:56 -040081 adapterMgr.SetAdapterRestartedCallback(deviceMgr.adapterRestarted)
Matteo Scandolod525ae32020-04-02 17:27:29 -070082
Kent Hagerman2b216042020-04-03 18:28:56 -040083 return deviceMgr, logicalDeviceMgr
khenaidoob9203542018-09-17 22:56:37 -040084}
85
Kent Hagerman2b216042020-04-03 18:28:56 -040086func (dMgr *Manager) Start(ctx context.Context) {
Girish Kumarf56a4682020-03-20 20:07:46 +000087 logger.Info("starting-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040088 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070089 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
Girish Kumarf56a4682020-03-20 20:07:46 +000090 logger.Info("device-manager-started")
khenaidoob9203542018-09-17 22:56:37 -040091}
92
Kent Hagerman2b216042020-04-03 18:28:56 -040093func (dMgr *Manager) Stop(ctx context.Context) {
Girish Kumarf56a4682020-03-20 20:07:46 +000094 logger.Info("stopping-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040095 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070096 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
Girish Kumarf56a4682020-03-20 20:07:46 +000097 logger.Info("device-manager-stopped")
khenaidoob9203542018-09-17 22:56:37 -040098}
99
100func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
101 if ctx.Err() == nil {
102 // Returned response only of the ctx has not been cancelled/timeout/etc
103 // Channel is automatically closed when a context is Done
104 ch <- result
Girish Kumarf56a4682020-03-20 20:07:46 +0000105 logger.Debugw("sendResponse", log.Fields{"result": result})
khenaidoob9203542018-09-17 22:56:37 -0400106 } else {
107 // Should the transaction be reverted back?
Girish Kumarf56a4682020-03-20 20:07:46 +0000108 logger.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
khenaidoob9203542018-09-17 22:56:37 -0400109 }
110}
111
Kent Hagerman2b216042020-04-03 18:28:56 -0400112func (dMgr *Manager) addDeviceAgentToMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +0530113 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
114 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -0400115 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400116 dMgr.lockRootDeviceMap.Lock()
117 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530118 dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400119
khenaidoob9203542018-09-17 22:56:37 -0400120}
121
Kent Hagerman2b216042020-04-03 18:28:56 -0400122func (dMgr *Manager) deleteDeviceAgentFromMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +0530123 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400124 dMgr.lockRootDeviceMap.Lock()
125 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530126 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400127}
128
khenaidoo297cd252019-02-07 22:10:23 -0500129// getDeviceAgent returns the agent managing the device. If the device is not in memory, it will loads it, if it exists
Kent Hagerman2b216042020-04-03 18:28:56 -0400130func (dMgr *Manager) getDeviceAgent(ctx context.Context, deviceID string) *Agent {
npujar1d86a522019-11-14 17:11:16 +0530131 agent, ok := dMgr.deviceAgents.Load(deviceID)
132 if ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400133 return agent.(*Agent)
khenaidoob9203542018-09-17 22:56:37 -0400134 }
khenaidoo442e7c72020-03-10 16:13:48 -0400135 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530136 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530137 if err == nil {
138 agent, ok = dMgr.deviceAgents.Load(deviceID)
139 if !ok {
140 return nil
141 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400142 return agent.(*Agent)
npujar1d86a522019-11-14 17:11:16 +0530143 }
144 //TODO: Change the return params to return an error as well
Girish Kumarf56a4682020-03-20 20:07:46 +0000145 logger.Errorw("loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400146 return nil
147}
148
khenaidoo297cd252019-02-07 22:10:23 -0500149// listDeviceIdsFromMap returns the list of device IDs that are in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400150func (dMgr *Manager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500151 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400152
153 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
154 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
155 return true
156 })
157
khenaidoo7ccedd52018-12-14 16:48:54 -0500158 return result
159}
160
Kent Hagerman2b216042020-04-03 18:28:56 -0400161func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
npujar467fe752020-01-16 20:17:45 +0530162 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530163 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000164 logger.Errorf("Failed to fetch parent device info")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530165 sendResponse(ctx, ch, err)
166 return
167 }
168 if deviceExist {
Girish Kumarf56a4682020-03-20 20:07:46 +0000169 logger.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530170 sendResponse(ctx, ch, errors.New("Device is already pre-provisioned"))
171 return
172 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400173 logger.Debugw("CreateDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400174
khenaidoo5e677ae2019-02-28 17:26:29 -0500175 // Ensure this device is set as root
176 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400177 // Create and start a device agent for that device
Kent Hagerman2b216042020-04-03 18:28:56 -0400178 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530179 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800180 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000181 logger.Errorw("Fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530182 sendResponse(ctx, ch, err)
Scott Baker80678602019-11-14 16:57:36 -0800183 return
184 }
khenaidoo442e7c72020-03-10 16:13:48 -0400185 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -0400186
Scott Baker80678602019-11-14 16:57:36 -0800187 sendResponse(ctx, ch, device)
khenaidoob9203542018-09-17 22:56:37 -0400188}
189
Kent Hagerman2b216042020-04-03 18:28:56 -0400190func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
191 logger.Debugw("EnableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400192 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530193 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400194 res = agent.enableDevice(ctx)
Girish Kumarf56a4682020-03-20 20:07:46 +0000195 logger.Debugw("EnableDevice-result", log.Fields{"result": res})
Hardik Windlassb9cfcb12020-02-03 15:59:46 +0000196 } else {
197 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400198 }
khenaidoob9203542018-09-17 22:56:37 -0400199 sendResponse(ctx, ch, res)
200}
201
Kent Hagerman2b216042020-04-03 18:28:56 -0400202func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
203 logger.Debugw("DisableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400204 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530205 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400206 res = agent.disableDevice(ctx)
Kent Hagerman2b216042020-04-03 18:28:56 -0400207 logger.Debugw("DisableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400208 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400209 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400210 }
khenaidoo92e62c52018-10-03 14:02:54 -0400211
212 sendResponse(ctx, ch, res)
213}
214
Kent Hagerman2b216042020-04-03 18:28:56 -0400215func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
216 logger.Debugw("RebootDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400217 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530218 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400219 res = agent.rebootDevice(ctx)
Kent Hagerman2b216042020-04-03 18:28:56 -0400220 logger.Debugw("RebootDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400221 } else {
222 res = status.Errorf(codes.NotFound, "%s", id.Id)
223 }
224 sendResponse(ctx, ch, res)
225}
226
Kent Hagerman2b216042020-04-03 18:28:56 -0400227func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
228 logger.Debugw("DeleteDevice", log.Fields{"deviceid": id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400229 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530230 if agent := dMgr.getDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400231 res = agent.deleteDevice(ctx)
Kent Hagerman2b216042020-04-03 18:28:56 -0400232 logger.Debugw("DeleteDevice-result", log.Fields{"result": res})
khenaidoo4d4802d2018-10-04 21:59:49 -0400233 } else {
234 res = status.Errorf(codes.NotFound, "%s", id.Id)
235 }
236 sendResponse(ctx, ch, res)
237}
238
khenaidoo6d62c002019-05-15 21:57:03 -0400239// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
240// This function is called only in the Core that does not own this device. In the Core that owns this device then a
241// deletion deletion also includes removal of any reference of this device.
Kent Hagerman2b216042020-04-03 18:28:56 -0400242func (dMgr *Manager) stopManagingDevice(ctx context.Context, id string) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000243 logger.Infow("stopManagingDevice", log.Fields{"deviceId": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400244 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530245 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400246 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700247 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400248 }
npujar467fe752020-01-16 20:17:45 +0530249 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400250 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000251 logger.Warnw("unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400252 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400253 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400254 }
255 }
256}
257
npujar1d86a522019-11-14 17:11:16 +0530258// RunPostDeviceDelete removes any reference of this device
Kent Hagerman2b216042020-04-03 18:28:56 -0400259func (dMgr *Manager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000260 logger.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530261 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400262 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400263}
264
khenaidoo297cd252019-02-07 22:10:23 -0500265// GetDevice will returns a device, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -0400266func (dMgr *Manager) GetDevice(ctx context.Context, id string) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000267 logger.Debugw("GetDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530268 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400269 return agent.getDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400270 }
271 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400272}
273
npujar1d86a522019-11-14 17:11:16 +0530274// GetChildDevice will return a device, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -0400275func (dMgr *Manager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000276 logger.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
npujar1d86a522019-11-14 17:11:16 +0530277 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500278
279 var parentDevice *voltha.Device
280 var err error
npujar467fe752020-01-16 20:17:45 +0530281 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500282 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
283 }
284 var childDeviceIds []string
285 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
286 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
287 }
288 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000289 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530290 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500291 }
292
293 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530294 for _, childDeviceID := range childDeviceIds {
295 var found bool
npujar467fe752020-01-16 20:17:45 +0530296 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500297
npujar1d86a522019-11-14 17:11:16 +0530298 foundOnuID := false
299 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500300 if searchDevice.ParentPortNo == uint32(parentPortNo) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000301 logger.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530302 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500303 }
304 }
305
306 foundSerialNumber := false
307 if searchDevice.SerialNumber == serialNumber {
Girish Kumarf56a4682020-03-20 20:07:46 +0000308 logger.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500309 foundSerialNumber = true
310 }
311
312 // if both onuId and serialNumber are provided both must be true for the device to be found
313 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530314 if onuID > 0 && serialNumber != "" {
315 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500316 } else {
npujar1d86a522019-11-14 17:11:16 +0530317 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500318 }
319
npujar1d86a522019-11-14 17:11:16 +0530320 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500321 foundChildDevice = searchDevice
322 break
323 }
324 }
325 }
326
327 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000328 logger.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500329 return foundChildDevice, nil
330 }
331
Girish Kumarf56a4682020-03-20 20:07:46 +0000332 logger.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530333 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
334 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500335}
336
npujar1d86a522019-11-14 17:11:16 +0530337// GetChildDeviceWithProxyAddress will return a device based on proxy address
Kent Hagerman2b216042020-04-03 18:28:56 -0400338func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000339 logger.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500340
341 var parentDevice *voltha.Device
342 var err error
npujar467fe752020-01-16 20:17:45 +0530343 if parentDevice, err = dMgr.GetDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500344 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
345 }
346 var childDeviceIds []string
347 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
348 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
349 }
350 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000351 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500352 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
353 }
354
355 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530356 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530357 if searchDevice, err := dMgr.GetDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500358 if searchDevice.ProxyAddress == proxyAddress {
359 foundChildDevice = searchDevice
360 break
361 }
362 }
363 }
364
365 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000366 logger.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500367 return foundChildDevice, nil
368 }
369
Girish Kumarf56a4682020-03-20 20:07:46 +0000370 logger.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500371 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
372}
373
npujar1d86a522019-11-14 17:11:16 +0530374// IsDeviceInCache returns true if device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400375func (dMgr *Manager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400376 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500377 return exist
378}
379
npujar1d86a522019-11-14 17:11:16 +0530380// IsRootDevice returns true if root device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400381func (dMgr *Manager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400382 dMgr.lockRootDeviceMap.RLock()
383 defer dMgr.lockRootDeviceMap.RUnlock()
384 if exist := dMgr.rootDevices[id]; exist {
385 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400386 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400387 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400388}
389
Stephane Barbarieaa467942019-02-06 14:09:44 -0500390// ListDevices retrieves the latest devices from the data model
Kent Hagerman2b216042020-04-03 18:28:56 -0400391func (dMgr *Manager) ListDevices(ctx context.Context) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000392 logger.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400393 result := &voltha.Devices{}
Kent Hagerman4f355f52020-03-30 16:01:33 -0400394
395 var devices []*voltha.Device
396 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000397 logger.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530398 return nil, err
399 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400400
401 for _, device := range devices {
402 // If device is not in memory then set it up
403 if !dMgr.IsDeviceInCache(device.Id) {
404 logger.Debugw("loading-device-from-Model", log.Fields{"id": device.Id})
Kent Hagerman2b216042020-04-03 18:28:56 -0400405 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Kent Hagerman4f355f52020-03-30 16:01:33 -0400406 if _, err := agent.start(ctx, nil); err != nil {
407 logger.Warnw("failure-starting-agent", log.Fields{"deviceId": device.Id})
408 } else {
409 dMgr.addDeviceAgentToMap(agent)
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500410 }
khenaidoob9203542018-09-17 22:56:37 -0400411 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400412 result.Items = append(result.Items, device)
khenaidoob9203542018-09-17 22:56:37 -0400413 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000414 logger.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400415 return result, nil
416}
417
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530418//isParentDeviceExist checks whether device is already preprovisioned.
Kent Hagerman2b216042020-04-03 18:28:56 -0400419func (dMgr *Manager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530420 hostPort := newDevice.GetHostAndPort()
Kent Hagerman4f355f52020-03-30 16:01:33 -0400421 var devices []*voltha.Device
422 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000423 logger.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530424 return false, err
425 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400426 for _, device := range devices {
427 if !device.Root {
428 continue
429 }
430 if hostPort != "" && hostPort == device.GetHostAndPort() && device.AdminState != voltha.AdminState_DELETED {
431 return true, nil
432 }
433 if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress && device.AdminState != voltha.AdminState_DELETED {
434 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530435 }
436 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530437 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530438}
439
khenaidoo6d62c002019-05-15 21:57:03 -0400440//getDeviceFromModelretrieves the device data from the model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400441func (dMgr *Manager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400442 device := &voltha.Device{}
443 if have, err := dMgr.clusterDataProxy.Get(ctx, "devices/"+deviceID, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000444 logger.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530445 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400446 } else if !have {
447 return nil, status.Error(codes.NotFound, deviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530448 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400449
450 return device, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400451}
452
npujar1d86a522019-11-14 17:11:16 +0530453// loadDevice loads the deviceID in memory, if not present
Kent Hagerman2b216042020-04-03 18:28:56 -0400454func (dMgr *Manager) loadDevice(ctx context.Context, deviceID string) (*Agent, error) {
npujar1d86a522019-11-14 17:11:16 +0530455 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500456 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
457 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400458 var err error
459 var device *voltha.Device
460 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530461 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
462 if !dMgr.IsDeviceInCache(deviceID) {
463 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400464 dMgr.devicesLoadingLock.Unlock()
465 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530466 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000467 logger.Debugw("loading-device", log.Fields{"deviceId": deviceID})
Kent Hagerman2b216042020-04-03 18:28:56 -0400468 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530469 if _, err = agent.start(ctx, nil); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000470 logger.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400471 } else {
472 dMgr.addDeviceAgentToMap(agent)
473 }
474 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000475 logger.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400476 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400477 // announce completion of task to any number of waiting channels
478 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530479 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400480 for _, ch := range v {
481 close(ch)
482 }
npujar1d86a522019-11-14 17:11:16 +0530483 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400484 }
485 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400486 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400487 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500488 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400489 } else {
490 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530491 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400492 dMgr.devicesLoadingLock.Unlock()
493 // Wait for the channel to be closed, implying the process loading this device is done.
494 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500495 }
npujar1d86a522019-11-14 17:11:16 +0530496 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400497 return agent.(*Agent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500498 }
npujar1d86a522019-11-14 17:11:16 +0530499 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500500}
501
502// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400503func (dMgr *Manager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000504 logger.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500505 if device.Root {
506 // Scenario A
507 if device.ParentId != "" {
508 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530509 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000510 logger.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500511 }
512 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000513 logger.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500514 }
515 // Load all child devices, if needed
516 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530517 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530518 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000519 logger.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500520 return err
521 }
522 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000523 logger.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500524 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000525 logger.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500526 }
527 }
528 return nil
529}
530
531// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
532// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
533// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
534// and the proceed with the request.
Kent Hagerman2b216042020-04-03 18:28:56 -0400535func (dMgr *Manager) load(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000536 logger.Debug("load...")
khenaidoo297cd252019-02-07 22:10:23 -0500537 // First load the device - this may fail in case the device was deleted intentionally by the other core
Kent Hagerman2b216042020-04-03 18:28:56 -0400538 var dAgent *Agent
khenaidoo297cd252019-02-07 22:10:23 -0500539 var err error
npujar467fe752020-01-16 20:17:45 +0530540 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500541 return err
542 }
543 // Get the loaded device details
khenaidoo442e7c72020-03-10 16:13:48 -0400544 device, err := dAgent.getDevice(ctx)
545 if err != nil {
546 return err
547 }
khenaidoo297cd252019-02-07 22:10:23 -0500548
549 // If the device is in Pre-provisioning or deleted state stop here
550 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
551 return nil
552 }
553
554 // Now we face two scenarios
555 if device.Root {
556 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530557 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000558 logger.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500559 return err
560 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000561 logger.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500562 } else {
563 // Scenario B - use the parentId of that device (root device) to trigger the loading
564 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530565 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500566 }
567 }
568 return nil
569}
570
khenaidoo7ccedd52018-12-14 16:48:54 -0500571// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
Kent Hagerman2b216042020-04-03 18:28:56 -0400572func (dMgr *Manager) ListDeviceIds() (*voltha.IDs, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000573 logger.Debug("ListDeviceIDs")
khenaidoo7ccedd52018-12-14 16:48:54 -0500574 // Report only device IDs that are in the device agent map
575 return dMgr.listDeviceIdsFromMap(), nil
576}
577
khenaidoo4c9e5592019-09-09 16:20:41 -0400578//ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
579//trigger loading the devices along with their children and parent in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400580func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000581 logger.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo7ccedd52018-12-14 16:48:54 -0500582 var res interface{}
khenaidoo4c9e5592019-09-09 16:20:41 -0400583 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500584 toReconcile := len(ids.Items)
585 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400586 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500587 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530588 if err = dMgr.load(ctx, id.Id); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000589 logger.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400590 } else {
npujar1d86a522019-11-14 17:11:16 +0530591 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500592 }
593 }
594 if toReconcile != reconciled {
khenaidoo4c9e5592019-09-09 16:20:41 -0400595 res = status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500596 }
597 } else {
598 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
599 }
600 sendResponse(ctx, ch, res)
601}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500602
khenaidooba6b6c42019-08-02 09:11:56 -0400603// isOkToReconcile validates whether a device is in the correct status to be reconciled
604func isOkToReconcile(device *voltha.Device) bool {
605 if device == nil {
606 return false
607 }
608 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
609}
610
611// adapterRestarted is invoked whenever an adapter is restarted
Kent Hagerman2b216042020-04-03 18:28:56 -0400612func (dMgr *Manager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Matteo Scandolod525ae32020-04-02 17:27:29 -0700613 logger.Debugw("adapter-restarted", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
614 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidooba6b6c42019-08-02 09:11:56 -0400615
616 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700617 if len(dMgr.rootDevices) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000618 logger.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400619 return nil
620 }
621
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500622 responses := make([]utils.Response, 0)
David Bainbridged1afd662020-03-26 18:27:41 -0700623 for rootDeviceID := range dMgr.rootDevices {
npujar467fe752020-01-16 20:17:45 +0530624 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -0400625 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(rootDeviceID, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700626 if err != nil {
627 logger.Warnw("is-device-owned-by-service", log.Fields{"error": err, "root-device-id": rootDeviceID, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
628 continue
629 }
630 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400631 if isOkToReconcile(rootDevice) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000632 logger.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530633 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400634 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000635 logger.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400636 }
637 } else { // Should we be reconciling the root's children instead?
638 childManagedByAdapter:
639 for _, port := range rootDevice.Ports {
640 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530641 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -0400642 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(childDevice.Id, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700643 if err != nil {
644 logger.Warnw("is-device-owned-by-service", log.Fields{"error": err, "child-device-id": childDevice.Id, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
645 }
646 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400647 if isOkToReconcile(childDevice) {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700648 logger.Debugw("reconciling-child-device", log.Fields{"child-device-id": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530649 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400650 } else {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700651 logger.Debugw("not-reconciling-child-device", log.Fields{"child-device-id": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400652 }
653 } else {
654 // All child devices under a parent device are typically managed by the same adapter type.
655 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
656 break childManagedByAdapter
657 }
658 }
659 }
660 }
661 }
662 }
663 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500664 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400665 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500666 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400667 return status.Errorf(codes.Aborted, "errors-%s", res)
668 }
669 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000670 logger.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400671 }
672 return nil
673}
674
Kent Hagerman2b216042020-04-03 18:28:56 -0400675func (dMgr *Manager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400676 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
677 // 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 +0530678 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to the adapter via
Kent Hagerman2b216042020-04-03 18:28:56 -0400679 // the adapter proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500680 response := utils.NewResponse()
Kent Hagerman2b216042020-04-03 18:28:56 -0400681 ch, err := dMgr.adapterProxy.ReconcileDevice(ctx, device)
khenaidoo442e7c72020-03-10 16:13:48 -0400682 if err != nil {
683 response.Error(err)
684 }
685 // Wait for adapter response in its own routine
686 go func() {
687 resp, ok := <-ch
688 if !ok {
689 response.Error(status.Errorf(codes.Aborted, "channel-closed-device: %s", device.Id))
690 } else if resp.Err != nil {
691 response.Error(resp.Err)
khenaidooba6b6c42019-08-02 09:11:56 -0400692 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500693 response.Done()
khenaidoo442e7c72020-03-10 16:13:48 -0400694 }()
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500695 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400696}
697
Kent Hagerman2b216042020-04-03 18:28:56 -0400698func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID string) error {
npujar467fe752020-01-16 20:17:45 +0530699 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500700 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400701 for _, port := range parentDevice.Ports {
702 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530703 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
704 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400705 }
706 }
707 }
708 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500709 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400710 return status.Errorf(codes.Aborted, "errors-%s", res)
711 }
712 }
713 return nil
714}
715
Kent Hagerman2b216042020-04-03 18:28:56 -0400716func (dMgr *Manager) UpdateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
717 logger.Debugw("UpdateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530718 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
719 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400720 }
721 return status.Errorf(codes.NotFound, "%s", device.Id)
722}
723
Kent Hagerman2b216042020-04-03 18:28:56 -0400724func (dMgr *Manager) AddPort(ctx context.Context, deviceID string, port *voltha.Port) error {
npujar467fe752020-01-16 20:17:45 +0530725 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530726 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530727 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400728 return err
729 }
730 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530731 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400732 for _, peerPort := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530733 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
734 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000735 logger.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
khenaidoo92e62c52018-10-03 14:02:54 -0400736 return err
737 }
738 }
739 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400740 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
741 // then a logical port will be added to the logical device and the device graph generated. If the port is a
742 // PON port then only the device graph will be generated.
npujar467fe752020-01-16 20:17:45 +0530743 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530744 go func() {
npujar467fe752020-01-16 20:17:45 +0530745 err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port)
npujar1d86a522019-11-14 17:11:16 +0530746 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000747 logger.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530748 }
749 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400750 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000751 logger.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400752 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400753 }
khenaidoo92e62c52018-10-03 14:02:54 -0400754 return nil
khenaidoob9203542018-09-17 22:56:37 -0400755 }
npujar1d86a522019-11-14 17:11:16 +0530756 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400757}
758
Kent Hagerman2b216042020-04-03 18:28:56 -0400759func (dMgr *Manager) addFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000760 logger.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530761 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
762 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400763 }
npujar1d86a522019-11-14 17:11:16 +0530764 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400765}
766
Kent Hagerman2b216042020-04-03 18:28:56 -0400767func (dMgr *Manager) deleteFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000768 logger.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530769 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
770 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400771 }
npujar1d86a522019-11-14 17:11:16 +0530772 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400773}
774
Kent Hagerman2b216042020-04-03 18:28:56 -0400775func (dMgr *Manager) updateFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000776 logger.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530777 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
778 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400779 }
npujar1d86a522019-11-14 17:11:16 +0530780 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400781}
782
Kent Hagerman2b216042020-04-03 18:28:56 -0400783// UpdatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
khenaidoob3127472019-07-24 21:04:55 -0400784// following a user action
Kent Hagerman2b216042020-04-03 18:28:56 -0400785func (dMgr *Manager) UpdatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
khenaidoob3127472019-07-24 21:04:55 -0400786 var res interface{}
787 if pmConfigs.Id == "" {
788 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
npujar467fe752020-01-16 20:17:45 +0530789 } else if agent := dMgr.getDeviceAgent(ctx, pmConfigs.Id); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400790 res = agent.updatePmConfigs(ctx, pmConfigs)
791 } else {
792 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
793 }
794 sendResponse(ctx, ch, res)
795}
796
Kent Hagerman2b216042020-04-03 18:28:56 -0400797// InitPmConfigs initialize the pm configs as defined by the adapter.
798func (dMgr *Manager) InitPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400799 if pmConfigs.Id == "" {
800 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
801 }
npujar467fe752020-01-16 20:17:45 +0530802 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
803 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400804 }
npujar1d86a522019-11-14 17:11:16 +0530805 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400806}
807
Kent Hagerman2b216042020-04-03 18:28:56 -0400808func (dMgr *Manager) ListPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
npujar467fe752020-01-16 20:17:45 +0530809 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400810 return agent.listPmConfigs(ctx)
811 }
npujar1d86a522019-11-14 17:11:16 +0530812 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400813}
814
Kent Hagerman2b216042020-04-03 18:28:56 -0400815func (dMgr *Manager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000816 logger.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530817 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400818 return agent.getSwitchCapability(ctx)
819 }
npujar1d86a522019-11-14 17:11:16 +0530820 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400821}
822
Kent Hagerman2b216042020-04-03 18:28:56 -0400823func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
824 logger.Debugw("GetPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530825 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400826 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400827 }
npujar1d86a522019-11-14 17:11:16 +0530828 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400829}
830
Kent Hagerman2b216042020-04-03 18:28:56 -0400831func (dMgr *Manager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000832 logger.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530833 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400834 return agent.getPortCapability(ctx, portNo)
835 }
npujar1d86a522019-11-14 17:11:16 +0530836 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400837}
838
Kent Hagerman2b216042020-04-03 18:28:56 -0400839func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
840 logger.Debugw("UpdateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530841 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
842 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400843 }
npujar1d86a522019-11-14 17:11:16 +0530844 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400845}
846
Kent Hagerman2b216042020-04-03 18:28:56 -0400847func (dMgr *Manager) UpdateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
848 logger.Debugw("UpdateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400849 var parentDevice *voltha.Device
850 var err error
npujar467fe752020-01-16 20:17:45 +0530851 if parentDevice, err = dMgr.GetDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400852 return status.Errorf(codes.Aborted, "%s", err.Error())
853 }
854 var childDeviceIds []string
855 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
856 return status.Errorf(codes.Aborted, "%s", err.Error())
857 }
858 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000859 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400860 }
npujar1d86a522019-11-14 17:11:16 +0530861 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530862 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
863 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530864 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400865 }
866 }
867 }
868 return nil
869}
870
Kent Hagerman2b216042020-04-03 18:28:56 -0400871func (dMgr *Manager) UpdatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
872 logger.Debugw("UpdatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530873 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
874 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000875 logger.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400876 return err
877 }
878 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800879 // Do this for NNI and UNIs only. PON ports are not known by logical device
880 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
881 go func() {
882 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
883 if err != nil {
884 // While we want to handle (catch) and log when
885 // an update to a port was not able to be
886 // propagated to the logical port, we can report
887 // it as a warning and not an error because it
888 // doesn't stop or modify processing.
889 // TODO: VOL-2707
Girish Kumarf56a4682020-03-20 20:07:46 +0000890 logger.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800891 }
892 }()
893 }
khenaidoo442e7c72020-03-10 16:13:48 -0400894 return nil
khenaidoob9203542018-09-17 22:56:37 -0400895 }
npujar1d86a522019-11-14 17:11:16 +0530896 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400897}
898
Kent Hagerman2b216042020-04-03 18:28:56 -0400899func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000900 logger.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530901 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
902 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400903 return err
904 }
905 // Notify the logical device manager to remove all logical ports, if needed.
Kent Hagerman2b216042020-04-03 18:28:56 -0400906 // At this stage the device itself may gave been deleted already at a DeleteAllPorts
khenaidoo0a822f92019-05-08 15:15:57 -0400907 // typically is part of a device deletion phase.
npujar467fe752020-01-16 20:17:45 +0530908 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530909 go func() {
npujar467fe752020-01-16 20:17:45 +0530910 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530911 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000912 logger.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530913 }
914 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400915 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000916 logger.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400917 return err
918 }
919 return nil
920 }
npujar1d86a522019-11-14 17:11:16 +0530921 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400922}
923
Kent Hagerman2b216042020-04-03 18:28:56 -0400924//UpdatePortsState updates all ports on the device
925func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
926 logger.Debugw("UpdatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400927
npujar467fe752020-01-16 20:17:45 +0530928 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400929 switch state {
930 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500931 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000932 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400933 return err
934 }
935 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500936 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000937 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400938 return err
939 }
940 default:
941 return status.Error(codes.Unimplemented, "state-change-not-implemented")
942 }
943 // Notify the logical device about the state change
npujar467fe752020-01-16 20:17:45 +0530944 device, err := dMgr.GetDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530945 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000946 logger.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400947 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400948 }
kesavandbc2d1622020-01-21 00:42:01 -0500949 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000950 logger.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530951 return err
952 }
953 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400954 }
npujar1d86a522019-11-14 17:11:16 +0530955 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400956}
957
Kent Hagerman2b216042020-04-03 18:28:56 -0400958func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530959 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -0400960 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 -0700961
npujar1d86a522019-11-14 17:11:16 +0530962 if deviceType == "" && vendorID != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000963 logger.Debug("device-type-is-nil-fetching-device-type")
Kent Hagerman4f355f52020-03-30 16:01:33 -0400964 OLoop:
Kent Hagerman2b216042020-04-03 18:28:56 -0400965 for _, dType := range dMgr.adapterMgr.ListDeviceTypes() {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400966 for _, v := range dType.VendorIds {
967 if v == vendorID {
968 deviceType = dType.Adapter
969 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700970 }
971 }
972 }
973 }
974 //if no match found for the vendorid,report adapter with the custom error message
975 if deviceType == "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000976 logger.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +0530977 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700978 }
khenaidoob9203542018-09-17 22:56:37 -0400979
980 // Create the ONU device
981 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400982 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530983 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400984 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530985 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500986 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400987 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400988
khenaidoo442e7c72020-03-10 16:13:48 -0400989 // Get parent device type
990 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
991 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +0530992 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400993 }
khenaidoo442e7c72020-03-10 16:13:48 -0400994 if pAgent.deviceType == "" {
995 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
996 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400997
npujar467fe752020-01-16 20:17:45 +0530998 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000999 logger.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001000 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001001 }
1002
khenaidoo442e7c72020-03-10 16:13:48 -04001003 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001004
1005 // Create and start a device agent for that device
Kent Hagerman2b216042020-04-03 18:28:56 -04001006 agent := newAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -04001007 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001008 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001009 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 -08001010 return nil, err
1011 }
khenaidoo442e7c72020-03-10 16:13:48 -04001012 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001013
1014 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301015 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301016 go func() {
npujar467fe752020-01-16 20:17:45 +05301017 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301018 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001019 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301020 }
1021 }()
khenaidoob9203542018-09-17 22:56:37 -04001022 }
1023
khenaidoo79232702018-12-04 11:00:41 -05001024 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301025 go func() {
1026 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1027 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001028 logger.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301029 }
1030 }()
khenaidoo79232702018-12-04 11:00:41 -05001031
Scott Baker80678602019-11-14 16:57:36 -08001032 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001033}
1034
Kent Hagerman2b216042020-04-03 18:28:56 -04001035func (dMgr *Manager) processTransition(ctx context.Context, device *voltha.Device, previousState *deviceState) error {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001036 // This will be triggered on every state update
1037 logger.Debugw("state-transition", log.Fields{
1038 "device": device.Id,
1039 "prev-admin-state": previousState.Admin,
1040 "prev-oper-state": previousState.Operational,
1041 "prev-conn-state": previousState.Connection,
1042 "curr-admin-state": device.AdminState,
1043 "curr-oper-state": device.OperStatus,
1044 "curr-conn-state": device.ConnectStatus,
1045 })
1046 handlers := dMgr.stateTransitions.GetTransitionHandler(device, previousState)
khenaidoo92e62c52018-10-03 14:02:54 -04001047 if handlers == nil {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001048 logger.Debugw("no-op-transition", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001049 return nil
khenaidoob9203542018-09-17 22:56:37 -04001050 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001051 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 -04001052 for _, handler := range handlers {
Girish Kumarf56a4682020-03-20 20:07:46 +00001053 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001054 if err := handler(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001055 logger.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001056 return err
1057 }
1058 }
khenaidoob9203542018-09-17 22:56:37 -04001059 return nil
1060}
1061
Kent Hagerman2b216042020-04-03 18:28:56 -04001062func (dMgr *Manager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001063 logger.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301064 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1065 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001066 }
npujar1d86a522019-11-14 17:11:16 +05301067 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001068}
1069
npujar1d86a522019-11-14 17:11:16 +05301070// PacketIn receives packet from adapter
Kent Hagerman2b216042020-04-03 18:28:56 -04001071func (dMgr *Manager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001072 logger.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001073 // Get the logical device Id based on the deviceId
1074 var device *voltha.Device
1075 var err error
npujar467fe752020-01-16 20:17:45 +05301076 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001077 logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001078 return err
1079 }
khenaidoo43c82122018-11-22 18:38:28 -05001080 if !device.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +00001081 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301082 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001083 }
1084
npujar467fe752020-01-16 20:17:45 +05301085 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001086 return err
1087 }
1088 return nil
1089}
1090
Kent Hagerman2b216042020-04-03 18:28:56 -04001091func (dMgr *Manager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001092 logger.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301093 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1094 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001095 }
1096 return status.Errorf(codes.NotFound, "%s", device.Id)
1097}
1098
npujar1d86a522019-11-14 17:11:16 +05301099// CreateLogicalDevice creates logical device in core
Kent Hagerman2b216042020-04-03 18:28:56 -04001100func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001101 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001102 // Verify whether the logical device has already been created
1103 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001104 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001105 return nil
1106 }
khenaidoob9203542018-09-17 22:56:37 -04001107 var err error
npujar467fe752020-01-16 20:17:45 +05301108 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001109 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001110 return err
1111 }
khenaidoob9203542018-09-17 22:56:37 -04001112 return nil
1113}
1114
npujar1d86a522019-11-14 17:11:16 +05301115// DeleteLogicalDevice deletes logical device from core
Kent Hagerman2b216042020-04-03 18:28:56 -04001116func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001117 logger.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001118 var err error
npujar467fe752020-01-16 20:17:45 +05301119 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001120 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001121 return err
1122 }
1123 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301124 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301125 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001126 return nil
1127}
1128
npujar1d86a522019-11-14 17:11:16 +05301129// DeleteLogicalPort removes the logical port associated with a device
Kent Hagerman2b216042020-04-03 18:28:56 -04001130func (dMgr *Manager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001131 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001132 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001133 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301134 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301135 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001136 logger.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001137 return err
1138 }
npujar467fe752020-01-16 20:17:45 +05301139 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001140 logger.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001141 return err
1142 }
khenaidoo92e62c52018-10-03 14:02:54 -04001143 return nil
1144}
1145
npujar1d86a522019-11-14 17:11:16 +05301146// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagerman2b216042020-04-03 18:28:56 -04001147func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001148 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001149 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001150 // 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 +00001151 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001152 }
1153 return nil
1154}
1155
Kent Hagerman2b216042020-04-03 18:28:56 -04001156func (dMgr *Manager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001157 // Sanity check
1158 if childDevice.Root {
1159 // childDevice is the parent device
1160 return childDevice
1161 }
npujar467fe752020-01-16 20:17:45 +05301162 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001163 return parentDevice
1164}
1165
Kent Hagerman2b216042020-04-03 18:28:56 -04001166//ChildDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
khenaidoo0a822f92019-05-08 15:15:57 -04001167//cannot manage the child devices. This will trigger the Core to disable all the child devices.
Kent Hagerman2b216042020-04-03 18:28:56 -04001168func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
1169 logger.Debug("ChildDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001170 var err error
1171 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301172 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001173 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001174 return err
1175 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001176 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001177}
1178
Kent Hagerman2b216042020-04-03 18:28:56 -04001179//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
khenaidoo0a822f92019-05-08 15:15:57 -04001180// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
Kent Hagerman2b216042020-04-03 18:28:56 -04001181func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
1182 logger.Debug("ChildDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001183 var err error
1184 var parentDevice *voltha.Device
1185 var childDeviceIds []string
1186
npujar467fe752020-01-16 20:17:45 +05301187 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001188 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001189 return err
1190 }
1191
1192 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1193 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1194 }
1195 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001196 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001197 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001198 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301199 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301200 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001201 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301202 go func() {
npujar467fe752020-01-16 20:17:45 +05301203 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301204 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001205 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301206 }
1207 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001208 } else {
npujar1d86a522019-11-14 17:11:16 +05301209 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Girish Kumarf56a4682020-03-20 20:07:46 +00001210 logger.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001211 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001212 }
1213 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001214 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001215 return err
1216 }
1217 return nil
1218}
1219
khenaidoo4d4802d2018-10-04 21:59:49 -04001220/*
1221All the functions below are callback functions where they are invoked with the latest and previous data. We can
1222therefore use the data as is without trying to get the latest from the model.
1223*/
1224
khenaidoo0a822f92019-05-08 15:15:57 -04001225//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagerman2b216042020-04-03 18:28:56 -04001226func (dMgr *Manager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001227 logger.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001228 var childDeviceIds []string
1229 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001230 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1231 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001232 }
1233 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001234 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001235 }
npujar1d86a522019-11-14 17:11:16 +05301236 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301237 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1238 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001239 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001240 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001241 }
1242 }
1243 }
1244 return nil
1245}
1246
khenaidoo0a822f92019-05-08 15:15:57 -04001247//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001248func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001249 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001250 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001251 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001252 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1253 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001254 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001255 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001256 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001257 }
npujar1d86a522019-11-14 17:11:16 +05301258 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301259 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1260 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001261 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001262 }
khenaidoo49085352020-01-13 19:15:43 -05001263 // No further action is required here. The deleteDevice will change the device state where the resulting
1264 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001265 }
1266 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001267 return nil
1268}
1269
Hardik Windlassc704def2020-02-26 18:23:19 +00001270//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001271func (dMgr *Manager) DeleteAllUNILogicalPorts(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001272 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": curr.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001273 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, curr); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001274 // Just log the error and let the remaining pipeline proceed - ports may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001275 logger.Warnw("delete-all-uni-logical-ports-failed", log.Fields{"parent-device-id": curr.Id, "error": err})
Hardik Windlassc704def2020-02-26 18:23:19 +00001276 }
1277 return nil
1278}
1279
Girish Gowdra408cd962020-03-11 14:31:31 -07001280//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001281func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001282 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001283 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001284 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001285 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001286 }
1287 return nil
1288}
1289
1290//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001291func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001292 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001293 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1294 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001295 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001296 return err
1297 }
1298 return nil
1299 }
1300 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1301}
1302
khenaidoo4d4802d2018-10-04 21:59:49 -04001303//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
Kent Hagerman2b216042020-04-03 18:28:56 -04001304func (dMgr *Manager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001305 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001306 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001307 if parentDevice != nil {
1308 for _, port := range parentDevice.Ports {
1309 for _, peer := range port.Peers {
1310 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1311 }
khenaidoo92e62c52018-10-03 14:02:54 -04001312 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001313 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001314 }
1315 return childDeviceIds, nil
1316}
1317
Kent Hagerman2b216042020-04-03 18:28:56 -04001318//GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1319func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
1320 logger.Debugw("GetAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301321 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001322 childDevices := make([]*voltha.Device, 0)
1323 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301324 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301325 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001326 childDevices = append(childDevices, d)
1327 }
1328 }
1329 }
1330 return &voltha.Devices{Items: childDevices}, nil
1331 }
npujar1d86a522019-11-14 17:11:16 +05301332 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001333}
1334
npujar1d86a522019-11-14 17:11:16 +05301335// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagerman2b216042020-04-03 18:28:56 -04001336func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001337 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301338 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001339 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001340 return err
1341 }
1342 return nil
1343}
1344
Kent Hagerman2b216042020-04-03 18:28:56 -04001345func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1346 logger.Debugw("DownloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001347 var res interface{}
1348 var err error
npujar467fe752020-01-16 20:17:45 +05301349 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001350 if res, err = agent.downloadImage(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001351 logger.Debugw("DownloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001352 res = err
1353 }
1354 } else {
1355 res = status.Errorf(codes.NotFound, "%s", img.Id)
1356 }
1357 sendResponse(ctx, ch, res)
1358}
1359
Kent Hagerman2b216042020-04-03 18:28:56 -04001360func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1361 logger.Debugw("CancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001362 var res interface{}
1363 var err error
npujar467fe752020-01-16 20:17:45 +05301364 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001365 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001366 logger.Debugw("CancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001367 res = err
1368 }
1369 } else {
1370 res = status.Errorf(codes.NotFound, "%s", img.Id)
1371 }
1372 sendResponse(ctx, ch, res)
1373}
1374
Kent Hagerman2b216042020-04-03 18:28:56 -04001375func (dMgr *Manager) ActivateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1376 logger.Debugw("ActivateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001377 var res interface{}
1378 var err error
npujar467fe752020-01-16 20:17:45 +05301379 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001380 if res, err = agent.activateImage(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001381 logger.Debugw("ActivateImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001382 res = err
1383 }
1384 } else {
1385 res = status.Errorf(codes.NotFound, "%s", img.Id)
1386 }
1387 sendResponse(ctx, ch, res)
1388}
1389
Kent Hagerman2b216042020-04-03 18:28:56 -04001390func (dMgr *Manager) RevertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1391 logger.Debugw("RevertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001392 var res interface{}
1393 var err error
npujar467fe752020-01-16 20:17:45 +05301394 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001395 if res, err = agent.revertImage(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001396 logger.Debugw("RevertImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001397 res = err
1398 }
1399 } else {
1400 res = status.Errorf(codes.NotFound, "%s", img.Id)
1401 }
1402 sendResponse(ctx, ch, res)
1403}
1404
Kent Hagerman2b216042020-04-03 18:28:56 -04001405func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1406 logger.Debugw("GetImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001407 var res interface{}
1408 var err error
npujar467fe752020-01-16 20:17:45 +05301409 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001410 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001411 logger.Debugw("GetImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001412 res = err
1413 }
1414 } else {
1415 res = status.Errorf(codes.NotFound, "%s", img.Id)
1416 }
1417 sendResponse(ctx, ch, res)
1418}
1419
Kent Hagerman2b216042020-04-03 18:28:56 -04001420func (dMgr *Manager) UpdateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
1421 logger.Debugw("UpdateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301422 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1423 if err := agent.updateImageDownload(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001424 logger.Debugw("UpdateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001425 return err
1426 }
1427 } else {
1428 return status.Errorf(codes.NotFound, "%s", img.Id)
1429 }
1430 return nil
1431}
1432
Kent Hagerman2b216042020-04-03 18:28:56 -04001433func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1434 logger.Debugw("GetImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301435 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001436 return agent.getImageDownload(ctx, img)
1437 }
1438 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1439}
1440
Kent Hagerman2b216042020-04-03 18:28:56 -04001441func (dMgr *Manager) ListImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
1442 logger.Debugw("ListImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301443 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301444 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001445 }
npujar1d86a522019-11-14 17:11:16 +05301446 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001447}
1448
Kent Hagerman2b216042020-04-03 18:28:56 -04001449func (dMgr *Manager) NotifyInvalidTransition(_ context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001450 logger.Errorw("NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001451 "device": device.Id,
1452 "curr-admin-state": device.AdminState,
1453 "curr-oper-state": device.OperStatus,
1454 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001455 })
khenaidoo0a822f92019-05-08 15:15:57 -04001456 //TODO: notify over kafka?
1457 return nil
1458}
1459
khenaidoob9203542018-09-17 22:56:37 -04001460func funcName(f interface{}) string {
1461 p := reflect.ValueOf(f).Pointer()
1462 rf := runtime.FuncForPC(p)
1463 return rf.Name()
1464}
1465
npujar1d86a522019-11-14 17:11:16 +05301466// UpdateDeviceAttribute updates value of particular device attribute
Kent Hagerman2b216042020-04-03 18:28:56 -04001467func (dMgr *Manager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301468 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -04001469 agent.(*Agent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001470 }
1471}
1472
npujar1d86a522019-11-14 17:11:16 +05301473// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -04001474func (dMgr *Manager) GetParentDeviceID(ctx context.Context, deviceID string) string {
npujar467fe752020-01-16 20:17:45 +05301475 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001476 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001477 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001478 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001479 return ""
khenaidoob9203542018-09-17 22:56:37 -04001480}
serkant.uluderya334479d2019-04-10 08:26:15 -07001481
Kent Hagerman2b216042020-04-03 18:28:56 -04001482func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1483 logger.Debugw("SimulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
serkant.uluderya334479d2019-04-10 08:26:15 -07001484 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1485 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1486 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301487 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001488 res = agent.simulateAlarm(ctx, simulatereq)
Kent Hagerman2b216042020-04-03 18:28:56 -04001489 logger.Debugw("SimulateAlarm-result", log.Fields{"result": res})
serkant.uluderya334479d2019-04-10 08:26:15 -07001490 }
1491 //TODO CLI always get successful response
1492 sendResponse(ctx, ch, res)
1493}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001494
Kent Hagerman2b216042020-04-03 18:28:56 -04001495func (dMgr *Manager) UpdateDeviceReason(ctx context.Context, deviceID string, reason string) error {
1496 logger.Debugw("UpdateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301497 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1498 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001499 }
npujar1d86a522019-11-14 17:11:16 +05301500 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001501}
kesavandbc2d1622020-01-21 00:42:01 -05001502
Kent Hagerman2b216042020-04-03 18:28:56 -04001503func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1504 logger.Debugw("EnablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001505 var res interface{}
1506 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1507 res = agent.enablePort(ctx, port)
Kent Hagerman2b216042020-04-03 18:28:56 -04001508 logger.Debugw("EnablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001509 } else {
1510 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1511 }
1512
1513 sendResponse(ctx, ch, res)
1514}
1515
Kent Hagerman2b216042020-04-03 18:28:56 -04001516func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1517 logger.Debugw("DisablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001518 var res interface{}
1519 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1520 res = agent.disablePort(ctx, port)
Kent Hagerman2b216042020-04-03 18:28:56 -04001521 logger.Debugw("DisablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001522 } else {
1523 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1524 }
1525
1526 sendResponse(ctx, ch, res)
1527}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001528
Kent Hagerman2b216042020-04-03 18:28:56 -04001529// ChildDeviceLost calls parent adapter to delete child device and all its references
1530func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001531 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001532 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001533 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1534 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001535 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001536 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001537 }
khenaidooe132f522020-03-20 15:23:15 -04001538 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1539 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001540}
onkarkundargi87285252020-01-27 11:34:52 +05301541
Kent Hagerman2b216042020-04-03 18:28:56 -04001542func (dMgr *Manager) StartOmciTest(ctx context.Context, omcitestrequest *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001543 logger.Debugw("Omci_test_Request", log.Fields{"device-id": omcitestrequest.Id, "uuid": omcitestrequest.Uuid})
onkarkundargi87285252020-01-27 11:34:52 +05301544 if agent := dMgr.getDeviceAgent(ctx, omcitestrequest.Id); agent != nil {
1545 res, err := agent.startOmciTest(ctx, omcitestrequest)
1546 if err != nil {
1547 return nil, err
1548 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001549 logger.Debugw("Omci_test_Response_result-device-magnager", log.Fields{"result": res})
onkarkundargi87285252020-01-27 11:34:52 +05301550 return res, nil
1551 }
1552 return nil, status.Errorf(codes.NotFound, "%s", omcitestrequest.Id)
1553}