blob: 19dab3d891803d80ed6e6ca35d4adbeb5195fadf [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
npujar1d86a522019-11-14 17:11:16 +053016
Kent Hagerman2b216042020-04-03 18:28:56 -040017package device
khenaidoob9203542018-09-17 22:56:37 -040018
19import (
20 "context"
21 "errors"
David Bainbridged1afd662020-03-26 18:27:41 -070022 "reflect"
23 "runtime"
24 "sync"
25 "time"
26
Kent Hagerman45a13e42020-04-13 12:23:50 -040027 "github.com/golang/protobuf/ptypes/empty"
sbarbari17d7e222019-11-05 10:02:29 -050028 "github.com/opencord/voltha-go/db/model"
Kent Hagerman2b216042020-04-03 18:28:56 -040029 "github.com/opencord/voltha-go/rw_core/core/adapter"
Kent Hagermanf5a67352020-04-30 15:15:26 -040030 "github.com/opencord/voltha-go/rw_core/core/device/event"
Kent Hagerman2b216042020-04-03 18:28:56 -040031 "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"
Kent Hagerman45a13e42020-04-13 12:23:50 -040035 "github.com/opencord/voltha-protos/v3/go/common"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080036 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
Mahir Gunyel03de0d32020-06-03 01:36:59 -070037 "github.com/opencord/voltha-protos/v3/go/openflow_13"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080038 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
Mahir Gunyel03de0d32020-06-03 01:36:59 -070054 dbPath *model.Path
Kent Hagermanf5a67352020-04-30 15:15:26 -040055 dProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053056 coreInstanceID string
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
Mahir Gunyel03de0d32020-06-03 01:36:59 -070062//NewManagers creates the Manager and the Logical Manager.
serkant.uluderya8ff291d2020-05-20 00:58:00 -070063func NewManagers(dbPath *model.Path, adapterMgr *adapter.Manager, kmp kafka.InterContainerProxy, endpointMgr kafka.EndpointManager, coreTopic, coreInstanceID string, defaultCoreTimeout time.Duration) (*Manager, *LogicalManager) {
Kent Hagerman2b216042020-04-03 18:28:56 -040064 deviceMgr := &Manager{
Kent Hagerman2b216042020-04-03 18:28:56 -040065 rootDevices: make(map[string]bool),
66 kafkaICProxy: kmp,
serkant.uluderya8ff291d2020-05-20 00:58:00 -070067 adapterProxy: remote.NewAdapterProxy(kmp, coreTopic, endpointMgr),
Kent Hagerman2b216042020-04-03 18:28:56 -040068 coreInstanceID: coreInstanceID,
Mahir Gunyel03de0d32020-06-03 01:36:59 -070069 dbPath: dbPath,
70 dProxy: dbPath.Proxy("devices"),
Kent Hagerman2b216042020-04-03 18:28:56 -040071 adapterMgr: adapterMgr,
Kent Hagermanf4151de2020-06-19 15:58:47 -040072 defaultTimeout: defaultCoreTimeout,
Kent Hagerman2b216042020-04-03 18:28:56 -040073 deviceLoadingInProgress: make(map[string][]chan int),
74 }
Kent Hagerman2f0d0552020-04-23 17:28:52 -040075 deviceMgr.stateTransitions = NewTransitionMap(deviceMgr)
76
Kent Hagerman2b216042020-04-03 18:28:56 -040077 logicalDeviceMgr := &LogicalManager{
Kent Hagerman45a13e42020-04-13 12:23:50 -040078 Manager: event.NewManager(),
Kent Hagerman2b216042020-04-03 18:28:56 -040079 deviceMgr: deviceMgr,
80 kafkaICProxy: kmp,
Mahir Gunyel03de0d32020-06-03 01:36:59 -070081 dbPath: dbPath,
82 ldProxy: dbPath.Proxy("logical_devices"),
Kent Hagerman2b216042020-04-03 18:28:56 -040083 defaultTimeout: defaultCoreTimeout,
84 logicalDeviceLoadingInProgress: make(map[string][]chan int),
85 }
86 deviceMgr.logicalDeviceMgr = logicalDeviceMgr
Matteo Scandolod525ae32020-04-02 17:27:29 -070087
Kent Hagerman2b216042020-04-03 18:28:56 -040088 adapterMgr.SetAdapterRestartedCallback(deviceMgr.adapterRestarted)
Matteo Scandolod525ae32020-04-02 17:27:29 -070089
Kent Hagerman2b216042020-04-03 18:28:56 -040090 return deviceMgr, logicalDeviceMgr
khenaidoob9203542018-09-17 22:56:37 -040091}
92
Kent Hagerman2b216042020-04-03 18:28:56 -040093func (dMgr *Manager) addDeviceAgentToMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +053094 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
95 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -040096 }
khenaidoo2c6a0992019-04-29 13:46:56 -040097 dMgr.lockRootDeviceMap.Lock()
98 defer dMgr.lockRootDeviceMap.Unlock()
Kent Hagerman2a07b862020-06-19 15:23:07 -040099 dMgr.rootDevices[agent.deviceID] = agent.isRootDevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400100
khenaidoob9203542018-09-17 22:56:37 -0400101}
102
Kent Hagerman2b216042020-04-03 18:28:56 -0400103func (dMgr *Manager) deleteDeviceAgentFromMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +0530104 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400105 dMgr.lockRootDeviceMap.Lock()
106 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530107 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400108}
109
khenaidoo297cd252019-02-07 22:10:23 -0500110// 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 -0400111func (dMgr *Manager) getDeviceAgent(ctx context.Context, deviceID string) *Agent {
npujar1d86a522019-11-14 17:11:16 +0530112 agent, ok := dMgr.deviceAgents.Load(deviceID)
113 if ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400114 return agent.(*Agent)
khenaidoob9203542018-09-17 22:56:37 -0400115 }
khenaidoo442e7c72020-03-10 16:13:48 -0400116 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530117 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530118 if err == nil {
119 agent, ok = dMgr.deviceAgents.Load(deviceID)
120 if !ok {
121 return nil
122 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400123 return agent.(*Agent)
npujar1d86a522019-11-14 17:11:16 +0530124 }
125 //TODO: Change the return params to return an error as well
Rohan Agrawal31f21802020-06-12 05:38:46 +0000126 logger.Errorw(ctx, "loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400127 return nil
128}
129
khenaidoo297cd252019-02-07 22:10:23 -0500130// listDeviceIdsFromMap returns the list of device IDs that are in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400131func (dMgr *Manager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500132 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400133
134 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
135 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
136 return true
137 })
138
khenaidoo7ccedd52018-12-14 16:48:54 -0500139 return result
140}
141
Kent Hagerman45a13e42020-04-13 12:23:50 -0400142// CreateDevice creates a new parent device in the data model
143func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
144 if device.MacAddress == "" && device.GetHostAndPort() == "" {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000145 logger.Errorf(ctx, "No Device Info Present")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400146 return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
147 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000148 logger.Debugw(ctx, "create-device", log.Fields{"device": *device})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400149
npujar467fe752020-01-16 20:17:45 +0530150 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530151 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000152 logger.Errorf(ctx, "Failed to fetch parent device info")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400153 return nil, err
Thomas Lee Se5a44012019-11-07 20:32:24 +0530154 }
155 if deviceExist {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000156 logger.Errorf(ctx, "Device is Pre-provisioned already with same IP-Port or MAC Address")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400157 return nil, errors.New("device is already pre-provisioned")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530158 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000159 logger.Debugw(ctx, "CreateDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400160
khenaidoo5e677ae2019-02-28 17:26:29 -0500161 // Ensure this device is set as root
162 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400163 // Create and start a device agent for that device
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700164 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530165 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800166 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000167 logger.Errorw(ctx, "Fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400168 return nil, err
Scott Baker80678602019-11-14 16:57:36 -0800169 }
khenaidoo442e7c72020-03-10 16:13:48 -0400170 dMgr.addDeviceAgentToMap(agent)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400171 return device, nil
khenaidoob9203542018-09-17 22:56:37 -0400172}
173
Kent Hagerman45a13e42020-04-13 12:23:50 -0400174// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
175func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000176 logger.Debugw(ctx, "EnableDevice", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400177 agent := dMgr.getDeviceAgent(ctx, id.Id)
178 if agent == nil {
179 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400180 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400181 return &empty.Empty{}, agent.enableDevice(ctx)
khenaidoob9203542018-09-17 22:56:37 -0400182}
183
Kent Hagerman45a13e42020-04-13 12:23:50 -0400184// DisableDevice disables a device along with any child device it may have
185func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000186 logger.Debugw(ctx, "DisableDevice", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400187 agent := dMgr.getDeviceAgent(ctx, id.Id)
188 if agent == nil {
189 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400190 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400191 return &empty.Empty{}, agent.disableDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400192}
193
Kent Hagerman45a13e42020-04-13 12:23:50 -0400194//RebootDevice invoked the reboot API to the corresponding adapter
195func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000196 logger.Debugw(ctx, "RebootDevice", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400197 agent := dMgr.getDeviceAgent(ctx, id.Id)
198 if agent == nil {
199 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400200 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400201 return &empty.Empty{}, agent.rebootDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400202}
203
Kent Hagerman45a13e42020-04-13 12:23:50 -0400204// DeleteDevice removes a device from the data model
205func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000206 logger.Debugw(ctx, "DeleteDevice", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400207 agent := dMgr.getDeviceAgent(ctx, id.Id)
208 if agent == nil {
209 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400210 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400211 return &empty.Empty{}, agent.deleteDevice(ctx)
212}
213
Kent Hagerman2a07b862020-06-19 15:23:07 -0400214// GetDevicePort returns the port details for a specific device port entry
215func (dMgr *Manager) GetDevicePort(ctx context.Context, deviceID string, portID uint32) (*voltha.Port, error) {
216 logger.Debugw(ctx, "ListDevicePorts", log.Fields{"device-id": deviceID})
217 agent := dMgr.getDeviceAgent(ctx, deviceID)
218 if agent == nil {
219 return nil, status.Errorf(codes.NotFound, "device-%s", deviceID)
220 }
221 return agent.getDevicePort(portID)
222}
223
Kent Hagerman45a13e42020-04-13 12:23:50 -0400224// ListDevicePorts returns the ports details for a specific device entry
225func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000226 logger.Debugw(ctx, "ListDevicePorts", log.Fields{"device-id": id.Id})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400227 agent := dMgr.getDeviceAgent(ctx, id.Id)
228 if agent == nil {
229 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400230 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400231
232 ports := agent.listDevicePorts()
233 ctr, ret := 0, make([]*voltha.Port, len(ports))
234 for _, port := range ports {
235 ret[ctr] = port
236 ctr++
237 }
238 return &voltha.Ports{Items: ret}, nil
Kent Hagerman45a13e42020-04-13 12:23:50 -0400239}
240
241// ListDeviceFlows returns the flow details for a specific device entry
242func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000243 logger.Debugw(ctx, "ListDeviceFlows", log.Fields{"device-id": id.Id})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700244 agent := dMgr.getDeviceAgent(ctx, id.Id)
245 if agent == nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400246 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400247 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700248
249 flows := agent.listDeviceFlows()
250 ctr, ret := 0, make([]*ofp.OfpFlowStats, len(flows))
251 for _, flow := range flows {
252 ret[ctr] = flow
253 ctr++
254 }
255 return &openflow_13.Flows{Items: ret}, nil
Kent Hagerman45a13e42020-04-13 12:23:50 -0400256}
257
258// ListDeviceFlowGroups returns the flow group details for a specific device entry
259func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*voltha.FlowGroups, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000260 logger.Debugw(ctx, "ListDeviceFlowGroups", log.Fields{"device-id": id.Id})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700261 agent := dMgr.getDeviceAgent(ctx, id.Id)
262 if agent == nil {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400263 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
264 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700265 groups := agent.listDeviceGroups()
266 ctr, ret := 0, make([]*openflow_13.OfpGroupEntry, len(groups))
267 for _, group := range groups {
268 ret[ctr] = group
269 ctr++
270 }
271 return &voltha.FlowGroups{Items: ret}, nil
khenaidoo4d4802d2018-10-04 21:59:49 -0400272}
273
khenaidoo6d62c002019-05-15 21:57:03 -0400274// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
275// This function is called only in the Core that does not own this device. In the Core that owns this device then a
276// deletion deletion also includes removal of any reference of this device.
Kent Hagerman2b216042020-04-03 18:28:56 -0400277func (dMgr *Manager) stopManagingDevice(ctx context.Context, id string) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000278 logger.Infow(ctx, "stopManagingDevice", log.Fields{"deviceId": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400279 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530280 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400281 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700282 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400283 }
npujar467fe752020-01-16 20:17:45 +0530284 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400285 if err := agent.stop(ctx); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000286 logger.Warnw(ctx, "unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400287 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400288 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400289 }
290 }
291}
292
npujar1d86a522019-11-14 17:11:16 +0530293// RunPostDeviceDelete removes any reference of this device
Kent Hagerman2b216042020-04-03 18:28:56 -0400294func (dMgr *Manager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000295 logger.Infow(ctx, "RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530296 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400297 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400298}
299
Kent Hagermancba2f302020-07-28 13:37:36 -0400300// GetDevice exists primarily to implement the gRPC interface.
301// Internal functions should call getDeviceReadOnly instead.
Kent Hagerman45a13e42020-04-13 12:23:50 -0400302func (dMgr *Manager) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
Kent Hagermancba2f302020-07-28 13:37:36 -0400303 return dMgr.getDeviceReadOnly(ctx, id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400304}
305
Kent Hagermancba2f302020-07-28 13:37:36 -0400306// getDeviceReadOnly will returns a device, either from memory or from the dB, if present
307func (dMgr *Manager) getDeviceReadOnly(ctx context.Context, id string) (*voltha.Device, error) {
308 logger.Debugw(ctx, "getDeviceReadOnly", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530309 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
Kent Hagermancba2f302020-07-28 13:37:36 -0400310 return agent.getDeviceReadOnly(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400311 }
312 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400313}
314
Kent Hagerman2a07b862020-06-19 15:23:07 -0400315func (dMgr *Manager) listDevicePorts(ctx context.Context, id string) (map[uint32]*voltha.Port, error) {
316 logger.Debugw(ctx, "listDevicePorts", log.Fields{"deviceid": id})
317 agent := dMgr.getDeviceAgent(ctx, id)
318 if agent == nil {
319 return nil, status.Errorf(codes.NotFound, "%s", id)
320 }
321 return agent.listDevicePorts(), nil
322}
323
npujar1d86a522019-11-14 17:11:16 +0530324// GetChildDevice will return a device, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -0400325func (dMgr *Manager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000326 logger.Debugw(ctx, "GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
npujar1d86a522019-11-14 17:11:16 +0530327 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500328
Kent Hagerman2a07b862020-06-19 15:23:07 -0400329 parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
330 if err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500331 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
332 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400333 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500334 if len(childDeviceIds) == 0 {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400335 logger.Debugw(ctx, "no-child-devices", log.Fields{"parentDeviceId": parentDeviceID, "serialNumber": serialNumber, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530336 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500337 }
338
339 var foundChildDevice *voltha.Device
Kent Hagerman2a07b862020-06-19 15:23:07 -0400340 for childDeviceID := range childDeviceIds {
npujar1d86a522019-11-14 17:11:16 +0530341 var found bool
Kent Hagermancba2f302020-07-28 13:37:36 -0400342 if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500343
npujar1d86a522019-11-14 17:11:16 +0530344 foundOnuID := false
345 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500346 if searchDevice.ParentPortNo == uint32(parentPortNo) {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400347 logger.Debugw(ctx, "found-child-by-onuid", log.Fields{"parentDeviceId": parentDeviceID, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530348 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500349 }
350 }
351
352 foundSerialNumber := false
353 if searchDevice.SerialNumber == serialNumber {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400354 logger.Debugw(ctx, "found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDeviceID, "serialNumber": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500355 foundSerialNumber = true
356 }
357
358 // if both onuId and serialNumber are provided both must be true for the device to be found
359 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530360 if onuID > 0 && serialNumber != "" {
361 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500362 } else {
npujar1d86a522019-11-14 17:11:16 +0530363 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500364 }
365
npujar1d86a522019-11-14 17:11:16 +0530366 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500367 foundChildDevice = searchDevice
368 break
369 }
370 }
371 }
372
373 if foundChildDevice != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400374 logger.Debugw(ctx, "child-device-found", log.Fields{"parentDeviceId": parentDeviceID, "foundChildDevice": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500375 return foundChildDevice, nil
376 }
377
Kent Hagerman2a07b862020-06-19 15:23:07 -0400378 logger.Debugw(ctx, "child-device-not-found", log.Fields{"parentDeviceId": parentDeviceID,
npujar1d86a522019-11-14 17:11:16 +0530379 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
380 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500381}
382
npujar1d86a522019-11-14 17:11:16 +0530383// GetChildDeviceWithProxyAddress will return a device based on proxy address
Kent Hagerman2b216042020-04-03 18:28:56 -0400384func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000385 logger.Debugw(ctx, "GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500386
Kent Hagerman2a07b862020-06-19 15:23:07 -0400387 parentDevicePorts, err := dMgr.listDevicePorts(ctx, proxyAddress.DeviceId)
388 if err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500389 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
390 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400391 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500392 if len(childDeviceIds) == 0 {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400393 logger.Debugw(ctx, "no-child-devices", log.Fields{"parentDeviceId": proxyAddress.DeviceId})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500394 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
395 }
396
397 var foundChildDevice *voltha.Device
Kent Hagerman2a07b862020-06-19 15:23:07 -0400398 for childDeviceID := range childDeviceIds {
Kent Hagermancba2f302020-07-28 13:37:36 -0400399 if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500400 if searchDevice.ProxyAddress == proxyAddress {
401 foundChildDevice = searchDevice
402 break
403 }
404 }
405 }
406
407 if foundChildDevice != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000408 logger.Debugw(ctx, "child-device-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500409 return foundChildDevice, nil
410 }
411
Rohan Agrawal31f21802020-06-12 05:38:46 +0000412 logger.Warnw(ctx, "child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500413 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
414}
415
npujar1d86a522019-11-14 17:11:16 +0530416// IsDeviceInCache returns true if device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400417func (dMgr *Manager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400418 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500419 return exist
420}
421
npujar1d86a522019-11-14 17:11:16 +0530422// IsRootDevice returns true if root device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400423func (dMgr *Manager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400424 dMgr.lockRootDeviceMap.RLock()
425 defer dMgr.lockRootDeviceMap.RUnlock()
426 if exist := dMgr.rootDevices[id]; exist {
427 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400428 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400429 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400430}
431
Stephane Barbarieaa467942019-02-06 14:09:44 -0500432// ListDevices retrieves the latest devices from the data model
Kent Hagerman45a13e42020-04-13 12:23:50 -0400433func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000434 logger.Debug(ctx, "ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400435 result := &voltha.Devices{}
Kent Hagerman4f355f52020-03-30 16:01:33 -0400436
437 var devices []*voltha.Device
Kent Hagermanf5a67352020-04-30 15:15:26 -0400438 if err := dMgr.dProxy.List(ctx, &devices); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000439 logger.Errorw(ctx, "failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530440 return nil, err
441 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400442
443 for _, device := range devices {
444 // If device is not in memory then set it up
445 if !dMgr.IsDeviceInCache(device.Id) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000446 logger.Debugw(ctx, "loading-device-from-Model", log.Fields{"id": device.Id})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700447 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
Kent Hagerman4f355f52020-03-30 16:01:33 -0400448 if _, err := agent.start(ctx, nil); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000449 logger.Warnw(ctx, "failure-starting-agent", log.Fields{"deviceId": device.Id})
Kent Hagerman4f355f52020-03-30 16:01:33 -0400450 } else {
451 dMgr.addDeviceAgentToMap(agent)
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500452 }
khenaidoob9203542018-09-17 22:56:37 -0400453 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400454 result.Items = append(result.Items, device)
khenaidoob9203542018-09-17 22:56:37 -0400455 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000456 logger.Debugw(ctx, "ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400457 return result, nil
458}
459
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530460//isParentDeviceExist checks whether device is already preprovisioned.
Kent Hagerman2b216042020-04-03 18:28:56 -0400461func (dMgr *Manager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530462 hostPort := newDevice.GetHostAndPort()
Kent Hagerman4f355f52020-03-30 16:01:33 -0400463 var devices []*voltha.Device
Kent Hagermanf5a67352020-04-30 15:15:26 -0400464 if err := dMgr.dProxy.List(ctx, &devices); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000465 logger.Errorw(ctx, "Failed to list devices from cluster data proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530466 return false, err
467 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400468 for _, device := range devices {
469 if !device.Root {
470 continue
471 }
472 if hostPort != "" && hostPort == device.GetHostAndPort() && device.AdminState != voltha.AdminState_DELETED {
473 return true, nil
474 }
475 if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress && device.AdminState != voltha.AdminState_DELETED {
476 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530477 }
478 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530479 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530480}
481
khenaidoo6d62c002019-05-15 21:57:03 -0400482//getDeviceFromModelretrieves the device data from the model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400483func (dMgr *Manager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400484 device := &voltha.Device{}
Kent Hagermanf5a67352020-04-30 15:15:26 -0400485 if have, err := dMgr.dProxy.Get(ctx, deviceID, device); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000486 logger.Errorw(ctx, "failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530487 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400488 } else if !have {
489 return nil, status.Error(codes.NotFound, deviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530490 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400491
492 return device, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400493}
494
npujar1d86a522019-11-14 17:11:16 +0530495// loadDevice loads the deviceID in memory, if not present
Kent Hagerman2b216042020-04-03 18:28:56 -0400496func (dMgr *Manager) loadDevice(ctx context.Context, deviceID string) (*Agent, error) {
npujar1d86a522019-11-14 17:11:16 +0530497 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500498 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
499 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400500 var err error
501 var device *voltha.Device
502 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530503 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
504 if !dMgr.IsDeviceInCache(deviceID) {
505 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400506 dMgr.devicesLoadingLock.Unlock()
507 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530508 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000509 logger.Debugw(ctx, "loading-device", log.Fields{"deviceId": deviceID})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700510 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530511 if _, err = agent.start(ctx, nil); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000512 logger.Warnw(ctx, "Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400513 } else {
514 dMgr.addDeviceAgentToMap(agent)
515 }
516 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000517 logger.Debugw(ctx, "Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400518 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400519 // announce completion of task to any number of waiting channels
520 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530521 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400522 for _, ch := range v {
523 close(ch)
524 }
npujar1d86a522019-11-14 17:11:16 +0530525 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400526 }
527 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400528 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400529 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500530 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400531 } else {
532 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530533 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400534 dMgr.devicesLoadingLock.Unlock()
535 // Wait for the channel to be closed, implying the process loading this device is done.
536 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500537 }
npujar1d86a522019-11-14 17:11:16 +0530538 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400539 return agent.(*Agent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500540 }
npujar1d86a522019-11-14 17:11:16 +0530541 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500542}
543
544// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
Kent Hagerman2a07b862020-06-19 15:23:07 -0400545func (dMgr *Manager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device, devicePorts map[uint32]*voltha.Port) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000546 logger.Debugw(ctx, "loading-parent-and-children", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500547 if device.Root {
548 // Scenario A
549 if device.ParentId != "" {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400550 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530551 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000552 logger.Warnw(ctx, "failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500553 }
554 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000555 logger.Debugw(ctx, "no-parent-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500556 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400557 // Load all child devices, if needed
558 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, devicePorts)
559 for childDeviceID := range childDeviceIds {
560 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
561 logger.Warnw(ctx, "failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
562 return err
khenaidoo297cd252019-02-07 22:10:23 -0500563 }
khenaidoo297cd252019-02-07 22:10:23 -0500564 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400565 logger.Debugw(ctx, "loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500566 }
567 return nil
568}
569
570// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
571// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
572// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
573// and the proceed with the request.
Kent Hagerman2b216042020-04-03 18:28:56 -0400574func (dMgr *Manager) load(ctx context.Context, deviceID string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000575 logger.Debug(ctx, "load...")
khenaidoo297cd252019-02-07 22:10:23 -0500576 // 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 -0400577 var dAgent *Agent
khenaidoo297cd252019-02-07 22:10:23 -0500578 var err error
npujar467fe752020-01-16 20:17:45 +0530579 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500580 return err
581 }
582 // Get the loaded device details
Kent Hagermancba2f302020-07-28 13:37:36 -0400583 device, err := dAgent.getDeviceReadOnly(ctx)
khenaidoo442e7c72020-03-10 16:13:48 -0400584 if err != nil {
585 return err
586 }
khenaidoo297cd252019-02-07 22:10:23 -0500587
588 // If the device is in Pre-provisioning or deleted state stop here
589 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
590 return nil
591 }
592
593 // Now we face two scenarios
594 if device.Root {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400595 devicePorts := dAgent.listDevicePorts()
596
khenaidoo297cd252019-02-07 22:10:23 -0500597 // Load all children as well as the parent of this device (logical_device)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400598 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device, devicePorts); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000599 logger.Warnw(ctx, "failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500600 return err
601 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000602 logger.Debugw(ctx, "successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500603 } else {
604 // Scenario B - use the parentId of that device (root device) to trigger the loading
605 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530606 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500607 }
608 }
609 return nil
610}
611
khenaidoo7ccedd52018-12-14 16:48:54 -0500612// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000613func (dMgr *Manager) ListDeviceIds(ctx context.Context, _ *empty.Empty) (*voltha.IDs, error) {
614 logger.Debug(ctx, "ListDeviceIDs")
khenaidoo7ccedd52018-12-14 16:48:54 -0500615 // Report only device IDs that are in the device agent map
616 return dMgr.listDeviceIdsFromMap(), nil
617}
618
Kent Hagerman45a13e42020-04-13 12:23:50 -0400619// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
620// trigger loading the devices along with their children and parent in memory
621func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000622 logger.Debugw(ctx, "ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo4c9e5592019-09-09 16:20:41 -0400623 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500624 toReconcile := len(ids.Items)
625 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400626 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500627 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530628 if err = dMgr.load(ctx, id.Id); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000629 logger.Warnw(ctx, "failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400630 } else {
npujar1d86a522019-11-14 17:11:16 +0530631 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500632 }
633 }
634 if toReconcile != reconciled {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400635 return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500636 }
637 } else {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400638 return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
khenaidoo7ccedd52018-12-14 16:48:54 -0500639 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400640 return &empty.Empty{}, nil
khenaidoo7ccedd52018-12-14 16:48:54 -0500641}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500642
khenaidooba6b6c42019-08-02 09:11:56 -0400643// isOkToReconcile validates whether a device is in the correct status to be reconciled
644func isOkToReconcile(device *voltha.Device) bool {
645 if device == nil {
646 return false
647 }
648 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
649}
650
651// adapterRestarted is invoked whenever an adapter is restarted
Kent Hagerman2b216042020-04-03 18:28:56 -0400652func (dMgr *Manager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000653 logger.Debugw(ctx, "adapter-restarted", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
Matteo Scandolod525ae32020-04-02 17:27:29 -0700654 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidooba6b6c42019-08-02 09:11:56 -0400655
656 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700657 if len(dMgr.rootDevices) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000658 logger.Debugw(ctx, "nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400659 return nil
660 }
661
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500662 responses := make([]utils.Response, 0)
David Bainbridged1afd662020-03-26 18:27:41 -0700663 for rootDeviceID := range dMgr.rootDevices {
npujar467fe752020-01-16 20:17:45 +0530664 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000665 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(ctx, rootDeviceID, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700666 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000667 logger.Warnw(ctx, "is-device-owned-by-service", log.Fields{"error": err, "root-device-id": rootDeviceID, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700668 continue
669 }
670 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400671 if isOkToReconcile(rootDevice) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000672 logger.Debugw(ctx, "reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530673 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400674 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000675 logger.Debugw(ctx, "not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400676 }
677 } else { // Should we be reconciling the root's children instead?
Kent Hagerman2a07b862020-06-19 15:23:07 -0400678 rootDevicePorts, _ := dMgr.listDevicePorts(ctx, rootDeviceID)
khenaidooba6b6c42019-08-02 09:11:56 -0400679 childManagedByAdapter:
Kent Hagerman2a07b862020-06-19 15:23:07 -0400680 for _, port := range rootDevicePorts {
khenaidooba6b6c42019-08-02 09:11:56 -0400681 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530682 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000683 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(ctx, childDevice.Id, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700684 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000685 logger.Warnw(ctx, "is-device-owned-by-service", log.Fields{"error": err, "child-device-id": childDevice.Id, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700686 }
687 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400688 if isOkToReconcile(childDevice) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000689 logger.Debugw(ctx, "reconciling-child-device", log.Fields{"child-device-id": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530690 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400691 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000692 logger.Debugw(ctx, "not-reconciling-child-device", log.Fields{"child-device-id": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400693 }
694 } else {
695 // All child devices under a parent device are typically managed by the same adapter type.
696 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
697 break childManagedByAdapter
698 }
699 }
700 }
701 }
702 }
703 }
704 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500705 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400706 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500707 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400708 return status.Errorf(codes.Aborted, "errors-%s", res)
709 }
710 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000711 logger.Debugw(ctx, "no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400712 }
713 return nil
714}
715
Kent Hagerman2b216042020-04-03 18:28:56 -0400716func (dMgr *Manager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400717 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
718 // 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 +0530719 // 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 -0400720 // the adapter proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500721 response := utils.NewResponse()
Kent Hagerman2b216042020-04-03 18:28:56 -0400722 ch, err := dMgr.adapterProxy.ReconcileDevice(ctx, device)
khenaidoo442e7c72020-03-10 16:13:48 -0400723 if err != nil {
724 response.Error(err)
725 }
726 // Wait for adapter response in its own routine
727 go func() {
728 resp, ok := <-ch
729 if !ok {
730 response.Error(status.Errorf(codes.Aborted, "channel-closed-device: %s", device.Id))
731 } else if resp.Err != nil {
732 response.Error(resp.Err)
khenaidooba6b6c42019-08-02 09:11:56 -0400733 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500734 response.Done()
khenaidoo442e7c72020-03-10 16:13:48 -0400735 }()
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500736 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400737}
738
Kent Hagerman2b216042020-04-03 18:28:56 -0400739func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID string) error {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400740 if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500741 responses := make([]utils.Response, 0)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400742 for _, port := range parentDevicePorts {
khenaidooba6b6c42019-08-02 09:11:56 -0400743 for _, peer := range port.Peers {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400744 if childDevice, err := dMgr.getDeviceFromModel(ctx, peer.DeviceId); err == nil {
npujar467fe752020-01-16 20:17:45 +0530745 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400746 }
747 }
748 }
749 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500750 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400751 return status.Errorf(codes.Aborted, "errors-%s", res)
752 }
753 }
754 return nil
755}
756
Kent Hagerman2b216042020-04-03 18:28:56 -0400757func (dMgr *Manager) UpdateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000758 logger.Debugw(ctx, "UpdateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530759 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
760 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400761 }
762 return status.Errorf(codes.NotFound, "%s", device.Id)
763}
764
khenaidoo0db4c812020-05-27 15:27:30 -0400765func (dMgr *Manager) addPeerPort(ctx context.Context, deviceID string, port *voltha.Port) error {
766 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
767 for _, peerPort := range port.Peers {
768 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
769 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
770 return err
771 }
772 }
773 }
774 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
775 // then a logical port will be added to the logical device and the device route generated. If the port is a
776 // PON port then only the device graph will be generated.
Kent Hagermancba2f302020-07-28 13:37:36 -0400777 device, err := dMgr.getDeviceReadOnly(ctx, deviceID)
khenaidoo0db4c812020-05-27 15:27:30 -0400778 if err != nil {
779 return err
780 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400781 ports, err := dMgr.listDevicePorts(ctx, deviceID)
782 if err != nil {
783 return err
784 }
785 if err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, ports, port); err != nil {
khenaidoo0db4c812020-05-27 15:27:30 -0400786 return err
787 }
788 return nil
789}
790
Kent Hagerman2b216042020-04-03 18:28:56 -0400791func (dMgr *Manager) AddPort(ctx context.Context, deviceID string, port *voltha.Port) error {
npujar467fe752020-01-16 20:17:45 +0530792 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530793 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530794 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400795 return err
796 }
khenaidoo0db4c812020-05-27 15:27:30 -0400797 // Setup peer ports in its own routine
798 go func() {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000799 if err := dMgr.addPeerPort(context.Background(), deviceID, port); err != nil {
800 logger.Errorw(ctx, "unable-to-add-peer-port", log.Fields{"error": err, "device-id": deviceID})
khenaidoo92e62c52018-10-03 14:02:54 -0400801 }
khenaidoo0db4c812020-05-27 15:27:30 -0400802 }()
khenaidoo92e62c52018-10-03 14:02:54 -0400803 return nil
khenaidoob9203542018-09-17 22:56:37 -0400804 }
npujar1d86a522019-11-14 17:11:16 +0530805 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400806}
807
Kent Hagerman2b216042020-04-03 18:28:56 -0400808func (dMgr *Manager) addFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000809 logger.Debugw(ctx, "addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530810 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
811 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400812 }
npujar1d86a522019-11-14 17:11:16 +0530813 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400814}
815
khenaidoo787224a2020-04-16 18:08:47 -0400816// deleteParentFlows removes flows from the parent device based on specific attributes
817func (dMgr *Manager) deleteParentFlows(ctx context.Context, deviceID string, uniPort uint32, metadata *voltha.FlowMetadata) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000818 logger.Debugw(ctx, "deleteParentFlows", log.Fields{"device-id": deviceID, "uni-port": uniPort, "metadata": metadata})
khenaidoo787224a2020-04-16 18:08:47 -0400819 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400820 if !agent.isRootDevice {
khenaidoo787224a2020-04-16 18:08:47 -0400821 return status.Errorf(codes.FailedPrecondition, "not-a-parent-device-%s", deviceID)
822 }
823 return agent.filterOutFlows(ctx, uniPort, metadata)
824 }
825 return status.Errorf(codes.NotFound, "%s", deviceID)
826}
827
Kent Hagerman2b216042020-04-03 18:28:56 -0400828func (dMgr *Manager) deleteFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000829 logger.Debugw(ctx, "deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530830 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
831 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400832 }
npujar1d86a522019-11-14 17:11:16 +0530833 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400834}
835
Kent Hagerman2b216042020-04-03 18:28:56 -0400836func (dMgr *Manager) updateFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000837 logger.Debugw(ctx, "updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530838 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
839 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400840 }
npujar1d86a522019-11-14 17:11:16 +0530841 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400842}
843
Kent Hagerman45a13e42020-04-13 12:23:50 -0400844// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
khenaidoob3127472019-07-24 21:04:55 -0400845// following a user action
Kent Hagerman45a13e42020-04-13 12:23:50 -0400846func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
847 if configs.Id == "" {
848 return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
khenaidoob3127472019-07-24 21:04:55 -0400849 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400850 agent := dMgr.getDeviceAgent(ctx, configs.Id)
851 if agent == nil {
852 return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
853 }
854 return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
khenaidoob3127472019-07-24 21:04:55 -0400855}
856
Kent Hagerman2b216042020-04-03 18:28:56 -0400857// InitPmConfigs initialize the pm configs as defined by the adapter.
858func (dMgr *Manager) InitPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400859 if pmConfigs.Id == "" {
860 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
861 }
npujar467fe752020-01-16 20:17:45 +0530862 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
863 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400864 }
npujar1d86a522019-11-14 17:11:16 +0530865 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400866}
867
Kent Hagerman45a13e42020-04-13 12:23:50 -0400868// ListDevicePmConfigs returns pm configs of device
869func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
870 agent := dMgr.getDeviceAgent(ctx, id.Id)
871 if agent == nil {
872 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob3127472019-07-24 21:04:55 -0400873 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400874 return agent.listPmConfigs(ctx)
khenaidoob3127472019-07-24 21:04:55 -0400875}
876
Kent Hagerman2b216042020-04-03 18:28:56 -0400877func (dMgr *Manager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000878 logger.Debugw(ctx, "getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530879 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400880 return agent.getSwitchCapability(ctx)
881 }
npujar1d86a522019-11-14 17:11:16 +0530882 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400883}
884
Kent Hagerman2b216042020-04-03 18:28:56 -0400885func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000886 logger.Debugw(ctx, "GetPorts", log.Fields{"deviceid": deviceID, "portType": portType})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400887 agent := dMgr.getDeviceAgent(ctx, deviceID)
888 if agent == nil {
889 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400890 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400891 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400892}
893
Kent Hagerman2b216042020-04-03 18:28:56 -0400894func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000895 logger.Debugw(ctx, "UpdateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530896 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
897 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400898 }
npujar1d86a522019-11-14 17:11:16 +0530899 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400900}
901
Kent Hagerman2b216042020-04-03 18:28:56 -0400902func (dMgr *Manager) UpdateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000903 logger.Debugw(ctx, "UpdateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400904 parentDevicePorts, err := dMgr.listDevicePorts(ctx, deviceID)
905 if err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400906 return status.Errorf(codes.Aborted, "%s", err.Error())
907 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400908 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
npujar467fe752020-01-16 20:17:45 +0530909 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
910 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530911 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400912 }
913 }
914 }
915 return nil
916}
917
Kent Hagerman2b216042020-04-03 18:28:56 -0400918func (dMgr *Manager) UpdatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000919 logger.Debugw(ctx, "UpdatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530920 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
921 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000922 logger.Errorw(ctx, "updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400923 return err
924 }
925 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800926 // Do this for NNI and UNIs only. PON ports are not known by logical device
927 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
928 go func() {
929 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
930 if err != nil {
931 // While we want to handle (catch) and log when
932 // an update to a port was not able to be
933 // propagated to the logical port, we can report
934 // it as a warning and not an error because it
935 // doesn't stop or modify processing.
936 // TODO: VOL-2707
Rohan Agrawal31f21802020-06-12 05:38:46 +0000937 logger.Warnw(ctx, "unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800938 }
939 }()
940 }
khenaidoo442e7c72020-03-10 16:13:48 -0400941 return nil
khenaidoob9203542018-09-17 22:56:37 -0400942 }
npujar1d86a522019-11-14 17:11:16 +0530943 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400944}
945
Kent Hagerman2b216042020-04-03 18:28:56 -0400946func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000947 logger.Debugw(ctx, "DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530948 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
949 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400950 return err
951 }
952 // Notify the logical device manager to remove all logical ports, if needed.
Kent Hagerman2b216042020-04-03 18:28:56 -0400953 // At this stage the device itself may gave been deleted already at a DeleteAllPorts
khenaidoo0a822f92019-05-08 15:15:57 -0400954 // typically is part of a device deletion phase.
Kent Hagermancba2f302020-07-28 13:37:36 -0400955 if device, err := dMgr.getDeviceReadOnly(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530956 go func() {
Kent Hagermancba2f302020-07-28 13:37:36 -0400957 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(context.Background(), device); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000958 logger.Errorw(ctx, "unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530959 }
960 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400961 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000962 logger.Warnw(ctx, "failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400963 return err
964 }
965 return nil
966 }
npujar1d86a522019-11-14 17:11:16 +0530967 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400968}
969
Kent Hagerman2b216042020-04-03 18:28:56 -0400970//UpdatePortsState updates all ports on the device
Kent Hagerman2a07b862020-06-19 15:23:07 -0400971func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, portTypeFilter uint32, state voltha.OperStatus_Types) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000972 logger.Debugw(ctx, "UpdatePortsState", log.Fields{"deviceid": deviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400973 agent := dMgr.getDeviceAgent(ctx, deviceID)
974 if agent == nil {
975 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400976 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400977 if state != voltha.OperStatus_ACTIVE && state != voltha.OperStatus_UNKNOWN {
978 return status.Error(codes.Unimplemented, "state-change-not-implemented")
979 }
980 if err := agent.updatePortsOperState(ctx, portTypeFilter, state); err != nil {
981 logger.Warnw(ctx, "updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
982 return err
983 }
984 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400985}
986
Kent Hagerman2b216042020-04-03 18:28:56 -0400987func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530988 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000989 logger.Debugw(ctx, "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 -0700990
npujar1d86a522019-11-14 17:11:16 +0530991 if deviceType == "" && vendorID != "" {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000992 logger.Debug(ctx, "device-type-is-nil-fetching-device-type")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400993 deviceTypes, err := dMgr.adapterMgr.ListDeviceTypes(ctx, nil)
994 if err != nil {
995 return nil, err
996 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400997 OLoop:
Kent Hagerman45a13e42020-04-13 12:23:50 -0400998 for _, dType := range deviceTypes.Items {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400999 for _, v := range dType.VendorIds {
1000 if v == vendorID {
1001 deviceType = dType.Adapter
1002 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001003 }
1004 }
1005 }
1006 }
1007 //if no match found for the vendorid,report adapter with the custom error message
1008 if deviceType == "" {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001009 logger.Errorw(ctx, "failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +05301010 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001011 }
khenaidoob9203542018-09-17 22:56:37 -04001012
1013 // Create the ONU device
1014 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -04001015 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +05301016 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -04001017 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +05301018 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -05001019 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -04001020 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001021
khenaidoo442e7c72020-03-10 16:13:48 -04001022 // Get parent device type
1023 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
1024 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +05301025 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001026 }
khenaidoo442e7c72020-03-10 16:13:48 -04001027 if pAgent.deviceType == "" {
1028 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
1029 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001030
npujar467fe752020-01-16 20:17:45 +05301031 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001032 logger.Warnw(ctx, "child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001033 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001034 }
1035
khenaidoo442e7c72020-03-10 16:13:48 -04001036 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001037
1038 // Create and start a device agent for that device
Mahir Gunyel03de0d32020-06-03 01:36:59 -07001039 agent := newAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -04001040 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001041 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001042 logger.Errorw(ctx, "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 -08001043 return nil, err
1044 }
khenaidoo442e7c72020-03-10 16:13:48 -04001045 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001046
1047 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301048 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301049 go func() {
npujar467fe752020-01-16 20:17:45 +05301050 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301051 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001052 logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301053 }
1054 }()
khenaidoob9203542018-09-17 22:56:37 -04001055 }
1056
Scott Baker80678602019-11-14 16:57:36 -08001057 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001058}
1059
Kent Hagerman2b216042020-04-03 18:28:56 -04001060func (dMgr *Manager) processTransition(ctx context.Context, device *voltha.Device, previousState *deviceState) error {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001061 // This will be triggered on every state update
Rohan Agrawal31f21802020-06-12 05:38:46 +00001062 logger.Debugw(ctx, "state-transition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001063 "device": device.Id,
1064 "prev-admin-state": previousState.Admin,
1065 "prev-oper-state": previousState.Operational,
1066 "prev-conn-state": previousState.Connection,
1067 "curr-admin-state": device.AdminState,
1068 "curr-oper-state": device.OperStatus,
1069 "curr-conn-state": device.ConnectStatus,
1070 })
Rohan Agrawal31f21802020-06-12 05:38:46 +00001071 handlers := dMgr.stateTransitions.GetTransitionHandler(ctx, device, previousState)
khenaidoo92e62c52018-10-03 14:02:54 -04001072 if handlers == nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001073 logger.Debugw(ctx, "no-op-transition", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001074 return nil
khenaidoob9203542018-09-17 22:56:37 -04001075 }
Rohan Agrawal31f21802020-06-12 05:38:46 +00001076 logger.Debugw(ctx, "handler-found", log.Fields{"num-expectedHandlers": len(handlers), "isParent": device.Root, "current-data": device, "previous-state": previousState})
khenaidoo92e62c52018-10-03 14:02:54 -04001077 for _, handler := range handlers {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001078 logger.Debugw(ctx, "running-handler", log.Fields{"handler": funcName(handler)})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001079 if err := handler(ctx, device); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001080 logger.Warnw(ctx, "handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001081 return err
1082 }
1083 }
khenaidoob9203542018-09-17 22:56:37 -04001084 return nil
1085}
1086
Kent Hagerman2b216042020-04-03 18:28:56 -04001087func (dMgr *Manager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001088 logger.Debugw(ctx, "packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301089 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1090 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001091 }
npujar1d86a522019-11-14 17:11:16 +05301092 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001093}
1094
npujar1d86a522019-11-14 17:11:16 +05301095// PacketIn receives packet from adapter
Kent Hagerman2b216042020-04-03 18:28:56 -04001096func (dMgr *Manager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001097 logger.Debugw(ctx, "PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001098 // Get the logical device Id based on the deviceId
1099 var device *voltha.Device
1100 var err error
Kent Hagermancba2f302020-07-28 13:37:36 -04001101 if device, err = dMgr.getDeviceReadOnly(ctx, deviceID); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001102 logger.Errorw(ctx, "device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001103 return err
1104 }
khenaidoo43c82122018-11-22 18:38:28 -05001105 if !device.Root {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001106 logger.Errorw(ctx, "device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301107 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001108 }
1109
npujar467fe752020-01-16 20:17:45 +05301110 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001111 return err
1112 }
1113 return nil
1114}
1115
Kent Hagerman2b216042020-04-03 18:28:56 -04001116func (dMgr *Manager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001117 logger.Debugw(ctx, "setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301118 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1119 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001120 }
1121 return status.Errorf(codes.NotFound, "%s", device.Id)
1122}
1123
npujar1d86a522019-11-14 17:11:16 +05301124// CreateLogicalDevice creates logical device in core
Kent Hagerman2b216042020-04-03 18:28:56 -04001125func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001126 logger.Info(ctx, "CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001127 // Verify whether the logical device has already been created
1128 if cDevice.ParentId != "" {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001129 logger.Debugw(ctx, "Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001130 return nil
1131 }
khenaidoob9203542018-09-17 22:56:37 -04001132 var err error
npujar467fe752020-01-16 20:17:45 +05301133 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001134 logger.Warnw(ctx, "createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001135 return err
1136 }
khenaidoob9203542018-09-17 22:56:37 -04001137 return nil
1138}
1139
npujar1d86a522019-11-14 17:11:16 +05301140// DeleteLogicalDevice deletes logical device from core
Kent Hagerman2b216042020-04-03 18:28:56 -04001141func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001142 logger.Info(ctx, "DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001143 var err error
npujar467fe752020-01-16 20:17:45 +05301144 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001145 logger.Warnw(ctx, "deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001146 return err
1147 }
1148 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301149 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301150 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001151 return nil
1152}
1153
npujar1d86a522019-11-14 17:11:16 +05301154// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagerman2b216042020-04-03 18:28:56 -04001155func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001156 logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001157 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001158 // Just log the error. The logical device or port may already have been deleted before this callback is invoked.
Rohan Agrawal31f21802020-06-12 05:38:46 +00001159 logger.Warnw(ctx, "deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001160 }
1161 return nil
1162}
1163
Kent Hagerman2b216042020-04-03 18:28:56 -04001164func (dMgr *Manager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001165 // Sanity check
1166 if childDevice.Root {
1167 // childDevice is the parent device
1168 return childDevice
1169 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001170 parentDevice, _ := dMgr.getDeviceReadOnly(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001171 return parentDevice
1172}
1173
Kent Hagerman2b216042020-04-03 18:28:56 -04001174//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 -04001175//cannot manage the child devices. This will trigger the Core to disable all the child devices.
Kent Hagerman2b216042020-04-03 18:28:56 -04001176func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001177 logger.Debug(ctx, "ChildDevicesLost")
Kent Hagermancba2f302020-07-28 13:37:36 -04001178 parentDevice, err := dMgr.getDeviceReadOnly(ctx, parentDeviceID)
Kent Hagerman2a07b862020-06-19 15:23:07 -04001179 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001180 logger.Warnw(ctx, "failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001181 return err
1182 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001183 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001184}
1185
Kent Hagerman2b216042020-04-03 18:28:56 -04001186//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
khenaidoo0a822f92019-05-08 15:15:57 -04001187// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
Kent Hagerman2b216042020-04-03 18:28:56 -04001188func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001189 logger.Debug(ctx, "ChildDevicesDetected")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001190 parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
1191 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001192 logger.Warnw(ctx, "failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001193 return err
1194 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001195 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
khenaidoo0a822f92019-05-08 15:15:57 -04001196 if len(childDeviceIds) == 0 {
Kent Hagerman2a07b862020-06-19 15:23:07 -04001197 logger.Debugw(ctx, "no-child-device", log.Fields{"parentDeviceId": parentDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001198 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001199 allChildEnableRequestSent := true
Kent Hagerman2a07b862020-06-19 15:23:07 -04001200 for childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301201 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001202 // Run the children re-registration in its own routine
Kent Hagerman2a07b862020-06-19 15:23:07 -04001203 go func(ctx context.Context) {
1204 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301205 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001206 logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301207 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001208 }(context.Background())
khenaidoo59ef7be2019-06-21 12:40:28 -04001209 } else {
npujar1d86a522019-11-14 17:11:16 +05301210 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Kent Hagerman2a07b862020-06-19 15:23:07 -04001211 logger.Errorw(ctx, "no-child-device-agent", log.Fields{"parentDeviceId": parentDeviceID, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001212 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001213 }
1214 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001215 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001216 return err
1217 }
1218 return nil
1219}
1220
khenaidoo4d4802d2018-10-04 21:59:49 -04001221/*
1222All the functions below are callback functions where they are invoked with the latest and previous data. We can
1223therefore use the data as is without trying to get the latest from the model.
1224*/
1225
khenaidoo0a822f92019-05-08 15:15:57 -04001226//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagerman2b216042020-04-03 18:28:56 -04001227func (dMgr *Manager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001228 logger.Debug(ctx, "DisableAllChildDevices")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001229 ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
1230 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
npujar467fe752020-01-16 20:17:45 +05301231 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -04001232 if err := agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001233 // Just log the error - this error happens only if the child device was already in deleted state.
Rohan Agrawal31f21802020-06-12 05:38:46 +00001234 logger.Errorw(ctx, "failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001235 }
1236 }
1237 }
1238 return nil
1239}
1240
khenaidoo0a822f92019-05-08 15:15:57 -04001241//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001242func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001243 logger.Debug(ctx, "DeleteAllChildDevices")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001244 ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
1245 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
npujar467fe752020-01-16 20:17:45 +05301246 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -04001247 if err := agent.deleteDevice(ctx); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001248 logger.Warnw(ctx, "failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001249 }
khenaidoo49085352020-01-13 19:15:43 -05001250 // No further action is required here. The deleteDevice will change the device state where the resulting
1251 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001252 }
1253 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001254 return nil
1255}
1256
Girish Gowdra408cd962020-03-11 14:31:31 -07001257//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001258func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001259 logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001260 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001261 // Just log error as logical device may already have been deleted
Rohan Agrawal31f21802020-06-12 05:38:46 +00001262 logger.Warnw(ctx, "delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001263 }
1264 return nil
1265}
1266
1267//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001268func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001269 logger.Debugw(ctx, "delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001270 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1271 if err := agent.deleteAllFlows(ctx); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001272 logger.Errorw(ctx, "error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001273 return err
1274 }
1275 return nil
1276 }
1277 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1278}
1279
khenaidoo4d4802d2018-10-04 21:59:49 -04001280//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
Kent Hagerman2a07b862020-06-19 15:23:07 -04001281func (dMgr *Manager) getAllChildDeviceIds(ctx context.Context, parentDevicePorts map[uint32]*voltha.Port) map[string]struct{} {
1282 logger.Debug(ctx, "getAllChildDeviceIds")
1283 childDeviceIds := make(map[string]struct{}, len(parentDevicePorts))
1284 for _, port := range parentDevicePorts {
1285 for _, peer := range port.Peers {
1286 childDeviceIds[peer.DeviceId] = struct{}{}
khenaidoo92e62c52018-10-03 14:02:54 -04001287 }
1288 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001289 logger.Debugw(ctx, "returning-getAllChildDeviceIds", log.Fields{"childDeviceIds": childDeviceIds})
1290 return childDeviceIds
khenaidoo92e62c52018-10-03 14:02:54 -04001291}
1292
Kent Hagerman2b216042020-04-03 18:28:56 -04001293//GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1294func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001295 logger.Debugw(ctx, "GetAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -04001296 if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001297 childDevices := make([]*voltha.Device, 0)
Kent Hagerman2a07b862020-06-19 15:23:07 -04001298 for deviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
Kent Hagermancba2f302020-07-28 13:37:36 -04001299 if d, e := dMgr.getDeviceReadOnly(ctx, deviceID); e == nil && d != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -04001300 childDevices = append(childDevices, d)
khenaidoo297cd252019-02-07 22:10:23 -05001301 }
1302 }
1303 return &voltha.Devices{Items: childDevices}, nil
1304 }
npujar1d86a522019-11-14 17:11:16 +05301305 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001306}
1307
npujar1d86a522019-11-14 17:11:16 +05301308// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagerman2b216042020-04-03 18:28:56 -04001309func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Kent Hagermanf6db9f12020-07-22 17:16:19 -04001310 logger.Info(ctx, "SetupUNILogicalPorts")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001311 cDevicePorts, err := dMgr.listDevicePorts(ctx, cDevice.Id)
1312 if err != nil {
1313 return err
1314 }
1315 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice, cDevicePorts); err != nil {
Kent Hagermanf6db9f12020-07-22 17:16:19 -04001316 logger.Warnw(ctx, "setupUNILogicalPorts-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001317 return err
1318 }
1319 return nil
1320}
1321
Kent Hagerman45a13e42020-04-13 12:23:50 -04001322// convenience to avoid redefining
1323var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
1324
1325// DownloadImage execute an image download request
1326func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001327 logger.Debugw(ctx, "DownloadImage", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001328 agent := dMgr.getDeviceAgent(ctx, img.Id)
1329 if agent == nil {
1330 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001331 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001332 resp, err := agent.downloadImage(ctx, img)
1333 if err != nil {
1334 return operationFailureResp, err
1335 }
1336 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001337}
1338
Kent Hagerman45a13e42020-04-13 12:23:50 -04001339// CancelImageDownload cancels image download request
1340func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001341 logger.Debugw(ctx, "CancelImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001342 agent := dMgr.getDeviceAgent(ctx, img.Id)
1343 if agent == nil {
1344 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001345 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001346 resp, err := agent.cancelImageDownload(ctx, img)
1347 if err != nil {
1348 return operationFailureResp, err
1349 }
1350 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001351}
1352
Kent Hagerman45a13e42020-04-13 12:23:50 -04001353// ActivateImageUpdate activates image update request
1354func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001355 logger.Debugw(ctx, "ActivateImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001356 agent := dMgr.getDeviceAgent(ctx, img.Id)
1357 if agent == nil {
1358 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001359 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001360 resp, err := agent.activateImage(ctx, img)
1361 if err != nil {
1362 return operationFailureResp, err
1363 }
1364 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001365}
1366
Kent Hagerman45a13e42020-04-13 12:23:50 -04001367// RevertImageUpdate reverts image update
1368func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001369 logger.Debugw(ctx, "RevertImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001370 agent := dMgr.getDeviceAgent(ctx, img.Id)
1371 if agent == nil {
1372 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001373 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001374 resp, err := agent.revertImage(ctx, img)
1375 if err != nil {
1376 return operationFailureResp, err
1377 }
1378 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001379}
1380
Kent Hagerman45a13e42020-04-13 12:23:50 -04001381// convenience to avoid redefining
1382var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
1383
1384// GetImageDownloadStatus returns status of image download
1385func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001386 logger.Debugw(ctx, "GetImageDownloadStatus", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001387 agent := dMgr.getDeviceAgent(ctx, img.Id)
1388 if agent == nil {
1389 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001390 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001391 resp, err := agent.getImageDownloadStatus(ctx, img)
1392 if err != nil {
1393 return imageDownloadFailureResp, err
1394 }
1395 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001396}
1397
Kent Hagerman2b216042020-04-03 18:28:56 -04001398func (dMgr *Manager) UpdateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001399 logger.Debugw(ctx, "UpdateImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301400 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1401 if err := agent.updateImageDownload(ctx, img); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001402 logger.Debugw(ctx, "UpdateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001403 return err
1404 }
1405 } else {
1406 return status.Errorf(codes.NotFound, "%s", img.Id)
1407 }
1408 return nil
1409}
1410
Kent Hagerman45a13e42020-04-13 12:23:50 -04001411// GetImageDownload returns image download
Kent Hagerman2b216042020-04-03 18:28:56 -04001412func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001413 logger.Debugw(ctx, "GetImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001414 agent := dMgr.getDeviceAgent(ctx, img.Id)
1415 if agent == nil {
1416 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001417 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001418 resp, err := agent.getImageDownload(ctx, img)
1419 if err != nil {
1420 return imageDownloadFailureResp, err
1421 }
1422 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001423}
1424
Kent Hagerman45a13e42020-04-13 12:23:50 -04001425// ListImageDownloads returns image downloads
1426func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001427 logger.Debugw(ctx, "ListImageDownloads", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001428 agent := dMgr.getDeviceAgent(ctx, id.Id)
1429 if agent == nil {
1430 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001431 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001432 resp, err := agent.listImageDownloads(ctx, id.Id)
1433 if err != nil {
1434 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
1435 }
1436 return resp, nil
1437}
1438
1439// GetImages returns all images for a specific device entry
1440func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001441 logger.Debugw(ctx, "GetImages", log.Fields{"device-id": id.Id})
Kent Hagermancba2f302020-07-28 13:37:36 -04001442 device, err := dMgr.getDeviceReadOnly(ctx, id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -04001443 if err != nil {
1444 return nil, err
1445 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001446 return device.Images, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001447}
1448
Rohan Agrawal31f21802020-06-12 05:38:46 +00001449func (dMgr *Manager) NotifyInvalidTransition(ctx context.Context, device *voltha.Device) error {
1450 logger.Errorw(ctx, "NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001451 "device": device.Id,
1452 "curr-admin-state": device.AdminState,
1453 "curr-oper-state": device.OperStatus,
1454 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001455 })
khenaidoo0a822f92019-05-08 15:15:57 -04001456 //TODO: notify over kafka?
1457 return nil
1458}
1459
khenaidoob9203542018-09-17 22:56:37 -04001460func funcName(f interface{}) string {
1461 p := reflect.ValueOf(f).Pointer()
1462 rf := runtime.FuncForPC(p)
1463 return rf.Name()
1464}
1465
npujar1d86a522019-11-14 17:11:16 +05301466// UpdateDeviceAttribute updates value of particular device attribute
Kent Hagerman2b216042020-04-03 18:28:56 -04001467func (dMgr *Manager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301468 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -04001469 agent.(*Agent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001470 }
1471}
1472
npujar1d86a522019-11-14 17:11:16 +05301473// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -04001474func (dMgr *Manager) GetParentDeviceID(ctx context.Context, deviceID string) string {
Kent Hagermancba2f302020-07-28 13:37:36 -04001475 if device, _ := dMgr.getDeviceReadOnly(ctx, deviceID); device != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001476 logger.Infow(ctx, "GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001477 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001478 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001479 return ""
khenaidoob9203542018-09-17 22:56:37 -04001480}
serkant.uluderya334479d2019-04-10 08:26:15 -07001481
Kent Hagerman45a13e42020-04-13 12:23:50 -04001482func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001483 logger.Debugw(ctx, "SimulateAlarm", log.Fields{"id": simulateReq.Id, "Indicator": simulateReq.Indicator, "IntfId": simulateReq.IntfId,
Kent Hagerman45a13e42020-04-13 12:23:50 -04001484 "PortTypeName": simulateReq.PortTypeName, "OnuDeviceId": simulateReq.OnuDeviceId, "InverseBitErrorRate": simulateReq.InverseBitErrorRate,
1485 "Drift": simulateReq.Drift, "NewEqd": simulateReq.NewEqd, "OnuSerialNumber": simulateReq.OnuSerialNumber, "Operation": simulateReq.Operation})
1486 agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
1487 if agent == nil {
1488 return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
serkant.uluderya334479d2019-04-10 08:26:15 -07001489 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001490 if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
1491 return nil, err
1492 }
1493 return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
serkant.uluderya334479d2019-04-10 08:26:15 -07001494}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001495
Kent Hagerman2b216042020-04-03 18:28:56 -04001496func (dMgr *Manager) UpdateDeviceReason(ctx context.Context, deviceID string, reason string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001497 logger.Debugw(ctx, "UpdateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301498 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1499 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001500 }
npujar1d86a522019-11-14 17:11:16 +05301501 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001502}
kesavandbc2d1622020-01-21 00:42:01 -05001503
Kent Hagerman45a13e42020-04-13 12:23:50 -04001504func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001505 logger.Debugw(ctx, "EnablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001506 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1507 if agent == nil {
1508 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001509 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001510 return &empty.Empty{}, agent.enablePort(ctx, port.PortNo)
kesavandbc2d1622020-01-21 00:42:01 -05001511}
1512
Kent Hagerman45a13e42020-04-13 12:23:50 -04001513func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001514 logger.Debugw(ctx, "DisablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001515 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1516 if agent == nil {
1517 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001518 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001519 return &empty.Empty{}, agent.disablePort(ctx, port.PortNo)
kesavandbc2d1622020-01-21 00:42:01 -05001520}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001521
Kent Hagerman2b216042020-04-03 18:28:56 -04001522// ChildDeviceLost calls parent adapter to delete child device and all its references
1523func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001524 logger.Debugw(ctx, "childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001525 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001526 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1527 // Just log the message and let the remaining pipeline proceed.
Rohan Agrawal31f21802020-06-12 05:38:46 +00001528 logger.Warnw(ctx, "childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001529 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001530 }
khenaidooe132f522020-03-20 15:23:15 -04001531 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1532 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001533}
onkarkundargi87285252020-01-27 11:34:52 +05301534
Kent Hagerman45a13e42020-04-13 12:23:50 -04001535func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001536 logger.Debugw(ctx, "StartOmciTestAction", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001537 agent := dMgr.getDeviceAgent(ctx, request.Id)
1538 if agent == nil {
1539 return nil, status.Errorf(codes.NotFound, "%s", request.Id)
onkarkundargi87285252020-01-27 11:34:52 +05301540 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001541 return agent.startOmciTest(ctx, request)
onkarkundargi87285252020-01-27 11:34:52 +05301542}
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001543
1544func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
1545 log.Debugw("getExtValue", log.Fields{"onu-id": value.Id})
Kent Hagermancba2f302020-07-28 13:37:36 -04001546 cDevice, err := dMgr.getDeviceReadOnly(ctx, value.Id)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001547 if err != nil {
1548 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1549 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001550 pDevice, err := dMgr.getDeviceReadOnly(ctx, cDevice.ParentId)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001551 if err != nil {
1552 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1553 }
1554 if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
1555 resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
1556 if err != nil {
1557 return nil, err
1558 }
1559 log.Debugw("getExtValue-result", log.Fields{"result": resp})
1560 return resp, nil
1561 }
1562 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1563
1564}