blob: b0128a589c99568759c171a6e3a9a838036f6bac [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"
Kent Hagerman45a13e42020-04-13 12:23:50 -040022 "github.com/opencord/voltha-go/rw_core/core/device/event"
David Bainbridged1afd662020-03-26 18:27:41 -070023 "reflect"
24 "runtime"
25 "sync"
26 "time"
27
Kent Hagerman45a13e42020-04-13 12:23:50 -040028 "github.com/golang/protobuf/ptypes/empty"
sbarbari17d7e222019-11-05 10:02:29 -050029 "github.com/opencord/voltha-go/db/model"
Kent Hagerman2b216042020-04-03 18:28:56 -040030 "github.com/opencord/voltha-go/rw_core/core/adapter"
31 "github.com/opencord/voltha-go/rw_core/core/device/remote"
khenaidoo3d3b8c22019-05-22 18:10:39 -040032 "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080033 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
34 "github.com/opencord/voltha-lib-go/v3/pkg/log"
35 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
Kent Hagerman45a13e42020-04-13 12:23:50 -040036 "github.com/opencord/voltha-protos/v3/go/common"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080037 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
39 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040040 "google.golang.org/grpc/codes"
41 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040042)
43
Kent Hagerman2b216042020-04-03 18:28:56 -040044// Manager represent device manager attributes
45type Manager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040046 deviceAgents sync.Map
47 rootDevices map[string]bool
48 lockRootDeviceMap sync.RWMutex
Kent Hagerman2b216042020-04-03 18:28:56 -040049 adapterProxy *remote.AdapterProxy
50 adapterMgr *adapter.Manager
51 logicalDeviceMgr *LogicalManager
npujar467fe752020-01-16 20:17:45 +053052 kafkaICProxy kafka.InterContainerProxy
khenaidoo4c9e5592019-09-09 16:20:41 -040053 stateTransitions *TransitionMap
54 clusterDataProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053055 coreInstanceID string
khenaidoo4c9e5592019-09-09 16:20:41 -040056 exitChannel chan int
khenaidoo442e7c72020-03-10 16:13:48 -040057 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040058 devicesLoadingLock sync.RWMutex
59 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040060}
61
Kent Hagerman45a13e42020-04-13 12:23:50 -040062func NewManagers(proxy *model.Proxy, adapterMgr *adapter.Manager, kmp kafka.InterContainerProxy, endpointMgr kafka.EndpointManager, corePairTopic, coreInstanceID string, defaultCoreTimeout time.Duration) (*Manager, *LogicalManager) {
Kent Hagerman2b216042020-04-03 18:28:56 -040063 deviceMgr := &Manager{
64 exitChannel: make(chan int, 1),
65 rootDevices: make(map[string]bool),
66 kafkaICProxy: kmp,
67 adapterProxy: remote.NewAdapterProxy(kmp, corePairTopic, endpointMgr),
68 coreInstanceID: coreInstanceID,
69 clusterDataProxy: proxy,
70 adapterMgr: adapterMgr,
71 defaultTimeout: defaultCoreTimeout * time.Millisecond,
72 deviceLoadingInProgress: make(map[string][]chan int),
73 }
74 logicalDeviceMgr := &LogicalManager{
Kent Hagerman45a13e42020-04-13 12:23:50 -040075 Manager: event.NewManager(),
Kent Hagerman2b216042020-04-03 18:28:56 -040076 exitChannel: make(chan int, 1),
77 deviceMgr: deviceMgr,
78 kafkaICProxy: kmp,
79 clusterDataProxy: proxy,
80 defaultTimeout: defaultCoreTimeout,
81 logicalDeviceLoadingInProgress: make(map[string][]chan int),
82 }
83 deviceMgr.logicalDeviceMgr = logicalDeviceMgr
Matteo Scandolod525ae32020-04-02 17:27:29 -070084
Kent Hagerman2b216042020-04-03 18:28:56 -040085 adapterMgr.SetAdapterRestartedCallback(deviceMgr.adapterRestarted)
Matteo Scandolod525ae32020-04-02 17:27:29 -070086
Kent Hagerman2b216042020-04-03 18:28:56 -040087 return deviceMgr, logicalDeviceMgr
khenaidoob9203542018-09-17 22:56:37 -040088}
89
Kent Hagerman2b216042020-04-03 18:28:56 -040090func (dMgr *Manager) Start(ctx context.Context) {
Girish Kumarf56a4682020-03-20 20:07:46 +000091 logger.Info("starting-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040092 dMgr.stateTransitions = NewTransitionMap(dMgr)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070093 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
Girish Kumarf56a4682020-03-20 20:07:46 +000094 logger.Info("device-manager-started")
khenaidoob9203542018-09-17 22:56:37 -040095}
96
Kent Hagerman2b216042020-04-03 18:28:56 -040097func (dMgr *Manager) Stop(ctx context.Context) {
Girish Kumarf56a4682020-03-20 20:07:46 +000098 logger.Info("stopping-device-manager")
khenaidoob9203542018-09-17 22:56:37 -040099 dMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -0700100 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusStopped)
Girish Kumarf56a4682020-03-20 20:07:46 +0000101 logger.Info("device-manager-stopped")
khenaidoob9203542018-09-17 22:56:37 -0400102}
103
Kent Hagerman2b216042020-04-03 18:28:56 -0400104func (dMgr *Manager) addDeviceAgentToMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +0530105 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
106 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -0400107 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400108 dMgr.lockRootDeviceMap.Lock()
109 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530110 dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400111
khenaidoob9203542018-09-17 22:56:37 -0400112}
113
Kent Hagerman2b216042020-04-03 18:28:56 -0400114func (dMgr *Manager) deleteDeviceAgentFromMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +0530115 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400116 dMgr.lockRootDeviceMap.Lock()
117 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530118 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400119}
120
khenaidoo297cd252019-02-07 22:10:23 -0500121// 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 -0400122func (dMgr *Manager) getDeviceAgent(ctx context.Context, deviceID string) *Agent {
npujar1d86a522019-11-14 17:11:16 +0530123 agent, ok := dMgr.deviceAgents.Load(deviceID)
124 if ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400125 return agent.(*Agent)
khenaidoob9203542018-09-17 22:56:37 -0400126 }
khenaidoo442e7c72020-03-10 16:13:48 -0400127 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530128 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530129 if err == nil {
130 agent, ok = dMgr.deviceAgents.Load(deviceID)
131 if !ok {
132 return nil
133 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400134 return agent.(*Agent)
npujar1d86a522019-11-14 17:11:16 +0530135 }
136 //TODO: Change the return params to return an error as well
Girish Kumarf56a4682020-03-20 20:07:46 +0000137 logger.Errorw("loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400138 return nil
139}
140
khenaidoo297cd252019-02-07 22:10:23 -0500141// listDeviceIdsFromMap returns the list of device IDs that are in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400142func (dMgr *Manager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500143 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400144
145 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
146 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
147 return true
148 })
149
khenaidoo7ccedd52018-12-14 16:48:54 -0500150 return result
151}
152
Kent Hagerman45a13e42020-04-13 12:23:50 -0400153// CreateDevice creates a new parent device in the data model
154func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
155 if device.MacAddress == "" && device.GetHostAndPort() == "" {
156 logger.Errorf("No Device Info Present")
157 return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
158 }
159 logger.Debugw("create-device", log.Fields{"device": *device})
160
npujar467fe752020-01-16 20:17:45 +0530161 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530162 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000163 logger.Errorf("Failed to fetch parent device info")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400164 return nil, err
Thomas Lee Se5a44012019-11-07 20:32:24 +0530165 }
166 if deviceExist {
Girish Kumarf56a4682020-03-20 20:07:46 +0000167 logger.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400168 return nil, errors.New("device is already pre-provisioned")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530169 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400170 logger.Debugw("CreateDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400171
khenaidoo5e677ae2019-02-28 17:26:29 -0500172 // Ensure this device is set as root
173 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400174 // Create and start a device agent for that device
Kent Hagerman2b216042020-04-03 18:28:56 -0400175 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530176 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800177 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000178 logger.Errorw("Fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400179 return nil, err
Scott Baker80678602019-11-14 16:57:36 -0800180 }
khenaidoo442e7c72020-03-10 16:13:48 -0400181 dMgr.addDeviceAgentToMap(agent)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400182 return device, nil
khenaidoob9203542018-09-17 22:56:37 -0400183}
184
Kent Hagerman45a13e42020-04-13 12:23:50 -0400185// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
186func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
187 logger.Debugw("EnableDevice", log.Fields{"device-id": id.Id})
188 agent := dMgr.getDeviceAgent(ctx, id.Id)
189 if agent == nil {
190 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400191 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400192 return &empty.Empty{}, agent.enableDevice(ctx)
khenaidoob9203542018-09-17 22:56:37 -0400193}
194
Kent Hagerman45a13e42020-04-13 12:23:50 -0400195// DisableDevice disables a device along with any child device it may have
196func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
197 logger.Debugw("DisableDevice", log.Fields{"device-id": id.Id})
198 agent := dMgr.getDeviceAgent(ctx, id.Id)
199 if agent == nil {
200 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400201 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400202 return &empty.Empty{}, agent.disableDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400203}
204
Kent Hagerman45a13e42020-04-13 12:23:50 -0400205//RebootDevice invoked the reboot API to the corresponding adapter
206func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
207 logger.Debugw("RebootDevice", log.Fields{"device-id": id.Id})
208 agent := dMgr.getDeviceAgent(ctx, id.Id)
209 if agent == nil {
210 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400211 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400212 return &empty.Empty{}, agent.rebootDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400213}
214
Kent Hagerman45a13e42020-04-13 12:23:50 -0400215// DeleteDevice removes a device from the data model
216func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
217 logger.Debugw("DeleteDevice", log.Fields{"device-id": id.Id})
218 agent := dMgr.getDeviceAgent(ctx, id.Id)
219 if agent == nil {
220 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400221 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400222 return &empty.Empty{}, agent.deleteDevice(ctx)
223}
224
225// ListDevicePorts returns the ports details for a specific device entry
226func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
227 logger.Debugw("ListDevicePorts", log.Fields{"device-id": id.Id})
228 device, err := dMgr.getDevice(ctx, id.Id)
229 if err != nil {
230 return &voltha.Ports{}, err
231 }
232 return &voltha.Ports{Items: device.Ports}, nil
233}
234
235// ListDeviceFlows returns the flow details for a specific device entry
236func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
237 logger.Debugw("ListDeviceFlows", log.Fields{"device-id": id.Id})
238 device, err := dMgr.getDevice(ctx, id.Id)
239 if err != nil {
240 return &ofp.Flows{}, err
241 }
242 return device.Flows, nil
243}
244
245// ListDeviceFlowGroups returns the flow group details for a specific device entry
246func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*voltha.FlowGroups, error) {
247 logger.Debugw("ListDeviceFlowGroups", log.Fields{"device-id": id.Id})
248
249 device, err := dMgr.getDevice(ctx, id.Id)
250 if err != nil {
251 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
252 }
253 return device.GetFlowGroups(), nil
khenaidoo4d4802d2018-10-04 21:59:49 -0400254}
255
khenaidoo6d62c002019-05-15 21:57:03 -0400256// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
257// This function is called only in the Core that does not own this device. In the Core that owns this device then a
258// deletion deletion also includes removal of any reference of this device.
Kent Hagerman2b216042020-04-03 18:28:56 -0400259func (dMgr *Manager) stopManagingDevice(ctx context.Context, id string) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000260 logger.Infow("stopManagingDevice", log.Fields{"deviceId": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400261 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530262 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400263 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700264 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400265 }
npujar467fe752020-01-16 20:17:45 +0530266 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400267 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000268 logger.Warnw("unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400269 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400270 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400271 }
272 }
273}
274
npujar1d86a522019-11-14 17:11:16 +0530275// RunPostDeviceDelete removes any reference of this device
Kent Hagerman2b216042020-04-03 18:28:56 -0400276func (dMgr *Manager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000277 logger.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530278 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400279 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400280}
281
Kent Hagerman45a13e42020-04-13 12:23:50 -0400282func (dMgr *Manager) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
283 return dMgr.getDevice(ctx, id.Id)
284}
285
286// getDevice will returns a device, either from memory or from the dB, if present
287func (dMgr *Manager) getDevice(ctx context.Context, id string) (*voltha.Device, error) {
288 logger.Debugw("getDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530289 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400290 return agent.getDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400291 }
292 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400293}
294
npujar1d86a522019-11-14 17:11:16 +0530295// GetChildDevice will return a device, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -0400296func (dMgr *Manager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000297 logger.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
npujar1d86a522019-11-14 17:11:16 +0530298 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500299
300 var parentDevice *voltha.Device
301 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400302 if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500303 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
304 }
305 var childDeviceIds []string
306 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
307 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
308 }
309 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000310 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530311 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500312 }
313
314 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530315 for _, childDeviceID := range childDeviceIds {
316 var found bool
Kent Hagerman45a13e42020-04-13 12:23:50 -0400317 if searchDevice, err := dMgr.getDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500318
npujar1d86a522019-11-14 17:11:16 +0530319 foundOnuID := false
320 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500321 if searchDevice.ParentPortNo == uint32(parentPortNo) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000322 logger.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530323 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500324 }
325 }
326
327 foundSerialNumber := false
328 if searchDevice.SerialNumber == serialNumber {
Girish Kumarf56a4682020-03-20 20:07:46 +0000329 logger.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500330 foundSerialNumber = true
331 }
332
333 // if both onuId and serialNumber are provided both must be true for the device to be found
334 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530335 if onuID > 0 && serialNumber != "" {
336 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500337 } else {
npujar1d86a522019-11-14 17:11:16 +0530338 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500339 }
340
npujar1d86a522019-11-14 17:11:16 +0530341 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500342 foundChildDevice = searchDevice
343 break
344 }
345 }
346 }
347
348 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000349 logger.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500350 return foundChildDevice, nil
351 }
352
Girish Kumarf56a4682020-03-20 20:07:46 +0000353 logger.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530354 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
355 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500356}
357
npujar1d86a522019-11-14 17:11:16 +0530358// GetChildDeviceWithProxyAddress will return a device based on proxy address
Kent Hagerman2b216042020-04-03 18:28:56 -0400359func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000360 logger.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500361
362 var parentDevice *voltha.Device
363 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400364 if parentDevice, err = dMgr.getDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500365 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
366 }
367 var childDeviceIds []string
368 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
369 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
370 }
371 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000372 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500373 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
374 }
375
376 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530377 for _, childDeviceID := range childDeviceIds {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400378 if searchDevice, err := dMgr.getDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500379 if searchDevice.ProxyAddress == proxyAddress {
380 foundChildDevice = searchDevice
381 break
382 }
383 }
384 }
385
386 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000387 logger.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500388 return foundChildDevice, nil
389 }
390
Girish Kumarf56a4682020-03-20 20:07:46 +0000391 logger.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500392 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
393}
394
npujar1d86a522019-11-14 17:11:16 +0530395// IsDeviceInCache returns true if device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400396func (dMgr *Manager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400397 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500398 return exist
399}
400
npujar1d86a522019-11-14 17:11:16 +0530401// IsRootDevice returns true if root device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400402func (dMgr *Manager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400403 dMgr.lockRootDeviceMap.RLock()
404 defer dMgr.lockRootDeviceMap.RUnlock()
405 if exist := dMgr.rootDevices[id]; exist {
406 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400407 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400408 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400409}
410
Stephane Barbarieaa467942019-02-06 14:09:44 -0500411// ListDevices retrieves the latest devices from the data model
Kent Hagerman45a13e42020-04-13 12:23:50 -0400412func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000413 logger.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400414 result := &voltha.Devices{}
Kent Hagerman4f355f52020-03-30 16:01:33 -0400415
416 var devices []*voltha.Device
417 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000418 logger.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530419 return nil, err
420 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400421
422 for _, device := range devices {
423 // If device is not in memory then set it up
424 if !dMgr.IsDeviceInCache(device.Id) {
425 logger.Debugw("loading-device-from-Model", log.Fields{"id": device.Id})
Kent Hagerman2b216042020-04-03 18:28:56 -0400426 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Kent Hagerman4f355f52020-03-30 16:01:33 -0400427 if _, err := agent.start(ctx, nil); err != nil {
428 logger.Warnw("failure-starting-agent", log.Fields{"deviceId": device.Id})
429 } else {
430 dMgr.addDeviceAgentToMap(agent)
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500431 }
khenaidoob9203542018-09-17 22:56:37 -0400432 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400433 result.Items = append(result.Items, device)
khenaidoob9203542018-09-17 22:56:37 -0400434 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000435 logger.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400436 return result, nil
437}
438
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530439//isParentDeviceExist checks whether device is already preprovisioned.
Kent Hagerman2b216042020-04-03 18:28:56 -0400440func (dMgr *Manager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530441 hostPort := newDevice.GetHostAndPort()
Kent Hagerman4f355f52020-03-30 16:01:33 -0400442 var devices []*voltha.Device
443 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000444 logger.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530445 return false, err
446 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400447 for _, device := range devices {
448 if !device.Root {
449 continue
450 }
451 if hostPort != "" && hostPort == device.GetHostAndPort() && device.AdminState != voltha.AdminState_DELETED {
452 return true, nil
453 }
454 if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress && device.AdminState != voltha.AdminState_DELETED {
455 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530456 }
457 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530458 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530459}
460
khenaidoo6d62c002019-05-15 21:57:03 -0400461//getDeviceFromModelretrieves the device data from the model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400462func (dMgr *Manager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400463 device := &voltha.Device{}
464 if have, err := dMgr.clusterDataProxy.Get(ctx, "devices/"+deviceID, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000465 logger.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530466 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400467 } else if !have {
468 return nil, status.Error(codes.NotFound, deviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530469 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400470
471 return device, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400472}
473
npujar1d86a522019-11-14 17:11:16 +0530474// loadDevice loads the deviceID in memory, if not present
Kent Hagerman2b216042020-04-03 18:28:56 -0400475func (dMgr *Manager) loadDevice(ctx context.Context, deviceID string) (*Agent, error) {
npujar1d86a522019-11-14 17:11:16 +0530476 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500477 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
478 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400479 var err error
480 var device *voltha.Device
481 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530482 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
483 if !dMgr.IsDeviceInCache(deviceID) {
484 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400485 dMgr.devicesLoadingLock.Unlock()
486 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530487 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000488 logger.Debugw("loading-device", log.Fields{"deviceId": deviceID})
Kent Hagerman2b216042020-04-03 18:28:56 -0400489 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530490 if _, err = agent.start(ctx, nil); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000491 logger.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400492 } else {
493 dMgr.addDeviceAgentToMap(agent)
494 }
495 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000496 logger.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400497 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400498 // announce completion of task to any number of waiting channels
499 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530500 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400501 for _, ch := range v {
502 close(ch)
503 }
npujar1d86a522019-11-14 17:11:16 +0530504 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400505 }
506 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400507 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400508 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500509 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400510 } else {
511 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530512 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400513 dMgr.devicesLoadingLock.Unlock()
514 // Wait for the channel to be closed, implying the process loading this device is done.
515 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500516 }
npujar1d86a522019-11-14 17:11:16 +0530517 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400518 return agent.(*Agent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500519 }
npujar1d86a522019-11-14 17:11:16 +0530520 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500521}
522
523// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400524func (dMgr *Manager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000525 logger.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500526 if device.Root {
527 // Scenario A
528 if device.ParentId != "" {
529 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530530 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000531 logger.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500532 }
533 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000534 logger.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500535 }
536 // Load all child devices, if needed
537 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530538 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530539 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000540 logger.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500541 return err
542 }
543 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000544 logger.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500545 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000546 logger.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500547 }
548 }
549 return nil
550}
551
552// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
553// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
554// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
555// and the proceed with the request.
Kent Hagerman2b216042020-04-03 18:28:56 -0400556func (dMgr *Manager) load(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000557 logger.Debug("load...")
khenaidoo297cd252019-02-07 22:10:23 -0500558 // 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 -0400559 var dAgent *Agent
khenaidoo297cd252019-02-07 22:10:23 -0500560 var err error
npujar467fe752020-01-16 20:17:45 +0530561 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500562 return err
563 }
564 // Get the loaded device details
khenaidoo442e7c72020-03-10 16:13:48 -0400565 device, err := dAgent.getDevice(ctx)
566 if err != nil {
567 return err
568 }
khenaidoo297cd252019-02-07 22:10:23 -0500569
570 // If the device is in Pre-provisioning or deleted state stop here
571 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
572 return nil
573 }
574
575 // Now we face two scenarios
576 if device.Root {
577 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530578 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000579 logger.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500580 return err
581 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000582 logger.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500583 } else {
584 // Scenario B - use the parentId of that device (root device) to trigger the loading
585 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530586 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500587 }
588 }
589 return nil
590}
591
khenaidoo7ccedd52018-12-14 16:48:54 -0500592// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400593func (dMgr *Manager) ListDeviceIds(_ context.Context, _ *empty.Empty) (*voltha.IDs, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000594 logger.Debug("ListDeviceIDs")
khenaidoo7ccedd52018-12-14 16:48:54 -0500595 // Report only device IDs that are in the device agent map
596 return dMgr.listDeviceIdsFromMap(), nil
597}
598
Kent Hagerman45a13e42020-04-13 12:23:50 -0400599// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
600// trigger loading the devices along with their children and parent in memory
601func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000602 logger.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo4c9e5592019-09-09 16:20:41 -0400603 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500604 toReconcile := len(ids.Items)
605 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400606 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500607 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530608 if err = dMgr.load(ctx, id.Id); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000609 logger.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400610 } else {
npujar1d86a522019-11-14 17:11:16 +0530611 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500612 }
613 }
614 if toReconcile != reconciled {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400615 return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500616 }
617 } else {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400618 return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
khenaidoo7ccedd52018-12-14 16:48:54 -0500619 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400620 return &empty.Empty{}, nil
khenaidoo7ccedd52018-12-14 16:48:54 -0500621}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500622
khenaidooba6b6c42019-08-02 09:11:56 -0400623// isOkToReconcile validates whether a device is in the correct status to be reconciled
624func isOkToReconcile(device *voltha.Device) bool {
625 if device == nil {
626 return false
627 }
628 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
629}
630
631// adapterRestarted is invoked whenever an adapter is restarted
Kent Hagerman2b216042020-04-03 18:28:56 -0400632func (dMgr *Manager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Matteo Scandolod525ae32020-04-02 17:27:29 -0700633 logger.Debugw("adapter-restarted", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
634 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidooba6b6c42019-08-02 09:11:56 -0400635
636 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700637 if len(dMgr.rootDevices) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000638 logger.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400639 return nil
640 }
641
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500642 responses := make([]utils.Response, 0)
David Bainbridged1afd662020-03-26 18:27:41 -0700643 for rootDeviceID := range dMgr.rootDevices {
npujar467fe752020-01-16 20:17:45 +0530644 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -0400645 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(rootDeviceID, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700646 if err != nil {
647 logger.Warnw("is-device-owned-by-service", log.Fields{"error": err, "root-device-id": rootDeviceID, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
648 continue
649 }
650 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400651 if isOkToReconcile(rootDevice) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000652 logger.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530653 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400654 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000655 logger.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400656 }
657 } else { // Should we be reconciling the root's children instead?
658 childManagedByAdapter:
659 for _, port := range rootDevice.Ports {
660 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530661 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -0400662 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(childDevice.Id, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700663 if err != nil {
664 logger.Warnw("is-device-owned-by-service", log.Fields{"error": err, "child-device-id": childDevice.Id, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
665 }
666 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400667 if isOkToReconcile(childDevice) {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700668 logger.Debugw("reconciling-child-device", log.Fields{"child-device-id": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530669 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400670 } else {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700671 logger.Debugw("not-reconciling-child-device", log.Fields{"child-device-id": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400672 }
673 } else {
674 // All child devices under a parent device are typically managed by the same adapter type.
675 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
676 break childManagedByAdapter
677 }
678 }
679 }
680 }
681 }
682 }
683 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500684 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400685 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500686 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400687 return status.Errorf(codes.Aborted, "errors-%s", res)
688 }
689 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000690 logger.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400691 }
692 return nil
693}
694
Kent Hagerman2b216042020-04-03 18:28:56 -0400695func (dMgr *Manager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400696 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
697 // 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 +0530698 // 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 -0400699 // the adapter proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500700 response := utils.NewResponse()
Kent Hagerman2b216042020-04-03 18:28:56 -0400701 ch, err := dMgr.adapterProxy.ReconcileDevice(ctx, device)
khenaidoo442e7c72020-03-10 16:13:48 -0400702 if err != nil {
703 response.Error(err)
704 }
705 // Wait for adapter response in its own routine
706 go func() {
707 resp, ok := <-ch
708 if !ok {
709 response.Error(status.Errorf(codes.Aborted, "channel-closed-device: %s", device.Id))
710 } else if resp.Err != nil {
711 response.Error(resp.Err)
khenaidooba6b6c42019-08-02 09:11:56 -0400712 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500713 response.Done()
khenaidoo442e7c72020-03-10 16:13:48 -0400714 }()
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500715 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400716}
717
Kent Hagerman2b216042020-04-03 18:28:56 -0400718func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID string) error {
npujar467fe752020-01-16 20:17:45 +0530719 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500720 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400721 for _, port := range parentDevice.Ports {
722 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530723 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
724 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400725 }
726 }
727 }
728 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500729 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400730 return status.Errorf(codes.Aborted, "errors-%s", res)
731 }
732 }
733 return nil
734}
735
Kent Hagerman2b216042020-04-03 18:28:56 -0400736func (dMgr *Manager) UpdateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
737 logger.Debugw("UpdateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530738 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
739 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400740 }
741 return status.Errorf(codes.NotFound, "%s", device.Id)
742}
743
Kent Hagerman2b216042020-04-03 18:28:56 -0400744func (dMgr *Manager) AddPort(ctx context.Context, deviceID string, port *voltha.Port) error {
npujar467fe752020-01-16 20:17:45 +0530745 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530746 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530747 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400748 return err
749 }
750 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530751 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400752 for _, peerPort := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530753 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
754 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000755 logger.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
khenaidoo92e62c52018-10-03 14:02:54 -0400756 return err
757 }
758 }
759 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400760 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
761 // then a logical port will be added to the logical device and the device graph generated. If the port is a
762 // PON port then only the device graph will be generated.
Kent Hagerman45a13e42020-04-13 12:23:50 -0400763 if device, err := dMgr.getDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530764 go func() {
npujar467fe752020-01-16 20:17:45 +0530765 err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port)
npujar1d86a522019-11-14 17:11:16 +0530766 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000767 logger.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530768 }
769 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400770 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000771 logger.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400772 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400773 }
khenaidoo92e62c52018-10-03 14:02:54 -0400774 return nil
khenaidoob9203542018-09-17 22:56:37 -0400775 }
npujar1d86a522019-11-14 17:11:16 +0530776 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400777}
778
Kent Hagerman2b216042020-04-03 18:28:56 -0400779func (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 +0000780 logger.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530781 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
782 return agent.addFlowsAndGroups(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
khenaidoo787224a2020-04-16 18:08:47 -0400787// deleteParentFlows removes flows from the parent device based on specific attributes
788func (dMgr *Manager) deleteParentFlows(ctx context.Context, deviceID string, uniPort uint32, metadata *voltha.FlowMetadata) error {
789 logger.Debugw("deleteParentFlows", log.Fields{"device-id": deviceID, "uni-port": uniPort, "metadata": metadata})
790 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
791 if !agent.isRootdevice {
792 return status.Errorf(codes.FailedPrecondition, "not-a-parent-device-%s", deviceID)
793 }
794 return agent.filterOutFlows(ctx, uniPort, metadata)
795 }
796 return status.Errorf(codes.NotFound, "%s", deviceID)
797}
798
Kent Hagerman2b216042020-04-03 18:28:56 -0400799func (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 +0000800 logger.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530801 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
802 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400803 }
npujar1d86a522019-11-14 17:11:16 +0530804 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400805}
806
Kent Hagerman2b216042020-04-03 18:28:56 -0400807func (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 +0000808 logger.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530809 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
810 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400811 }
npujar1d86a522019-11-14 17:11:16 +0530812 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400813}
814
Kent Hagerman45a13e42020-04-13 12:23:50 -0400815// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
khenaidoob3127472019-07-24 21:04:55 -0400816// following a user action
Kent Hagerman45a13e42020-04-13 12:23:50 -0400817func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
818 if configs.Id == "" {
819 return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
khenaidoob3127472019-07-24 21:04:55 -0400820 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400821 agent := dMgr.getDeviceAgent(ctx, configs.Id)
822 if agent == nil {
823 return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
824 }
825 return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
khenaidoob3127472019-07-24 21:04:55 -0400826}
827
Kent Hagerman2b216042020-04-03 18:28:56 -0400828// InitPmConfigs initialize the pm configs as defined by the adapter.
829func (dMgr *Manager) InitPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400830 if pmConfigs.Id == "" {
831 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
832 }
npujar467fe752020-01-16 20:17:45 +0530833 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
834 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400835 }
npujar1d86a522019-11-14 17:11:16 +0530836 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400837}
838
Kent Hagerman45a13e42020-04-13 12:23:50 -0400839// ListDevicePmConfigs returns pm configs of device
840func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
841 agent := dMgr.getDeviceAgent(ctx, id.Id)
842 if agent == nil {
843 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob3127472019-07-24 21:04:55 -0400844 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400845 return agent.listPmConfigs(ctx)
khenaidoob3127472019-07-24 21:04:55 -0400846}
847
Kent Hagerman2b216042020-04-03 18:28:56 -0400848func (dMgr *Manager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000849 logger.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530850 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400851 return agent.getSwitchCapability(ctx)
852 }
npujar1d86a522019-11-14 17:11:16 +0530853 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400854}
855
Kent Hagerman2b216042020-04-03 18:28:56 -0400856func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
857 logger.Debugw("GetPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530858 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400859 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400860 }
npujar1d86a522019-11-14 17:11:16 +0530861 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400862}
863
Kent Hagerman2b216042020-04-03 18:28:56 -0400864func (dMgr *Manager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000865 logger.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530866 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400867 return agent.getPortCapability(ctx, portNo)
868 }
npujar1d86a522019-11-14 17:11:16 +0530869 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400870}
871
Kent Hagerman2b216042020-04-03 18:28:56 -0400872func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
873 logger.Debugw("UpdateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530874 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
875 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400876 }
npujar1d86a522019-11-14 17:11:16 +0530877 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400878}
879
Kent Hagerman2b216042020-04-03 18:28:56 -0400880func (dMgr *Manager) UpdateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
881 logger.Debugw("UpdateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400882 var parentDevice *voltha.Device
883 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400884 if parentDevice, err = dMgr.getDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400885 return status.Errorf(codes.Aborted, "%s", err.Error())
886 }
887 var childDeviceIds []string
888 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
889 return status.Errorf(codes.Aborted, "%s", err.Error())
890 }
891 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000892 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400893 }
npujar1d86a522019-11-14 17:11:16 +0530894 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530895 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
896 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530897 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400898 }
899 }
900 }
901 return nil
902}
903
Kent Hagerman2b216042020-04-03 18:28:56 -0400904func (dMgr *Manager) UpdatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
905 logger.Debugw("UpdatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530906 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
907 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000908 logger.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400909 return err
910 }
911 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800912 // Do this for NNI and UNIs only. PON ports are not known by logical device
913 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
914 go func() {
915 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
916 if err != nil {
917 // While we want to handle (catch) and log when
918 // an update to a port was not able to be
919 // propagated to the logical port, we can report
920 // it as a warning and not an error because it
921 // doesn't stop or modify processing.
922 // TODO: VOL-2707
Girish Kumarf56a4682020-03-20 20:07:46 +0000923 logger.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800924 }
925 }()
926 }
khenaidoo442e7c72020-03-10 16:13:48 -0400927 return nil
khenaidoob9203542018-09-17 22:56:37 -0400928 }
npujar1d86a522019-11-14 17:11:16 +0530929 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400930}
931
Kent Hagerman2b216042020-04-03 18:28:56 -0400932func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000933 logger.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530934 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
935 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400936 return err
937 }
938 // Notify the logical device manager to remove all logical ports, if needed.
Kent Hagerman2b216042020-04-03 18:28:56 -0400939 // At this stage the device itself may gave been deleted already at a DeleteAllPorts
khenaidoo0a822f92019-05-08 15:15:57 -0400940 // typically is part of a device deletion phase.
Kent Hagerman45a13e42020-04-13 12:23:50 -0400941 if device, err := dMgr.getDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530942 go func() {
npujar467fe752020-01-16 20:17:45 +0530943 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530944 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000945 logger.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530946 }
947 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400948 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000949 logger.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400950 return err
951 }
952 return nil
953 }
npujar1d86a522019-11-14 17:11:16 +0530954 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400955}
956
Kent Hagerman2b216042020-04-03 18:28:56 -0400957//UpdatePortsState updates all ports on the device
958func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
959 logger.Debugw("UpdatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400960
npujar467fe752020-01-16 20:17:45 +0530961 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400962 switch state {
963 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500964 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000965 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400966 return err
967 }
968 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500969 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000970 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400971 return err
972 }
973 default:
974 return status.Error(codes.Unimplemented, "state-change-not-implemented")
975 }
976 // Notify the logical device about the state change
Kent Hagerman45a13e42020-04-13 12:23:50 -0400977 device, err := dMgr.getDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530978 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000979 logger.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400980 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400981 }
kesavandbc2d1622020-01-21 00:42:01 -0500982 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000983 logger.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530984 return err
985 }
986 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400987 }
npujar1d86a522019-11-14 17:11:16 +0530988 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400989}
990
Kent Hagerman2b216042020-04-03 18:28:56 -0400991func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530992 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -0400993 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 -0700994
npujar1d86a522019-11-14 17:11:16 +0530995 if deviceType == "" && vendorID != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000996 logger.Debug("device-type-is-nil-fetching-device-type")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400997 deviceTypes, err := dMgr.adapterMgr.ListDeviceTypes(ctx, nil)
998 if err != nil {
999 return nil, err
1000 }
Kent Hagerman4f355f52020-03-30 16:01:33 -04001001 OLoop:
Kent Hagerman45a13e42020-04-13 12:23:50 -04001002 for _, dType := range deviceTypes.Items {
Kent Hagerman4f355f52020-03-30 16:01:33 -04001003 for _, v := range dType.VendorIds {
1004 if v == vendorID {
1005 deviceType = dType.Adapter
1006 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001007 }
1008 }
1009 }
1010 }
1011 //if no match found for the vendorid,report adapter with the custom error message
1012 if deviceType == "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001013 logger.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +05301014 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001015 }
khenaidoob9203542018-09-17 22:56:37 -04001016
1017 // Create the ONU device
1018 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -04001019 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +05301020 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -04001021 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +05301022 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -05001023 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -04001024 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001025
khenaidoo442e7c72020-03-10 16:13:48 -04001026 // Get parent device type
1027 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
1028 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +05301029 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001030 }
khenaidoo442e7c72020-03-10 16:13:48 -04001031 if pAgent.deviceType == "" {
1032 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
1033 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001034
npujar467fe752020-01-16 20:17:45 +05301035 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001036 logger.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001037 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001038 }
1039
khenaidoo442e7c72020-03-10 16:13:48 -04001040 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001041
1042 // Create and start a device agent for that device
Kent Hagerman2b216042020-04-03 18:28:56 -04001043 agent := newAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -04001044 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001045 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001046 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 -08001047 return nil, err
1048 }
khenaidoo442e7c72020-03-10 16:13:48 -04001049 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001050
1051 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301052 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301053 go func() {
npujar467fe752020-01-16 20:17:45 +05301054 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301055 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001056 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301057 }
1058 }()
khenaidoob9203542018-09-17 22:56:37 -04001059 }
1060
khenaidoo79232702018-12-04 11:00:41 -05001061 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301062 go func() {
1063 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1064 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001065 logger.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301066 }
1067 }()
khenaidoo79232702018-12-04 11:00:41 -05001068
Scott Baker80678602019-11-14 16:57:36 -08001069 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001070}
1071
Kent Hagerman2b216042020-04-03 18:28:56 -04001072func (dMgr *Manager) processTransition(ctx context.Context, device *voltha.Device, previousState *deviceState) error {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001073 // This will be triggered on every state update
1074 logger.Debugw("state-transition", log.Fields{
1075 "device": device.Id,
1076 "prev-admin-state": previousState.Admin,
1077 "prev-oper-state": previousState.Operational,
1078 "prev-conn-state": previousState.Connection,
1079 "curr-admin-state": device.AdminState,
1080 "curr-oper-state": device.OperStatus,
1081 "curr-conn-state": device.ConnectStatus,
1082 })
1083 handlers := dMgr.stateTransitions.GetTransitionHandler(device, previousState)
khenaidoo92e62c52018-10-03 14:02:54 -04001084 if handlers == nil {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001085 logger.Debugw("no-op-transition", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001086 return nil
khenaidoob9203542018-09-17 22:56:37 -04001087 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001088 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 -04001089 for _, handler := range handlers {
Girish Kumarf56a4682020-03-20 20:07:46 +00001090 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001091 if err := handler(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001092 logger.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001093 return err
1094 }
1095 }
khenaidoob9203542018-09-17 22:56:37 -04001096 return nil
1097}
1098
Kent Hagerman2b216042020-04-03 18:28:56 -04001099func (dMgr *Manager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001100 logger.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301101 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1102 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001103 }
npujar1d86a522019-11-14 17:11:16 +05301104 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001105}
1106
npujar1d86a522019-11-14 17:11:16 +05301107// PacketIn receives packet from adapter
Kent Hagerman2b216042020-04-03 18:28:56 -04001108func (dMgr *Manager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001109 logger.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001110 // Get the logical device Id based on the deviceId
1111 var device *voltha.Device
1112 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -04001113 if device, err = dMgr.getDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001114 logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001115 return err
1116 }
khenaidoo43c82122018-11-22 18:38:28 -05001117 if !device.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +00001118 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301119 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001120 }
1121
npujar467fe752020-01-16 20:17:45 +05301122 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001123 return err
1124 }
1125 return nil
1126}
1127
Kent Hagerman2b216042020-04-03 18:28:56 -04001128func (dMgr *Manager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001129 logger.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301130 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1131 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001132 }
1133 return status.Errorf(codes.NotFound, "%s", device.Id)
1134}
1135
npujar1d86a522019-11-14 17:11:16 +05301136// CreateLogicalDevice creates logical device in core
Kent Hagerman2b216042020-04-03 18:28:56 -04001137func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001138 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001139 // Verify whether the logical device has already been created
1140 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001141 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001142 return nil
1143 }
khenaidoob9203542018-09-17 22:56:37 -04001144 var err error
npujar467fe752020-01-16 20:17:45 +05301145 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001146 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001147 return err
1148 }
khenaidoob9203542018-09-17 22:56:37 -04001149 return nil
1150}
1151
npujar1d86a522019-11-14 17:11:16 +05301152// DeleteLogicalDevice deletes logical device from core
Kent Hagerman2b216042020-04-03 18:28:56 -04001153func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001154 logger.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001155 var err error
npujar467fe752020-01-16 20:17:45 +05301156 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001157 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001158 return err
1159 }
1160 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301161 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301162 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001163 return nil
1164}
1165
npujar1d86a522019-11-14 17:11:16 +05301166// DeleteLogicalPort removes the logical port associated with a device
Kent Hagerman2b216042020-04-03 18:28:56 -04001167func (dMgr *Manager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001168 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001169 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001170 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301171 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301172 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001173 logger.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001174 return err
1175 }
npujar467fe752020-01-16 20:17:45 +05301176 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001177 logger.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001178 return err
1179 }
khenaidoo92e62c52018-10-03 14:02:54 -04001180 return nil
1181}
1182
npujar1d86a522019-11-14 17:11:16 +05301183// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagerman2b216042020-04-03 18:28:56 -04001184func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001185 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001186 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001187 // 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 +00001188 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001189 }
1190 return nil
1191}
1192
Kent Hagerman2b216042020-04-03 18:28:56 -04001193func (dMgr *Manager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001194 // Sanity check
1195 if childDevice.Root {
1196 // childDevice is the parent device
1197 return childDevice
1198 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001199 parentDevice, _ := dMgr.getDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001200 return parentDevice
1201}
1202
Kent Hagerman2b216042020-04-03 18:28:56 -04001203//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 -04001204//cannot manage the child devices. This will trigger the Core to disable all the child devices.
Kent Hagerman2b216042020-04-03 18:28:56 -04001205func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
1206 logger.Debug("ChildDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001207 var err error
1208 var parentDevice *voltha.Device
Kent Hagerman45a13e42020-04-13 12:23:50 -04001209 if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001210 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001211 return err
1212 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001213 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001214}
1215
Kent Hagerman2b216042020-04-03 18:28:56 -04001216//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
khenaidoo0a822f92019-05-08 15:15:57 -04001217// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
Kent Hagerman2b216042020-04-03 18:28:56 -04001218func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
1219 logger.Debug("ChildDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001220 var err error
1221 var parentDevice *voltha.Device
1222 var childDeviceIds []string
1223
Kent Hagerman45a13e42020-04-13 12:23:50 -04001224 if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001225 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001226 return err
1227 }
1228
1229 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1230 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1231 }
1232 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001233 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001234 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001235 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301236 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301237 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001238 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301239 go func() {
npujar467fe752020-01-16 20:17:45 +05301240 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301241 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001242 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301243 }
1244 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001245 } else {
npujar1d86a522019-11-14 17:11:16 +05301246 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Girish Kumarf56a4682020-03-20 20:07:46 +00001247 logger.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001248 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001249 }
1250 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001251 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001252 return err
1253 }
1254 return nil
1255}
1256
khenaidoo4d4802d2018-10-04 21:59:49 -04001257/*
1258All the functions below are callback functions where they are invoked with the latest and previous data. We can
1259therefore use the data as is without trying to get the latest from the model.
1260*/
1261
khenaidoo0a822f92019-05-08 15:15:57 -04001262//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagerman2b216042020-04-03 18:28:56 -04001263func (dMgr *Manager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001264 logger.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001265 var childDeviceIds []string
1266 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001267 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1268 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001269 }
1270 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001271 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001272 }
npujar1d86a522019-11-14 17:11:16 +05301273 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301274 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1275 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001276 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001277 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001278 }
1279 }
1280 }
1281 return nil
1282}
1283
khenaidoo0a822f92019-05-08 15:15:57 -04001284//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001285func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001286 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001287 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001288 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001289 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1290 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001291 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001292 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001293 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001294 }
npujar1d86a522019-11-14 17:11:16 +05301295 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301296 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1297 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001298 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001299 }
khenaidoo49085352020-01-13 19:15:43 -05001300 // No further action is required here. The deleteDevice will change the device state where the resulting
1301 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001302 }
1303 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001304 return nil
1305}
1306
Hardik Windlassc704def2020-02-26 18:23:19 +00001307//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001308func (dMgr *Manager) DeleteAllUNILogicalPorts(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001309 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": curr.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001310 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, curr); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001311 // Just log the error and let the remaining pipeline proceed - ports may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001312 logger.Warnw("delete-all-uni-logical-ports-failed", log.Fields{"parent-device-id": curr.Id, "error": err})
Hardik Windlassc704def2020-02-26 18:23:19 +00001313 }
1314 return nil
1315}
1316
Girish Gowdra408cd962020-03-11 14:31:31 -07001317//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001318func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001319 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001320 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001321 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001322 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001323 }
1324 return nil
1325}
1326
1327//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001328func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001329 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001330 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1331 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001332 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001333 return err
1334 }
1335 return nil
1336 }
1337 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1338}
1339
khenaidoo4d4802d2018-10-04 21:59:49 -04001340//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 -04001341func (dMgr *Manager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001342 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001343 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001344 if parentDevice != nil {
1345 for _, port := range parentDevice.Ports {
1346 for _, peer := range port.Peers {
1347 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1348 }
khenaidoo92e62c52018-10-03 14:02:54 -04001349 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001350 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001351 }
1352 return childDeviceIds, nil
1353}
1354
Kent Hagerman2b216042020-04-03 18:28:56 -04001355//GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1356func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
1357 logger.Debugw("GetAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001358 if parentDevice, err := dMgr.getDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001359 childDevices := make([]*voltha.Device, 0)
1360 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301361 for _, deviceID := range childDeviceIds {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001362 if d, e := dMgr.getDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001363 childDevices = append(childDevices, d)
1364 }
1365 }
1366 }
1367 return &voltha.Devices{Items: childDevices}, nil
1368 }
npujar1d86a522019-11-14 17:11:16 +05301369 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001370}
1371
npujar1d86a522019-11-14 17:11:16 +05301372// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagerman2b216042020-04-03 18:28:56 -04001373func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001374 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301375 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001376 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001377 return err
1378 }
1379 return nil
1380}
1381
Kent Hagerman45a13e42020-04-13 12:23:50 -04001382// convenience to avoid redefining
1383var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
1384
1385// DownloadImage execute an image download request
1386func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1387 logger.Debugw("DownloadImage", log.Fields{"device-id": img.Id, "imageName": img.Name})
1388 agent := dMgr.getDeviceAgent(ctx, img.Id)
1389 if agent == nil {
1390 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001391 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001392 resp, err := agent.downloadImage(ctx, img)
1393 if err != nil {
1394 return operationFailureResp, err
1395 }
1396 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001397}
1398
Kent Hagerman45a13e42020-04-13 12:23:50 -04001399// CancelImageDownload cancels image download request
1400func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1401 logger.Debugw("CancelImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
1402 agent := dMgr.getDeviceAgent(ctx, img.Id)
1403 if agent == nil {
1404 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001405 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001406 resp, err := agent.cancelImageDownload(ctx, img)
1407 if err != nil {
1408 return operationFailureResp, err
1409 }
1410 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001411}
1412
Kent Hagerman45a13e42020-04-13 12:23:50 -04001413// ActivateImageUpdate activates image update request
1414func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1415 logger.Debugw("ActivateImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
1416 agent := dMgr.getDeviceAgent(ctx, img.Id)
1417 if agent == nil {
1418 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001419 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001420 resp, err := agent.activateImage(ctx, img)
1421 if err != nil {
1422 return operationFailureResp, err
1423 }
1424 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001425}
1426
Kent Hagerman45a13e42020-04-13 12:23:50 -04001427// RevertImageUpdate reverts image update
1428func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1429 logger.Debugw("RevertImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
1430 agent := dMgr.getDeviceAgent(ctx, img.Id)
1431 if agent == nil {
1432 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001433 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001434 resp, err := agent.revertImage(ctx, img)
1435 if err != nil {
1436 return operationFailureResp, err
1437 }
1438 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001439}
1440
Kent Hagerman45a13e42020-04-13 12:23:50 -04001441// convenience to avoid redefining
1442var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
1443
1444// GetImageDownloadStatus returns status of image download
1445func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1446 logger.Debugw("GetImageDownloadStatus", log.Fields{"device-id": img.Id, "imageName": img.Name})
1447 agent := dMgr.getDeviceAgent(ctx, img.Id)
1448 if agent == nil {
1449 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001450 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001451 resp, err := agent.getImageDownloadStatus(ctx, img)
1452 if err != nil {
1453 return imageDownloadFailureResp, err
1454 }
1455 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001456}
1457
Kent Hagerman2b216042020-04-03 18:28:56 -04001458func (dMgr *Manager) UpdateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001459 logger.Debugw("UpdateImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301460 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1461 if err := agent.updateImageDownload(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001462 logger.Debugw("UpdateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001463 return err
1464 }
1465 } else {
1466 return status.Errorf(codes.NotFound, "%s", img.Id)
1467 }
1468 return nil
1469}
1470
Kent Hagerman45a13e42020-04-13 12:23:50 -04001471// GetImageDownload returns image download
Kent Hagerman2b216042020-04-03 18:28:56 -04001472func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001473 logger.Debugw("GetImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
1474 agent := dMgr.getDeviceAgent(ctx, img.Id)
1475 if agent == nil {
1476 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001477 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001478 resp, err := agent.getImageDownload(ctx, img)
1479 if err != nil {
1480 return imageDownloadFailureResp, err
1481 }
1482 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001483}
1484
Kent Hagerman45a13e42020-04-13 12:23:50 -04001485// ListImageDownloads returns image downloads
1486func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
1487 logger.Debugw("ListImageDownloads", log.Fields{"device-id": id.Id})
1488 agent := dMgr.getDeviceAgent(ctx, id.Id)
1489 if agent == nil {
1490 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001491 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001492 resp, err := agent.listImageDownloads(ctx, id.Id)
1493 if err != nil {
1494 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
1495 }
1496 return resp, nil
1497}
1498
1499// GetImages returns all images for a specific device entry
1500func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
1501 logger.Debugw("GetImages", log.Fields{"device-id": id.Id})
1502 device, err := dMgr.getDevice(ctx, id.Id)
1503 if err != nil {
1504 return nil, err
1505 }
1506 return device.GetImages(), nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001507}
1508
Kent Hagerman2b216042020-04-03 18:28:56 -04001509func (dMgr *Manager) NotifyInvalidTransition(_ context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001510 logger.Errorw("NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001511 "device": device.Id,
1512 "curr-admin-state": device.AdminState,
1513 "curr-oper-state": device.OperStatus,
1514 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001515 })
khenaidoo0a822f92019-05-08 15:15:57 -04001516 //TODO: notify over kafka?
1517 return nil
1518}
1519
khenaidoob9203542018-09-17 22:56:37 -04001520func funcName(f interface{}) string {
1521 p := reflect.ValueOf(f).Pointer()
1522 rf := runtime.FuncForPC(p)
1523 return rf.Name()
1524}
1525
npujar1d86a522019-11-14 17:11:16 +05301526// UpdateDeviceAttribute updates value of particular device attribute
Kent Hagerman2b216042020-04-03 18:28:56 -04001527func (dMgr *Manager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301528 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -04001529 agent.(*Agent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001530 }
1531}
1532
npujar1d86a522019-11-14 17:11:16 +05301533// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -04001534func (dMgr *Manager) GetParentDeviceID(ctx context.Context, deviceID string) string {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001535 if device, _ := dMgr.getDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001536 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001537 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001538 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001539 return ""
khenaidoob9203542018-09-17 22:56:37 -04001540}
serkant.uluderya334479d2019-04-10 08:26:15 -07001541
Kent Hagerman45a13e42020-04-13 12:23:50 -04001542func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
1543 logger.Debugw("SimulateAlarm", log.Fields{"id": simulateReq.Id, "Indicator": simulateReq.Indicator, "IntfId": simulateReq.IntfId,
1544 "PortTypeName": simulateReq.PortTypeName, "OnuDeviceId": simulateReq.OnuDeviceId, "InverseBitErrorRate": simulateReq.InverseBitErrorRate,
1545 "Drift": simulateReq.Drift, "NewEqd": simulateReq.NewEqd, "OnuSerialNumber": simulateReq.OnuSerialNumber, "Operation": simulateReq.Operation})
1546 agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
1547 if agent == nil {
1548 return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
serkant.uluderya334479d2019-04-10 08:26:15 -07001549 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001550 if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
1551 return nil, err
1552 }
1553 return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
serkant.uluderya334479d2019-04-10 08:26:15 -07001554}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001555
Kent Hagerman2b216042020-04-03 18:28:56 -04001556func (dMgr *Manager) UpdateDeviceReason(ctx context.Context, deviceID string, reason string) error {
1557 logger.Debugw("UpdateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301558 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1559 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001560 }
npujar1d86a522019-11-14 17:11:16 +05301561 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001562}
kesavandbc2d1622020-01-21 00:42:01 -05001563
Kent Hagerman45a13e42020-04-13 12:23:50 -04001564func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -04001565 logger.Debugw("EnablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001566 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1567 if agent == nil {
1568 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001569 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001570 return &empty.Empty{}, agent.enablePort(ctx, port)
kesavandbc2d1622020-01-21 00:42:01 -05001571}
1572
Kent Hagerman45a13e42020-04-13 12:23:50 -04001573func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -04001574 logger.Debugw("DisablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001575 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1576 if agent == nil {
1577 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001578 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001579 return &empty.Empty{}, agent.disablePort(ctx, port)
kesavandbc2d1622020-01-21 00:42:01 -05001580}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001581
Kent Hagerman2b216042020-04-03 18:28:56 -04001582// ChildDeviceLost calls parent adapter to delete child device and all its references
1583func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001584 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001585 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001586 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1587 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001588 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001589 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001590 }
khenaidooe132f522020-03-20 15:23:15 -04001591 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1592 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001593}
onkarkundargi87285252020-01-27 11:34:52 +05301594
Kent Hagerman45a13e42020-04-13 12:23:50 -04001595func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
1596 logger.Debugw("StartOmciTestAction", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
1597 agent := dMgr.getDeviceAgent(ctx, request.Id)
1598 if agent == nil {
1599 return nil, status.Errorf(codes.NotFound, "%s", request.Id)
onkarkundargi87285252020-01-27 11:34:52 +05301600 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001601 return agent.startOmciTest(ctx, request)
onkarkundargi87285252020-01-27 11:34:52 +05301602}
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001603
1604func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
1605 log.Debugw("getExtValue", log.Fields{"onu-id": value.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001606 cDevice, err := dMgr.getDevice(ctx, value.Id)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001607 if err != nil {
1608 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1609 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001610 pDevice, err := dMgr.getDevice(ctx, cDevice.ParentId)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001611 if err != nil {
1612 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1613 }
1614 if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
1615 resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
1616 if err != nil {
1617 return nil, err
1618 }
1619 log.Debugw("getExtValue-result", log.Fields{"result": resp})
1620 return resp, nil
1621 }
1622 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1623
1624}