blob: ad2af573ee1abb33c238cf9b1d6aeb5a614f048c [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
khenaidoo787224a2020-04-16 18:08:47 -0400767// deleteParentFlows removes flows from the parent device based on specific attributes
768func (dMgr *Manager) deleteParentFlows(ctx context.Context, deviceID string, uniPort uint32, metadata *voltha.FlowMetadata) error {
769 logger.Debugw("deleteParentFlows", log.Fields{"device-id": deviceID, "uni-port": uniPort, "metadata": metadata})
770 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
771 if !agent.isRootdevice {
772 return status.Errorf(codes.FailedPrecondition, "not-a-parent-device-%s", deviceID)
773 }
774 return agent.filterOutFlows(ctx, uniPort, metadata)
775 }
776 return status.Errorf(codes.NotFound, "%s", deviceID)
777}
778
Kent Hagerman2b216042020-04-03 18:28:56 -0400779func (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 +0000780 logger.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530781 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
782 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400783 }
npujar1d86a522019-11-14 17:11:16 +0530784 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400785}
786
Kent Hagerman2b216042020-04-03 18:28:56 -0400787func (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 +0000788 logger.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530789 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
790 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400791 }
npujar1d86a522019-11-14 17:11:16 +0530792 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400793}
794
Kent Hagerman2b216042020-04-03 18:28:56 -0400795// UpdatePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
khenaidoob3127472019-07-24 21:04:55 -0400796// following a user action
Kent Hagerman2b216042020-04-03 18:28:56 -0400797func (dMgr *Manager) UpdatePmConfigs(ctx context.Context, pmConfigs *voltha.PmConfigs, ch chan interface{}) {
khenaidoob3127472019-07-24 21:04:55 -0400798 var res interface{}
799 if pmConfigs.Id == "" {
800 res = status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
npujar467fe752020-01-16 20:17:45 +0530801 } else if agent := dMgr.getDeviceAgent(ctx, pmConfigs.Id); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400802 res = agent.updatePmConfigs(ctx, pmConfigs)
803 } else {
804 res = status.Errorf(codes.NotFound, "%s", pmConfigs.Id)
805 }
806 sendResponse(ctx, ch, res)
807}
808
Kent Hagerman2b216042020-04-03 18:28:56 -0400809// InitPmConfigs initialize the pm configs as defined by the adapter.
810func (dMgr *Manager) InitPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400811 if pmConfigs.Id == "" {
812 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
813 }
npujar467fe752020-01-16 20:17:45 +0530814 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
815 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400816 }
npujar1d86a522019-11-14 17:11:16 +0530817 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400818}
819
Kent Hagerman2b216042020-04-03 18:28:56 -0400820func (dMgr *Manager) ListPmConfigs(ctx context.Context, deviceID string) (*voltha.PmConfigs, error) {
npujar467fe752020-01-16 20:17:45 +0530821 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob3127472019-07-24 21:04:55 -0400822 return agent.listPmConfigs(ctx)
823 }
npujar1d86a522019-11-14 17:11:16 +0530824 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob3127472019-07-24 21:04:55 -0400825}
826
Kent Hagerman2b216042020-04-03 18:28:56 -0400827func (dMgr *Manager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000828 logger.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530829 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400830 return agent.getSwitchCapability(ctx)
831 }
npujar1d86a522019-11-14 17:11:16 +0530832 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400833}
834
Kent Hagerman2b216042020-04-03 18:28:56 -0400835func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
836 logger.Debugw("GetPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530837 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400838 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400839 }
npujar1d86a522019-11-14 17:11:16 +0530840 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400841}
842
Kent Hagerman2b216042020-04-03 18:28:56 -0400843func (dMgr *Manager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000844 logger.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530845 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400846 return agent.getPortCapability(ctx, portNo)
847 }
npujar1d86a522019-11-14 17:11:16 +0530848 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400849}
850
Kent Hagerman2b216042020-04-03 18:28:56 -0400851func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
852 logger.Debugw("UpdateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530853 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
854 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400855 }
npujar1d86a522019-11-14 17:11:16 +0530856 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400857}
858
Kent Hagerman2b216042020-04-03 18:28:56 -0400859func (dMgr *Manager) UpdateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
860 logger.Debugw("UpdateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400861 var parentDevice *voltha.Device
862 var err error
npujar467fe752020-01-16 20:17:45 +0530863 if parentDevice, err = dMgr.GetDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400864 return status.Errorf(codes.Aborted, "%s", err.Error())
865 }
866 var childDeviceIds []string
867 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
868 return status.Errorf(codes.Aborted, "%s", err.Error())
869 }
870 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000871 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400872 }
npujar1d86a522019-11-14 17:11:16 +0530873 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530874 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
875 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530876 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400877 }
878 }
879 }
880 return nil
881}
882
Kent Hagerman2b216042020-04-03 18:28:56 -0400883func (dMgr *Manager) UpdatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
884 logger.Debugw("UpdatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530885 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
886 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000887 logger.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400888 return err
889 }
890 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800891 // Do this for NNI and UNIs only. PON ports are not known by logical device
892 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
893 go func() {
894 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
895 if err != nil {
896 // While we want to handle (catch) and log when
897 // an update to a port was not able to be
898 // propagated to the logical port, we can report
899 // it as a warning and not an error because it
900 // doesn't stop or modify processing.
901 // TODO: VOL-2707
Girish Kumarf56a4682020-03-20 20:07:46 +0000902 logger.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800903 }
904 }()
905 }
khenaidoo442e7c72020-03-10 16:13:48 -0400906 return nil
khenaidoob9203542018-09-17 22:56:37 -0400907 }
npujar1d86a522019-11-14 17:11:16 +0530908 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400909}
910
Kent Hagerman2b216042020-04-03 18:28:56 -0400911func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000912 logger.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530913 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
914 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400915 return err
916 }
917 // Notify the logical device manager to remove all logical ports, if needed.
Kent Hagerman2b216042020-04-03 18:28:56 -0400918 // At this stage the device itself may gave been deleted already at a DeleteAllPorts
khenaidoo0a822f92019-05-08 15:15:57 -0400919 // typically is part of a device deletion phase.
npujar467fe752020-01-16 20:17:45 +0530920 if device, err := dMgr.GetDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530921 go func() {
npujar467fe752020-01-16 20:17:45 +0530922 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530923 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000924 logger.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530925 }
926 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400927 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000928 logger.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400929 return err
930 }
931 return nil
932 }
npujar1d86a522019-11-14 17:11:16 +0530933 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400934}
935
Kent Hagerman2b216042020-04-03 18:28:56 -0400936//UpdatePortsState updates all ports on the device
937func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
938 logger.Debugw("UpdatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400939
npujar467fe752020-01-16 20:17:45 +0530940 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400941 switch state {
942 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500943 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000944 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400945 return err
946 }
947 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500948 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000949 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400950 return err
951 }
952 default:
953 return status.Error(codes.Unimplemented, "state-change-not-implemented")
954 }
955 // Notify the logical device about the state change
npujar467fe752020-01-16 20:17:45 +0530956 device, err := dMgr.GetDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530957 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000958 logger.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400959 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400960 }
kesavandbc2d1622020-01-21 00:42:01 -0500961 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000962 logger.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530963 return err
964 }
965 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400966 }
npujar1d86a522019-11-14 17:11:16 +0530967 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400968}
969
Kent Hagerman2b216042020-04-03 18:28:56 -0400970func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530971 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -0400972 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 -0700973
npujar1d86a522019-11-14 17:11:16 +0530974 if deviceType == "" && vendorID != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000975 logger.Debug("device-type-is-nil-fetching-device-type")
Kent Hagerman4f355f52020-03-30 16:01:33 -0400976 OLoop:
Kent Hagerman2b216042020-04-03 18:28:56 -0400977 for _, dType := range dMgr.adapterMgr.ListDeviceTypes() {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400978 for _, v := range dType.VendorIds {
979 if v == vendorID {
980 deviceType = dType.Adapter
981 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700982 }
983 }
984 }
985 }
986 //if no match found for the vendorid,report adapter with the custom error message
987 if deviceType == "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000988 logger.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +0530989 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700990 }
khenaidoob9203542018-09-17 22:56:37 -0400991
992 // Create the ONU device
993 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400994 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +0530995 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -0400996 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +0530997 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -0500998 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -0400999 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001000
khenaidoo442e7c72020-03-10 16:13:48 -04001001 // Get parent device type
1002 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
1003 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +05301004 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001005 }
khenaidoo442e7c72020-03-10 16:13:48 -04001006 if pAgent.deviceType == "" {
1007 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
1008 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001009
npujar467fe752020-01-16 20:17:45 +05301010 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001011 logger.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001012 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001013 }
1014
khenaidoo442e7c72020-03-10 16:13:48 -04001015 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001016
1017 // Create and start a device agent for that device
Kent Hagerman2b216042020-04-03 18:28:56 -04001018 agent := newAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -04001019 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001020 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001021 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 -08001022 return nil, err
1023 }
khenaidoo442e7c72020-03-10 16:13:48 -04001024 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001025
1026 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301027 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301028 go func() {
npujar467fe752020-01-16 20:17:45 +05301029 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301030 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001031 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301032 }
1033 }()
khenaidoob9203542018-09-17 22:56:37 -04001034 }
1035
khenaidoo79232702018-12-04 11:00:41 -05001036 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301037 go func() {
1038 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1039 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001040 logger.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301041 }
1042 }()
khenaidoo79232702018-12-04 11:00:41 -05001043
Scott Baker80678602019-11-14 16:57:36 -08001044 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001045}
1046
Kent Hagerman2b216042020-04-03 18:28:56 -04001047func (dMgr *Manager) processTransition(ctx context.Context, device *voltha.Device, previousState *deviceState) error {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001048 // This will be triggered on every state update
1049 logger.Debugw("state-transition", log.Fields{
1050 "device": device.Id,
1051 "prev-admin-state": previousState.Admin,
1052 "prev-oper-state": previousState.Operational,
1053 "prev-conn-state": previousState.Connection,
1054 "curr-admin-state": device.AdminState,
1055 "curr-oper-state": device.OperStatus,
1056 "curr-conn-state": device.ConnectStatus,
1057 })
1058 handlers := dMgr.stateTransitions.GetTransitionHandler(device, previousState)
khenaidoo92e62c52018-10-03 14:02:54 -04001059 if handlers == nil {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001060 logger.Debugw("no-op-transition", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001061 return nil
khenaidoob9203542018-09-17 22:56:37 -04001062 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001063 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 -04001064 for _, handler := range handlers {
Girish Kumarf56a4682020-03-20 20:07:46 +00001065 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001066 if err := handler(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001067 logger.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001068 return err
1069 }
1070 }
khenaidoob9203542018-09-17 22:56:37 -04001071 return nil
1072}
1073
Kent Hagerman2b216042020-04-03 18:28:56 -04001074func (dMgr *Manager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001075 logger.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301076 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1077 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001078 }
npujar1d86a522019-11-14 17:11:16 +05301079 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001080}
1081
npujar1d86a522019-11-14 17:11:16 +05301082// PacketIn receives packet from adapter
Kent Hagerman2b216042020-04-03 18:28:56 -04001083func (dMgr *Manager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001084 logger.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001085 // Get the logical device Id based on the deviceId
1086 var device *voltha.Device
1087 var err error
npujar467fe752020-01-16 20:17:45 +05301088 if device, err = dMgr.GetDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001089 logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001090 return err
1091 }
khenaidoo43c82122018-11-22 18:38:28 -05001092 if !device.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +00001093 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301094 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001095 }
1096
npujar467fe752020-01-16 20:17:45 +05301097 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001098 return err
1099 }
1100 return nil
1101}
1102
Kent Hagerman2b216042020-04-03 18:28:56 -04001103func (dMgr *Manager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001104 logger.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301105 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1106 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001107 }
1108 return status.Errorf(codes.NotFound, "%s", device.Id)
1109}
1110
npujar1d86a522019-11-14 17:11:16 +05301111// CreateLogicalDevice creates logical device in core
Kent Hagerman2b216042020-04-03 18:28:56 -04001112func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001113 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001114 // Verify whether the logical device has already been created
1115 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001116 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001117 return nil
1118 }
khenaidoob9203542018-09-17 22:56:37 -04001119 var err error
npujar467fe752020-01-16 20:17:45 +05301120 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001121 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001122 return err
1123 }
khenaidoob9203542018-09-17 22:56:37 -04001124 return nil
1125}
1126
npujar1d86a522019-11-14 17:11:16 +05301127// DeleteLogicalDevice deletes logical device from core
Kent Hagerman2b216042020-04-03 18:28:56 -04001128func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001129 logger.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001130 var err error
npujar467fe752020-01-16 20:17:45 +05301131 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001132 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001133 return err
1134 }
1135 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301136 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301137 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001138 return nil
1139}
1140
npujar1d86a522019-11-14 17:11:16 +05301141// DeleteLogicalPort removes the logical port associated with a device
Kent Hagerman2b216042020-04-03 18:28:56 -04001142func (dMgr *Manager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001143 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001144 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001145 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301146 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301147 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001148 logger.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001149 return err
1150 }
npujar467fe752020-01-16 20:17:45 +05301151 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001152 logger.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001153 return err
1154 }
khenaidoo92e62c52018-10-03 14:02:54 -04001155 return nil
1156}
1157
npujar1d86a522019-11-14 17:11:16 +05301158// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagerman2b216042020-04-03 18:28:56 -04001159func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001160 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001161 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001162 // 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 +00001163 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001164 }
1165 return nil
1166}
1167
Kent Hagerman2b216042020-04-03 18:28:56 -04001168func (dMgr *Manager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001169 // Sanity check
1170 if childDevice.Root {
1171 // childDevice is the parent device
1172 return childDevice
1173 }
npujar467fe752020-01-16 20:17:45 +05301174 parentDevice, _ := dMgr.GetDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001175 return parentDevice
1176}
1177
Kent Hagerman2b216042020-04-03 18:28:56 -04001178//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 -04001179//cannot manage the child devices. This will trigger the Core to disable all the child devices.
Kent Hagerman2b216042020-04-03 18:28:56 -04001180func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
1181 logger.Debug("ChildDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001182 var err error
1183 var parentDevice *voltha.Device
npujar467fe752020-01-16 20:17:45 +05301184 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001185 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001186 return err
1187 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001188 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001189}
1190
Kent Hagerman2b216042020-04-03 18:28:56 -04001191//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
khenaidoo0a822f92019-05-08 15:15:57 -04001192// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
Kent Hagerman2b216042020-04-03 18:28:56 -04001193func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
1194 logger.Debug("ChildDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001195 var err error
1196 var parentDevice *voltha.Device
1197 var childDeviceIds []string
1198
npujar467fe752020-01-16 20:17:45 +05301199 if parentDevice, err = dMgr.GetDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001200 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001201 return err
1202 }
1203
1204 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1205 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1206 }
1207 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001208 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001209 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001210 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301211 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301212 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001213 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301214 go func() {
npujar467fe752020-01-16 20:17:45 +05301215 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301216 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001217 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301218 }
1219 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001220 } else {
npujar1d86a522019-11-14 17:11:16 +05301221 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Girish Kumarf56a4682020-03-20 20:07:46 +00001222 logger.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001223 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001224 }
1225 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001226 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001227 return err
1228 }
1229 return nil
1230}
1231
khenaidoo4d4802d2018-10-04 21:59:49 -04001232/*
1233All the functions below are callback functions where they are invoked with the latest and previous data. We can
1234therefore use the data as is without trying to get the latest from the model.
1235*/
1236
khenaidoo0a822f92019-05-08 15:15:57 -04001237//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagerman2b216042020-04-03 18:28:56 -04001238func (dMgr *Manager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001239 logger.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001240 var childDeviceIds []string
1241 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001242 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1243 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001244 }
1245 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001246 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001247 }
npujar1d86a522019-11-14 17:11:16 +05301248 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301249 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1250 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001251 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001252 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001253 }
1254 }
1255 }
1256 return nil
1257}
1258
khenaidoo0a822f92019-05-08 15:15:57 -04001259//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001260func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001261 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001262 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001263 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001264 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1265 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001266 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001267 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001268 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001269 }
npujar1d86a522019-11-14 17:11:16 +05301270 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301271 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1272 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001273 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001274 }
khenaidoo49085352020-01-13 19:15:43 -05001275 // No further action is required here. The deleteDevice will change the device state where the resulting
1276 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001277 }
1278 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001279 return nil
1280}
1281
Hardik Windlassc704def2020-02-26 18:23:19 +00001282//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001283func (dMgr *Manager) DeleteAllUNILogicalPorts(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001284 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": curr.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001285 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, curr); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001286 // Just log the error and let the remaining pipeline proceed - ports may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001287 logger.Warnw("delete-all-uni-logical-ports-failed", log.Fields{"parent-device-id": curr.Id, "error": err})
Hardik Windlassc704def2020-02-26 18:23:19 +00001288 }
1289 return nil
1290}
1291
Girish Gowdra408cd962020-03-11 14:31:31 -07001292//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001293func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001294 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001295 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001296 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001297 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001298 }
1299 return nil
1300}
1301
1302//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001303func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001304 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001305 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1306 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001307 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001308 return err
1309 }
1310 return nil
1311 }
1312 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1313}
1314
khenaidoo4d4802d2018-10-04 21:59:49 -04001315//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 -04001316func (dMgr *Manager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001317 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001318 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001319 if parentDevice != nil {
1320 for _, port := range parentDevice.Ports {
1321 for _, peer := range port.Peers {
1322 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1323 }
khenaidoo92e62c52018-10-03 14:02:54 -04001324 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001325 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001326 }
1327 return childDeviceIds, nil
1328}
1329
Kent Hagerman2b216042020-04-03 18:28:56 -04001330//GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1331func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
1332 logger.Debugw("GetAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
npujar467fe752020-01-16 20:17:45 +05301333 if parentDevice, err := dMgr.GetDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001334 childDevices := make([]*voltha.Device, 0)
1335 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301336 for _, deviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301337 if d, e := dMgr.GetDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001338 childDevices = append(childDevices, d)
1339 }
1340 }
1341 }
1342 return &voltha.Devices{Items: childDevices}, nil
1343 }
npujar1d86a522019-11-14 17:11:16 +05301344 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001345}
1346
npujar1d86a522019-11-14 17:11:16 +05301347// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagerman2b216042020-04-03 18:28:56 -04001348func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001349 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301350 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001351 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001352 return err
1353 }
1354 return nil
1355}
1356
Kent Hagerman2b216042020-04-03 18:28:56 -04001357func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1358 logger.Debugw("DownloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001359 var res interface{}
1360 var err error
npujar467fe752020-01-16 20:17:45 +05301361 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001362 if res, err = agent.downloadImage(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001363 logger.Debugw("DownloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001364 res = err
1365 }
1366 } else {
1367 res = status.Errorf(codes.NotFound, "%s", img.Id)
1368 }
1369 sendResponse(ctx, ch, res)
1370}
1371
Kent Hagerman2b216042020-04-03 18:28:56 -04001372func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1373 logger.Debugw("CancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001374 var res interface{}
1375 var err error
npujar467fe752020-01-16 20:17:45 +05301376 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001377 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001378 logger.Debugw("CancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001379 res = err
1380 }
1381 } else {
1382 res = status.Errorf(codes.NotFound, "%s", img.Id)
1383 }
1384 sendResponse(ctx, ch, res)
1385}
1386
Kent Hagerman2b216042020-04-03 18:28:56 -04001387func (dMgr *Manager) ActivateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1388 logger.Debugw("ActivateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001389 var res interface{}
1390 var err error
npujar467fe752020-01-16 20:17:45 +05301391 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001392 if res, err = agent.activateImage(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001393 logger.Debugw("ActivateImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001394 res = err
1395 }
1396 } else {
1397 res = status.Errorf(codes.NotFound, "%s", img.Id)
1398 }
1399 sendResponse(ctx, ch, res)
1400}
1401
Kent Hagerman2b216042020-04-03 18:28:56 -04001402func (dMgr *Manager) RevertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1403 logger.Debugw("RevertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001404 var res interface{}
1405 var err error
npujar467fe752020-01-16 20:17:45 +05301406 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001407 if res, err = agent.revertImage(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001408 logger.Debugw("RevertImage-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001409 res = err
1410 }
1411 } else {
1412 res = status.Errorf(codes.NotFound, "%s", img.Id)
1413 }
1414 sendResponse(ctx, ch, res)
1415}
1416
Kent Hagerman2b216042020-04-03 18:28:56 -04001417func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
1418 logger.Debugw("GetImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001419 var res interface{}
1420 var err error
npujar467fe752020-01-16 20:17:45 +05301421 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001422 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001423 logger.Debugw("GetImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001424 res = err
1425 }
1426 } else {
1427 res = status.Errorf(codes.NotFound, "%s", img.Id)
1428 }
1429 sendResponse(ctx, ch, res)
1430}
1431
Kent Hagerman2b216042020-04-03 18:28:56 -04001432func (dMgr *Manager) UpdateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
1433 logger.Debugw("UpdateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301434 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1435 if err := agent.updateImageDownload(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001436 logger.Debugw("UpdateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001437 return err
1438 }
1439 } else {
1440 return status.Errorf(codes.NotFound, "%s", img.Id)
1441 }
1442 return nil
1443}
1444
Kent Hagerman2b216042020-04-03 18:28:56 -04001445func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1446 logger.Debugw("GetImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301447 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
khenaidoof5a5bfa2019-01-23 22:20:29 -05001448 return agent.getImageDownload(ctx, img)
1449 }
1450 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
1451}
1452
Kent Hagerman2b216042020-04-03 18:28:56 -04001453func (dMgr *Manager) ListImageDownloads(ctx context.Context, deviceID string) (*voltha.ImageDownloads, error) {
1454 logger.Debugw("ListImageDownloads", log.Fields{"deviceID": deviceID})
npujar467fe752020-01-16 20:17:45 +05301455 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301456 return agent.listImageDownloads(ctx, deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001457 }
npujar1d86a522019-11-14 17:11:16 +05301458 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001459}
1460
Kent Hagerman2b216042020-04-03 18:28:56 -04001461func (dMgr *Manager) NotifyInvalidTransition(_ context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001462 logger.Errorw("NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001463 "device": device.Id,
1464 "curr-admin-state": device.AdminState,
1465 "curr-oper-state": device.OperStatus,
1466 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001467 })
khenaidoo0a822f92019-05-08 15:15:57 -04001468 //TODO: notify over kafka?
1469 return nil
1470}
1471
khenaidoob9203542018-09-17 22:56:37 -04001472func funcName(f interface{}) string {
1473 p := reflect.ValueOf(f).Pointer()
1474 rf := runtime.FuncForPC(p)
1475 return rf.Name()
1476}
1477
npujar1d86a522019-11-14 17:11:16 +05301478// UpdateDeviceAttribute updates value of particular device attribute
Kent Hagerman2b216042020-04-03 18:28:56 -04001479func (dMgr *Manager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301480 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -04001481 agent.(*Agent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001482 }
1483}
1484
npujar1d86a522019-11-14 17:11:16 +05301485// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -04001486func (dMgr *Manager) GetParentDeviceID(ctx context.Context, deviceID string) string {
npujar467fe752020-01-16 20:17:45 +05301487 if device, _ := dMgr.GetDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001488 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001489 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001490 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001491 return ""
khenaidoob9203542018-09-17 22:56:37 -04001492}
serkant.uluderya334479d2019-04-10 08:26:15 -07001493
Kent Hagerman2b216042020-04-03 18:28:56 -04001494func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulatereq *voltha.SimulateAlarmRequest, ch chan interface{}) {
1495 logger.Debugw("SimulateAlarm", log.Fields{"id": simulatereq.Id, "Indicator": simulatereq.Indicator, "IntfId": simulatereq.IntfId,
serkant.uluderya334479d2019-04-10 08:26:15 -07001496 "PortTypeName": simulatereq.PortTypeName, "OnuDeviceId": simulatereq.OnuDeviceId, "InverseBitErrorRate": simulatereq.InverseBitErrorRate,
1497 "Drift": simulatereq.Drift, "NewEqd": simulatereq.NewEqd, "OnuSerialNumber": simulatereq.OnuSerialNumber, "Operation": simulatereq.Operation})
1498 var res interface{}
npujar467fe752020-01-16 20:17:45 +05301499 if agent := dMgr.getDeviceAgent(ctx, simulatereq.Id); agent != nil {
serkant.uluderya334479d2019-04-10 08:26:15 -07001500 res = agent.simulateAlarm(ctx, simulatereq)
Kent Hagerman2b216042020-04-03 18:28:56 -04001501 logger.Debugw("SimulateAlarm-result", log.Fields{"result": res})
serkant.uluderya334479d2019-04-10 08:26:15 -07001502 }
1503 //TODO CLI always get successful response
1504 sendResponse(ctx, ch, res)
1505}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001506
Kent Hagerman2b216042020-04-03 18:28:56 -04001507func (dMgr *Manager) UpdateDeviceReason(ctx context.Context, deviceID string, reason string) error {
1508 logger.Debugw("UpdateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301509 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1510 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001511 }
npujar1d86a522019-11-14 17:11:16 +05301512 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001513}
kesavandbc2d1622020-01-21 00:42:01 -05001514
Kent Hagerman2b216042020-04-03 18:28:56 -04001515func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1516 logger.Debugw("EnablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001517 var res interface{}
1518 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1519 res = agent.enablePort(ctx, port)
Kent Hagerman2b216042020-04-03 18:28:56 -04001520 logger.Debugw("EnablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001521 } else {
1522 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1523 }
1524
1525 sendResponse(ctx, ch, res)
1526}
1527
Kent Hagerman2b216042020-04-03 18:28:56 -04001528func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port, ch chan interface{}) {
1529 logger.Debugw("DisablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
kesavandbc2d1622020-01-21 00:42:01 -05001530 var res interface{}
1531 if agent := dMgr.getDeviceAgent(ctx, port.DeviceId); agent != nil {
1532 res = agent.disablePort(ctx, port)
Kent Hagerman2b216042020-04-03 18:28:56 -04001533 logger.Debugw("DisablePort-result", log.Fields{"result": res})
kesavandbc2d1622020-01-21 00:42:01 -05001534 } else {
1535 res = status.Errorf(codes.NotFound, "%s", port.DeviceId)
1536 }
1537
1538 sendResponse(ctx, ch, res)
1539}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001540
Kent Hagerman2b216042020-04-03 18:28:56 -04001541// ChildDeviceLost calls parent adapter to delete child device and all its references
1542func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001543 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001544 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001545 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1546 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001547 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001548 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001549 }
khenaidooe132f522020-03-20 15:23:15 -04001550 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1551 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001552}
onkarkundargi87285252020-01-27 11:34:52 +05301553
Kent Hagerman2b216042020-04-03 18:28:56 -04001554func (dMgr *Manager) StartOmciTest(ctx context.Context, omcitestrequest *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001555 logger.Debugw("Omci_test_Request", log.Fields{"device-id": omcitestrequest.Id, "uuid": omcitestrequest.Uuid})
onkarkundargi87285252020-01-27 11:34:52 +05301556 if agent := dMgr.getDeviceAgent(ctx, omcitestrequest.Id); agent != nil {
1557 res, err := agent.startOmciTest(ctx, omcitestrequest)
1558 if err != nil {
1559 return nil, err
1560 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001561 logger.Debugw("Omci_test_Response_result-device-magnager", log.Fields{"result": res})
onkarkundargi87285252020-01-27 11:34:52 +05301562 return res, nil
1563 }
1564 return nil, status.Errorf(codes.NotFound, "%s", omcitestrequest.Id)
1565}
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001566
1567func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
1568 log.Debugw("getExtValue", log.Fields{"onu-id": value.Id})
1569 cDevice, err := dMgr.GetDevice(ctx, value.Id)
1570 if err != nil {
1571 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1572 }
1573 pDevice, err := dMgr.GetDevice(ctx, cDevice.ParentId)
1574 if err != nil {
1575 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1576 }
1577 if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
1578 resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
1579 if err != nil {
1580 return nil, err
1581 }
1582 log.Debugw("getExtValue-result", log.Fields{"result": resp})
1583 return resp, nil
1584 }
1585 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1586
1587}