blob: 389962363dcb1866796c6e3dd95f02b2b1e91881 [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 "sync"
23 "time"
24
Kent Hagerman45a13e42020-04-13 12:23:50 -040025 "github.com/golang/protobuf/ptypes/empty"
sbarbari17d7e222019-11-05 10:02:29 -050026 "github.com/opencord/voltha-go/db/model"
Kent Hagerman2b216042020-04-03 18:28:56 -040027 "github.com/opencord/voltha-go/rw_core/core/adapter"
Kent Hagermanf5a67352020-04-30 15:15:26 -040028 "github.com/opencord/voltha-go/rw_core/core/device/event"
Kent Hagerman2b216042020-04-03 18:28:56 -040029 "github.com/opencord/voltha-go/rw_core/core/device/remote"
Kent Hagerman6031aad2020-07-29 16:36:33 -040030 "github.com/opencord/voltha-go/rw_core/core/device/state"
khenaidoo3d3b8c22019-05-22 18:10:39 -040031 "github.com/opencord/voltha-go/rw_core/utils"
Maninderdfadc982020-10-28 14:04:33 +053032 "github.com/opencord/voltha-lib-go/v4/pkg/kafka"
33 "github.com/opencord/voltha-lib-go/v4/pkg/log"
34 "github.com/opencord/voltha-protos/v4/go/common"
35 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
36 "github.com/opencord/voltha-protos/v4/go/openflow_13"
37 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
38 "github.com/opencord/voltha-protos/v4/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040039 "google.golang.org/grpc/codes"
40 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040041)
42
Kent Hagerman2b216042020-04-03 18:28:56 -040043// Manager represent device manager attributes
44type Manager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040045 deviceAgents sync.Map
46 rootDevices map[string]bool
47 lockRootDeviceMap sync.RWMutex
Kent Hagerman2b216042020-04-03 18:28:56 -040048 adapterProxy *remote.AdapterProxy
49 adapterMgr *adapter.Manager
50 logicalDeviceMgr *LogicalManager
npujar467fe752020-01-16 20:17:45 +053051 kafkaICProxy kafka.InterContainerProxy
Kent Hagerman6031aad2020-07-29 16:36:33 -040052 stateTransitions *state.TransitionMap
Mahir Gunyel03de0d32020-06-03 01:36:59 -070053 dbPath *model.Path
Kent Hagermanf5a67352020-04-30 15:15:26 -040054 dProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053055 coreInstanceID string
khenaidoo442e7c72020-03-10 16:13:48 -040056 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040057 devicesLoadingLock sync.RWMutex
58 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040059}
60
Mahir Gunyel03de0d32020-06-03 01:36:59 -070061//NewManagers creates the Manager and the Logical Manager.
serkant.uluderya8ff291d2020-05-20 00:58:00 -070062func 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 -040063 deviceMgr := &Manager{
Kent Hagerman2b216042020-04-03 18:28:56 -040064 rootDevices: make(map[string]bool),
65 kafkaICProxy: kmp,
serkant.uluderya8ff291d2020-05-20 00:58:00 -070066 adapterProxy: remote.NewAdapterProxy(kmp, coreTopic, endpointMgr),
Kent Hagerman2b216042020-04-03 18:28:56 -040067 coreInstanceID: coreInstanceID,
Mahir Gunyel03de0d32020-06-03 01:36:59 -070068 dbPath: dbPath,
69 dProxy: dbPath.Proxy("devices"),
Kent Hagerman2b216042020-04-03 18:28:56 -040070 adapterMgr: adapterMgr,
Kent Hagermanf4151de2020-06-19 15:58:47 -040071 defaultTimeout: defaultCoreTimeout,
Kent Hagerman2b216042020-04-03 18:28:56 -040072 deviceLoadingInProgress: make(map[string][]chan int),
73 }
Kent Hagerman6031aad2020-07-29 16:36:33 -040074 deviceMgr.stateTransitions = state.NewTransitionMap(deviceMgr)
Kent Hagerman2f0d0552020-04-23 17:28:52 -040075
Kent Hagerman2b216042020-04-03 18:28:56 -040076 logicalDeviceMgr := &LogicalManager{
Kent Hagerman45a13e42020-04-13 12:23:50 -040077 Manager: event.NewManager(),
Kent Hagerman2b216042020-04-03 18:28:56 -040078 deviceMgr: deviceMgr,
79 kafkaICProxy: kmp,
Mahir Gunyel03de0d32020-06-03 01:36:59 -070080 dbPath: dbPath,
81 ldProxy: dbPath.Proxy("logical_devices"),
Kent Hagerman2b216042020-04-03 18:28:56 -040082 defaultTimeout: defaultCoreTimeout,
83 logicalDeviceLoadingInProgress: make(map[string][]chan int),
84 }
85 deviceMgr.logicalDeviceMgr = logicalDeviceMgr
Matteo Scandolod525ae32020-04-02 17:27:29 -070086
Kent Hagerman2b216042020-04-03 18:28:56 -040087 adapterMgr.SetAdapterRestartedCallback(deviceMgr.adapterRestarted)
Matteo Scandolod525ae32020-04-02 17:27:29 -070088
Kent Hagerman2b216042020-04-03 18:28:56 -040089 return deviceMgr, logicalDeviceMgr
khenaidoob9203542018-09-17 22:56:37 -040090}
91
Kent Hagerman2b216042020-04-03 18:28:56 -040092func (dMgr *Manager) addDeviceAgentToMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +053093 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
94 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -040095 }
khenaidoo2c6a0992019-04-29 13:46:56 -040096 dMgr.lockRootDeviceMap.Lock()
97 defer dMgr.lockRootDeviceMap.Unlock()
Kent Hagerman2a07b862020-06-19 15:23:07 -040098 dMgr.rootDevices[agent.deviceID] = agent.isRootDevice
khenaidoo2c6a0992019-04-29 13:46:56 -040099
khenaidoob9203542018-09-17 22:56:37 -0400100}
101
Kent Hagerman2b216042020-04-03 18:28:56 -0400102func (dMgr *Manager) deleteDeviceAgentFromMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +0530103 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400104 dMgr.lockRootDeviceMap.Lock()
105 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530106 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400107}
108
khenaidoo297cd252019-02-07 22:10:23 -0500109// 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 -0400110func (dMgr *Manager) getDeviceAgent(ctx context.Context, deviceID string) *Agent {
npujar1d86a522019-11-14 17:11:16 +0530111 agent, ok := dMgr.deviceAgents.Load(deviceID)
112 if ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400113 return agent.(*Agent)
khenaidoob9203542018-09-17 22:56:37 -0400114 }
khenaidoo442e7c72020-03-10 16:13:48 -0400115 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530116 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530117 if err == nil {
118 agent, ok = dMgr.deviceAgents.Load(deviceID)
119 if !ok {
120 return nil
121 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400122 return agent.(*Agent)
npujar1d86a522019-11-14 17:11:16 +0530123 }
124 //TODO: Change the return params to return an error as well
divyadesaicb8b59d2020-08-18 09:55:47 +0000125 logger.Errorw(ctx, "loading-device-failed", log.Fields{"device-id": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400126 return nil
127}
128
khenaidoo297cd252019-02-07 22:10:23 -0500129// listDeviceIdsFromMap returns the list of device IDs that are in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400130func (dMgr *Manager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500131 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400132
133 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
134 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
135 return true
136 })
137
khenaidoo7ccedd52018-12-14 16:48:54 -0500138 return result
139}
140
Kent Hagerman45a13e42020-04-13 12:23:50 -0400141// CreateDevice creates a new parent device in the data model
142func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
143 if device.MacAddress == "" && device.GetHostAndPort() == "" {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000144 logger.Errorf(ctx, "No Device Info Present")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400145 return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
146 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000147 logger.Debugw(ctx, "create-device", log.Fields{"device": *device})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400148
npujar467fe752020-01-16 20:17:45 +0530149 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530150 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000151 logger.Errorf(ctx, "Failed to fetch parent device info")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400152 return nil, err
Thomas Lee Se5a44012019-11-07 20:32:24 +0530153 }
154 if deviceExist {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000155 logger.Errorf(ctx, "Device is Pre-provisioned already with same IP-Port or MAC Address")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400156 return nil, errors.New("device is already pre-provisioned")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530157 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000158 logger.Debugw(ctx, "CreateDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400159
khenaidoo5e677ae2019-02-28 17:26:29 -0500160 // Ensure this device is set as root
161 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400162 // Create and start a device agent for that device
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700163 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530164 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800165 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000166 logger.Errorw(ctx, "Fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400167 return nil, err
Scott Baker80678602019-11-14 16:57:36 -0800168 }
khenaidoo442e7c72020-03-10 16:13:48 -0400169 dMgr.addDeviceAgentToMap(agent)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400170 return device, nil
khenaidoob9203542018-09-17 22:56:37 -0400171}
172
Kent Hagerman45a13e42020-04-13 12:23:50 -0400173// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
174func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000175 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
176
Rohan Agrawal31f21802020-06-12 05:38:46 +0000177 logger.Debugw(ctx, "EnableDevice", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400178 agent := dMgr.getDeviceAgent(ctx, id.Id)
179 if agent == nil {
180 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400181 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400182 return &empty.Empty{}, agent.enableDevice(ctx)
khenaidoob9203542018-09-17 22:56:37 -0400183}
184
Kent Hagerman45a13e42020-04-13 12:23:50 -0400185// DisableDevice disables a device along with any child device it may have
186func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000187 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
188
Rohan Agrawal31f21802020-06-12 05:38:46 +0000189 logger.Debugw(ctx, "DisableDevice", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400190 agent := dMgr.getDeviceAgent(ctx, id.Id)
191 if agent == nil {
192 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400193 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400194 return &empty.Empty{}, agent.disableDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400195}
196
Kent Hagerman45a13e42020-04-13 12:23:50 -0400197//RebootDevice invoked the reboot API to the corresponding adapter
198func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000199 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
200
Rohan Agrawal31f21802020-06-12 05:38:46 +0000201 logger.Debugw(ctx, "RebootDevice", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400202 agent := dMgr.getDeviceAgent(ctx, id.Id)
203 if agent == nil {
204 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400205 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400206 return &empty.Empty{}, agent.rebootDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400207}
208
Kent Hagerman45a13e42020-04-13 12:23:50 -0400209// DeleteDevice removes a device from the data model
210func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000211 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
212
Rohan Agrawal31f21802020-06-12 05:38:46 +0000213 logger.Debugw(ctx, "DeleteDevice", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400214 agent := dMgr.getDeviceAgent(ctx, id.Id)
215 if agent == nil {
216 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400217 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400218 return &empty.Empty{}, agent.deleteDevice(ctx)
219}
220
Kent Hagerman2a07b862020-06-19 15:23:07 -0400221// GetDevicePort returns the port details for a specific device port entry
222func (dMgr *Manager) GetDevicePort(ctx context.Context, deviceID string, portID uint32) (*voltha.Port, error) {
223 logger.Debugw(ctx, "ListDevicePorts", log.Fields{"device-id": deviceID})
224 agent := dMgr.getDeviceAgent(ctx, deviceID)
225 if agent == nil {
226 return nil, status.Errorf(codes.NotFound, "device-%s", deviceID)
227 }
228 return agent.getDevicePort(portID)
229}
230
Kent Hagerman45a13e42020-04-13 12:23:50 -0400231// ListDevicePorts returns the ports details for a specific device entry
232func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000233 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
234
Rohan Agrawal31f21802020-06-12 05:38:46 +0000235 logger.Debugw(ctx, "ListDevicePorts", log.Fields{"device-id": id.Id})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400236 agent := dMgr.getDeviceAgent(ctx, id.Id)
237 if agent == nil {
238 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400239 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400240
241 ports := agent.listDevicePorts()
242 ctr, ret := 0, make([]*voltha.Port, len(ports))
243 for _, port := range ports {
244 ret[ctr] = port
245 ctr++
246 }
247 return &voltha.Ports{Items: ret}, nil
Kent Hagerman45a13e42020-04-13 12:23:50 -0400248}
249
250// ListDeviceFlows returns the flow details for a specific device entry
251func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000252 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
253
Rohan Agrawal31f21802020-06-12 05:38:46 +0000254 logger.Debugw(ctx, "ListDeviceFlows", log.Fields{"device-id": id.Id})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700255 agent := dMgr.getDeviceAgent(ctx, id.Id)
256 if agent == nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400257 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400258 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700259
260 flows := agent.listDeviceFlows()
261 ctr, ret := 0, make([]*ofp.OfpFlowStats, len(flows))
262 for _, flow := range flows {
263 ret[ctr] = flow
264 ctr++
265 }
266 return &openflow_13.Flows{Items: ret}, nil
Kent Hagerman45a13e42020-04-13 12:23:50 -0400267}
268
269// ListDeviceFlowGroups returns the flow group details for a specific device entry
270func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*voltha.FlowGroups, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000271 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
272
Rohan Agrawal31f21802020-06-12 05:38:46 +0000273 logger.Debugw(ctx, "ListDeviceFlowGroups", log.Fields{"device-id": id.Id})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700274 agent := dMgr.getDeviceAgent(ctx, id.Id)
275 if agent == nil {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400276 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
277 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700278 groups := agent.listDeviceGroups()
279 ctr, ret := 0, make([]*openflow_13.OfpGroupEntry, len(groups))
280 for _, group := range groups {
281 ret[ctr] = group
282 ctr++
283 }
284 return &voltha.FlowGroups{Items: ret}, nil
khenaidoo4d4802d2018-10-04 21:59:49 -0400285}
286
khenaidoo6d62c002019-05-15 21:57:03 -0400287// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
288// This function is called only in the Core that does not own this device. In the Core that owns this device then a
289// deletion deletion also includes removal of any reference of this device.
Kent Hagerman2b216042020-04-03 18:28:56 -0400290func (dMgr *Manager) stopManagingDevice(ctx context.Context, id string) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000291 logger.Infow(ctx, "stopManagingDevice", log.Fields{"device-id": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400292 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
Kent Hagerman6031aad2020-07-29 16:36:33 -0400293 if device, err := dMgr.getDeviceReadOnly(ctx, id); err == nil && device.Root {
khenaidoo6d62c002019-05-15 21:57:03 -0400294 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700295 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400296 }
npujar467fe752020-01-16 20:17:45 +0530297 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400298 if err := agent.stop(ctx); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000299 logger.Warnw(ctx, "unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400300 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400301 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400302 }
303 }
304}
305
npujar1d86a522019-11-14 17:11:16 +0530306// RunPostDeviceDelete removes any reference of this device
Kent Hagerman2b216042020-04-03 18:28:56 -0400307func (dMgr *Manager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000308 logger.Infow(ctx, "RunPostDeviceDelete", log.Fields{"device-id": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530309 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400310 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400311}
312
Kent Hagermancba2f302020-07-28 13:37:36 -0400313// GetDevice exists primarily to implement the gRPC interface.
314// Internal functions should call getDeviceReadOnly instead.
Kent Hagerman45a13e42020-04-13 12:23:50 -0400315func (dMgr *Manager) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000316 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Kent Hagermancba2f302020-07-28 13:37:36 -0400317 return dMgr.getDeviceReadOnly(ctx, id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400318}
319
Kent Hagermancba2f302020-07-28 13:37:36 -0400320// getDeviceReadOnly will returns a device, either from memory or from the dB, if present
321func (dMgr *Manager) getDeviceReadOnly(ctx context.Context, id string) (*voltha.Device, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000322 logger.Debugw(ctx, "getDeviceReadOnly", log.Fields{"device-id": id})
npujar467fe752020-01-16 20:17:45 +0530323 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
Kent Hagermancba2f302020-07-28 13:37:36 -0400324 return agent.getDeviceReadOnly(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400325 }
326 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400327}
328
Kent Hagerman2a07b862020-06-19 15:23:07 -0400329func (dMgr *Manager) listDevicePorts(ctx context.Context, id string) (map[uint32]*voltha.Port, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000330 logger.Debugw(ctx, "listDevicePorts", log.Fields{"device-id": id})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400331 agent := dMgr.getDeviceAgent(ctx, id)
332 if agent == nil {
333 return nil, status.Errorf(codes.NotFound, "%s", id)
334 }
335 return agent.listDevicePorts(), nil
336}
337
npujar1d86a522019-11-14 17:11:16 +0530338// GetChildDevice will return a device, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -0400339func (dMgr *Manager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000340 logger.Debugw(ctx, "GetChildDevice", log.Fields{"parent-device-id": parentDeviceID, "serialNumber": serialNumber,
npujar1d86a522019-11-14 17:11:16 +0530341 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500342
Kent Hagerman2a07b862020-06-19 15:23:07 -0400343 parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
344 if err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500345 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
346 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400347 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500348 if len(childDeviceIds) == 0 {
divyadesaicb8b59d2020-08-18 09:55:47 +0000349 logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": parentDeviceID, "serialNumber": serialNumber, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530350 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500351 }
352
353 var foundChildDevice *voltha.Device
Kent Hagerman2a07b862020-06-19 15:23:07 -0400354 for childDeviceID := range childDeviceIds {
npujar1d86a522019-11-14 17:11:16 +0530355 var found bool
Kent Hagermancba2f302020-07-28 13:37:36 -0400356 if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500357
npujar1d86a522019-11-14 17:11:16 +0530358 foundOnuID := false
359 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500360 if searchDevice.ParentPortNo == uint32(parentPortNo) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000361 logger.Debugw(ctx, "found-child-by-onuid", log.Fields{"parent-device-id": parentDeviceID, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530362 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500363 }
364 }
365
366 foundSerialNumber := false
367 if searchDevice.SerialNumber == serialNumber {
divyadesaicb8b59d2020-08-18 09:55:47 +0000368 logger.Debugw(ctx, "found-child-by-serialnumber", log.Fields{"parent-device-id": parentDeviceID, "serialNumber": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500369 foundSerialNumber = true
370 }
371
372 // if both onuId and serialNumber are provided both must be true for the device to be found
373 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530374 if onuID > 0 && serialNumber != "" {
375 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500376 } else {
npujar1d86a522019-11-14 17:11:16 +0530377 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500378 }
379
npujar1d86a522019-11-14 17:11:16 +0530380 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500381 foundChildDevice = searchDevice
382 break
383 }
384 }
385 }
386
387 if foundChildDevice != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000388 logger.Debugw(ctx, "child-device-found", log.Fields{"parent-device-id": parentDeviceID, "foundChildDevice": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500389 return foundChildDevice, nil
390 }
391
divyadesaicb8b59d2020-08-18 09:55:47 +0000392 logger.Debugw(ctx, "child-device-not-found", log.Fields{"parent-device-id": parentDeviceID,
npujar1d86a522019-11-14 17:11:16 +0530393 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
394 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500395}
396
npujar1d86a522019-11-14 17:11:16 +0530397// GetChildDeviceWithProxyAddress will return a device based on proxy address
Kent Hagerman2b216042020-04-03 18:28:56 -0400398func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000399 logger.Debugw(ctx, "GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500400
Kent Hagerman2a07b862020-06-19 15:23:07 -0400401 parentDevicePorts, err := dMgr.listDevicePorts(ctx, proxyAddress.DeviceId)
402 if err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500403 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
404 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400405 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500406 if len(childDeviceIds) == 0 {
divyadesaicb8b59d2020-08-18 09:55:47 +0000407 logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": proxyAddress.DeviceId})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500408 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
409 }
410
411 var foundChildDevice *voltha.Device
Kent Hagerman2a07b862020-06-19 15:23:07 -0400412 for childDeviceID := range childDeviceIds {
Kent Hagermancba2f302020-07-28 13:37:36 -0400413 if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500414 if searchDevice.ProxyAddress == proxyAddress {
415 foundChildDevice = searchDevice
416 break
417 }
418 }
419 }
420
421 if foundChildDevice != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000422 logger.Debugw(ctx, "child-device-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500423 return foundChildDevice, nil
424 }
425
Rohan Agrawal31f21802020-06-12 05:38:46 +0000426 logger.Warnw(ctx, "child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500427 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
428}
429
npujar1d86a522019-11-14 17:11:16 +0530430// IsDeviceInCache returns true if device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400431func (dMgr *Manager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400432 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500433 return exist
434}
435
Stephane Barbarieaa467942019-02-06 14:09:44 -0500436// ListDevices retrieves the latest devices from the data model
Kent Hagerman45a13e42020-04-13 12:23:50 -0400437func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000438 logger.Debug(ctx, "ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400439 result := &voltha.Devices{}
Kent Hagerman4f355f52020-03-30 16:01:33 -0400440
441 var devices []*voltha.Device
Kent Hagermanf5a67352020-04-30 15:15:26 -0400442 if err := dMgr.dProxy.List(ctx, &devices); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000443 logger.Errorw(ctx, "failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530444 return nil, err
445 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400446
447 for _, device := range devices {
448 // If device is not in memory then set it up
449 if !dMgr.IsDeviceInCache(device.Id) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000450 logger.Debugw(ctx, "loading-device-from-Model", log.Fields{"device-id": device.Id})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700451 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
Kent Hagerman4f355f52020-03-30 16:01:33 -0400452 if _, err := agent.start(ctx, nil); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000453 logger.Warnw(ctx, "failure-starting-agent", log.Fields{"device-id": device.Id})
Kent Hagerman4f355f52020-03-30 16:01:33 -0400454 } else {
455 dMgr.addDeviceAgentToMap(agent)
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500456 }
khenaidoob9203542018-09-17 22:56:37 -0400457 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400458 result.Items = append(result.Items, device)
khenaidoob9203542018-09-17 22:56:37 -0400459 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000460 logger.Debugw(ctx, "ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400461 return result, nil
462}
463
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530464//isParentDeviceExist checks whether device is already preprovisioned.
Kent Hagerman2b216042020-04-03 18:28:56 -0400465func (dMgr *Manager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530466 hostPort := newDevice.GetHostAndPort()
Kent Hagerman4f355f52020-03-30 16:01:33 -0400467 var devices []*voltha.Device
Kent Hagermanf5a67352020-04-30 15:15:26 -0400468 if err := dMgr.dProxy.List(ctx, &devices); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000469 logger.Errorw(ctx, "Failed to list devices from cluster data proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530470 return false, err
471 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400472 for _, device := range devices {
473 if !device.Root {
474 continue
475 }
476 if hostPort != "" && hostPort == device.GetHostAndPort() && device.AdminState != voltha.AdminState_DELETED {
477 return true, nil
478 }
479 if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress && device.AdminState != voltha.AdminState_DELETED {
480 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530481 }
482 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530483 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530484}
485
khenaidoo6d62c002019-05-15 21:57:03 -0400486//getDeviceFromModelretrieves the device data from the model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400487func (dMgr *Manager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400488 device := &voltha.Device{}
Kent Hagermanf5a67352020-04-30 15:15:26 -0400489 if have, err := dMgr.dProxy.Get(ctx, deviceID, device); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000490 logger.Errorw(ctx, "failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530491 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400492 } else if !have {
493 return nil, status.Error(codes.NotFound, deviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530494 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400495
496 return device, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400497}
498
npujar1d86a522019-11-14 17:11:16 +0530499// loadDevice loads the deviceID in memory, if not present
Kent Hagerman2b216042020-04-03 18:28:56 -0400500func (dMgr *Manager) loadDevice(ctx context.Context, deviceID string) (*Agent, error) {
npujar1d86a522019-11-14 17:11:16 +0530501 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500502 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
503 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400504 var err error
505 var device *voltha.Device
506 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530507 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
508 if !dMgr.IsDeviceInCache(deviceID) {
509 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400510 dMgr.devicesLoadingLock.Unlock()
511 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530512 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000513 logger.Debugw(ctx, "loading-device", log.Fields{"device-id": deviceID})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700514 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530515 if _, err = agent.start(ctx, nil); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000516 logger.Warnw(ctx, "Failure loading device", log.Fields{"device-id": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400517 } else {
518 dMgr.addDeviceAgentToMap(agent)
519 }
520 } else {
divyadesaicb8b59d2020-08-18 09:55:47 +0000521 logger.Debugw(ctx, "Device not in model", log.Fields{"device-id": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400522 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400523 // announce completion of task to any number of waiting channels
524 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530525 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400526 for _, ch := range v {
527 close(ch)
528 }
npujar1d86a522019-11-14 17:11:16 +0530529 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400530 }
531 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400532 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400533 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500534 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400535 } else {
536 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530537 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400538 dMgr.devicesLoadingLock.Unlock()
539 // Wait for the channel to be closed, implying the process loading this device is done.
540 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500541 }
npujar1d86a522019-11-14 17:11:16 +0530542 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400543 return agent.(*Agent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500544 }
npujar1d86a522019-11-14 17:11:16 +0530545 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500546}
547
548// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
Kent Hagerman2a07b862020-06-19 15:23:07 -0400549func (dMgr *Manager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device, devicePorts map[uint32]*voltha.Port) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000550 logger.Debugw(ctx, "loading-parent-and-children", log.Fields{"device-id": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500551 if device.Root {
552 // Scenario A
553 if device.ParentId != "" {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400554 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530555 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000556 logger.Warnw(ctx, "failure-loading-logical-device", log.Fields{"logical-device-id": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500557 }
558 } else {
divyadesaicb8b59d2020-08-18 09:55:47 +0000559 logger.Debugw(ctx, "no-parent-to-load", log.Fields{"device-id": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500560 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400561 // Load all child devices, if needed
562 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, devicePorts)
563 for childDeviceID := range childDeviceIds {
564 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000565 logger.Warnw(ctx, "failure-loading-device", log.Fields{"device-id": childDeviceID, "error": err})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400566 return err
khenaidoo297cd252019-02-07 22:10:23 -0500567 }
khenaidoo297cd252019-02-07 22:10:23 -0500568 }
divyadesaicb8b59d2020-08-18 09:55:47 +0000569 logger.Debugw(ctx, "loaded-children", log.Fields{"device-id": device.Id, "numChildren": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500570 }
571 return nil
572}
573
574// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
575// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
576// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
577// and the proceed with the request.
Kent Hagerman2b216042020-04-03 18:28:56 -0400578func (dMgr *Manager) load(ctx context.Context, deviceID string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000579 logger.Debug(ctx, "load...")
khenaidoo297cd252019-02-07 22:10:23 -0500580 // 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 -0400581 var dAgent *Agent
khenaidoo297cd252019-02-07 22:10:23 -0500582 var err error
npujar467fe752020-01-16 20:17:45 +0530583 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500584 return err
585 }
586 // Get the loaded device details
Kent Hagermancba2f302020-07-28 13:37:36 -0400587 device, err := dAgent.getDeviceReadOnly(ctx)
khenaidoo442e7c72020-03-10 16:13:48 -0400588 if err != nil {
589 return err
590 }
khenaidoo297cd252019-02-07 22:10:23 -0500591
592 // If the device is in Pre-provisioning or deleted state stop here
593 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
594 return nil
595 }
596
597 // Now we face two scenarios
598 if device.Root {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400599 devicePorts := dAgent.listDevicePorts()
600
khenaidoo297cd252019-02-07 22:10:23 -0500601 // Load all children as well as the parent of this device (logical_device)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400602 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device, devicePorts); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000603 logger.Warnw(ctx, "failure-loading-device-parent-and-children", log.Fields{"device-id": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500604 return err
605 }
divyadesaicb8b59d2020-08-18 09:55:47 +0000606 logger.Debugw(ctx, "successfully-loaded-parent-and-children", log.Fields{"device-id": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500607 } else {
608 // Scenario B - use the parentId of that device (root device) to trigger the loading
609 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530610 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500611 }
612 }
613 return nil
614}
615
khenaidoo7ccedd52018-12-14 16:48:54 -0500616// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000617func (dMgr *Manager) ListDeviceIds(ctx context.Context, _ *empty.Empty) (*voltha.IDs, error) {
618 logger.Debug(ctx, "ListDeviceIDs")
khenaidoo7ccedd52018-12-14 16:48:54 -0500619 // Report only device IDs that are in the device agent map
620 return dMgr.listDeviceIdsFromMap(), nil
621}
622
Kent Hagerman45a13e42020-04-13 12:23:50 -0400623// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
624// trigger loading the devices along with their children and parent in memory
625func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000626 logger.Debugw(ctx, "ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo4c9e5592019-09-09 16:20:41 -0400627 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500628 toReconcile := len(ids.Items)
629 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400630 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500631 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530632 if err = dMgr.load(ctx, id.Id); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000633 logger.Warnw(ctx, "failure-reconciling-device", log.Fields{"device-id": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400634 } else {
npujar1d86a522019-11-14 17:11:16 +0530635 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500636 }
637 }
638 if toReconcile != reconciled {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400639 return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500640 }
641 } else {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400642 return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
khenaidoo7ccedd52018-12-14 16:48:54 -0500643 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400644 return &empty.Empty{}, nil
khenaidoo7ccedd52018-12-14 16:48:54 -0500645}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500646
khenaidooba6b6c42019-08-02 09:11:56 -0400647// isOkToReconcile validates whether a device is in the correct status to be reconciled
648func isOkToReconcile(device *voltha.Device) bool {
649 if device == nil {
650 return false
651 }
652 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
653}
654
655// adapterRestarted is invoked whenever an adapter is restarted
Kent Hagerman2b216042020-04-03 18:28:56 -0400656func (dMgr *Manager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000657 logger.Debugw(ctx, "adapter-restarted", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
Matteo Scandolod525ae32020-04-02 17:27:29 -0700658 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidooba6b6c42019-08-02 09:11:56 -0400659
660 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700661 if len(dMgr.rootDevices) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000662 logger.Debugw(ctx, "nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400663 return nil
664 }
665
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500666 responses := make([]utils.Response, 0)
David Bainbridged1afd662020-03-26 18:27:41 -0700667 for rootDeviceID := range dMgr.rootDevices {
npujar467fe752020-01-16 20:17:45 +0530668 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000669 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(ctx, rootDeviceID, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700670 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000671 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 -0700672 continue
673 }
674 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400675 if isOkToReconcile(rootDevice) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000676 logger.Debugw(ctx, "reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530677 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400678 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000679 logger.Debugw(ctx, "not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400680 }
681 } else { // Should we be reconciling the root's children instead?
Kent Hagerman2a07b862020-06-19 15:23:07 -0400682 rootDevicePorts, _ := dMgr.listDevicePorts(ctx, rootDeviceID)
khenaidooba6b6c42019-08-02 09:11:56 -0400683 childManagedByAdapter:
Kent Hagerman2a07b862020-06-19 15:23:07 -0400684 for _, port := range rootDevicePorts {
khenaidooba6b6c42019-08-02 09:11:56 -0400685 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530686 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000687 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(ctx, childDevice.Id, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700688 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000689 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 -0700690 }
691 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400692 if isOkToReconcile(childDevice) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000693 logger.Debugw(ctx, "reconciling-child-device", log.Fields{"child-device-id": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530694 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400695 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000696 logger.Debugw(ctx, "not-reconciling-child-device", log.Fields{"child-device-id": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400697 }
698 } else {
699 // All child devices under a parent device are typically managed by the same adapter type.
700 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
701 break childManagedByAdapter
702 }
703 }
704 }
705 }
706 }
707 }
708 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500709 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400710 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500711 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400712 return status.Errorf(codes.Aborted, "errors-%s", res)
713 }
714 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000715 logger.Debugw(ctx, "no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400716 }
717 return nil
718}
719
Kent Hagerman2b216042020-04-03 18:28:56 -0400720func (dMgr *Manager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400721 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
722 // 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 +0530723 // 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 -0400724 // the adapter proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500725 response := utils.NewResponse()
Kent Hagerman2b216042020-04-03 18:28:56 -0400726 ch, err := dMgr.adapterProxy.ReconcileDevice(ctx, device)
khenaidoo442e7c72020-03-10 16:13:48 -0400727 if err != nil {
728 response.Error(err)
729 }
730 // Wait for adapter response in its own routine
731 go func() {
732 resp, ok := <-ch
733 if !ok {
734 response.Error(status.Errorf(codes.Aborted, "channel-closed-device: %s", device.Id))
735 } else if resp.Err != nil {
736 response.Error(resp.Err)
khenaidooba6b6c42019-08-02 09:11:56 -0400737 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500738 response.Done()
khenaidoo442e7c72020-03-10 16:13:48 -0400739 }()
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500740 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400741}
742
Kent Hagerman2b216042020-04-03 18:28:56 -0400743func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID string) error {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400744 if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500745 responses := make([]utils.Response, 0)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400746 for _, port := range parentDevicePorts {
khenaidooba6b6c42019-08-02 09:11:56 -0400747 for _, peer := range port.Peers {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400748 if childDevice, err := dMgr.getDeviceFromModel(ctx, peer.DeviceId); err == nil {
npujar467fe752020-01-16 20:17:45 +0530749 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400750 }
751 }
752 }
753 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500754 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400755 return status.Errorf(codes.Aborted, "errors-%s", res)
756 }
757 }
758 return nil
759}
760
Kent Hagerman2b216042020-04-03 18:28:56 -0400761func (dMgr *Manager) UpdateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000762 logger.Debugw(ctx, "UpdateDeviceUsingAdapterData", log.Fields{"device-id": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530763 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
764 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400765 }
766 return status.Errorf(codes.NotFound, "%s", device.Id)
767}
768
khenaidoo0db4c812020-05-27 15:27:30 -0400769func (dMgr *Manager) addPeerPort(ctx context.Context, deviceID string, port *voltha.Port) error {
770 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
771 for _, peerPort := range port.Peers {
772 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
773 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
774 return err
775 }
776 }
777 }
778 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
779 // then a logical port will be added to the logical device and the device route generated. If the port is a
780 // PON port then only the device graph will be generated.
Kent Hagermancba2f302020-07-28 13:37:36 -0400781 device, err := dMgr.getDeviceReadOnly(ctx, deviceID)
khenaidoo0db4c812020-05-27 15:27:30 -0400782 if err != nil {
783 return err
784 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400785 ports, err := dMgr.listDevicePorts(ctx, deviceID)
786 if err != nil {
787 return err
788 }
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000789 if err = dMgr.logicalDeviceMgr.updateLogicalPort(log.WithSpanFromContext(context.Background(), ctx), device, ports, port); err != nil {
khenaidoo0db4c812020-05-27 15:27:30 -0400790 return err
791 }
792 return nil
793}
794
Kent Hagerman2b216042020-04-03 18:28:56 -0400795func (dMgr *Manager) AddPort(ctx context.Context, deviceID string, port *voltha.Port) error {
npujar467fe752020-01-16 20:17:45 +0530796 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530797 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530798 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400799 return err
800 }
khenaidoo0db4c812020-05-27 15:27:30 -0400801 // Setup peer ports in its own routine
802 go func() {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000803 if err := dMgr.addPeerPort(log.WithSpanFromContext(context.Background(), ctx), deviceID, port); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000804 logger.Errorw(ctx, "unable-to-add-peer-port", log.Fields{"error": err, "device-id": deviceID})
khenaidoo92e62c52018-10-03 14:02:54 -0400805 }
khenaidoo0db4c812020-05-27 15:27:30 -0400806 }()
khenaidoo92e62c52018-10-03 14:02:54 -0400807 return nil
khenaidoob9203542018-09-17 22:56:37 -0400808 }
npujar1d86a522019-11-14 17:11:16 +0530809 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400810}
811
Kent Hagerman2b216042020-04-03 18:28:56 -0400812func (dMgr *Manager) addFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000813 logger.Debugw(ctx, "addFlowsAndGroups", log.Fields{"device-id": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530814 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
815 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400816 }
npujar1d86a522019-11-14 17:11:16 +0530817 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400818}
819
khenaidoo787224a2020-04-16 18:08:47 -0400820// deleteParentFlows removes flows from the parent device based on specific attributes
821func (dMgr *Manager) deleteParentFlows(ctx context.Context, deviceID string, uniPort uint32, metadata *voltha.FlowMetadata) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000822 logger.Debugw(ctx, "deleteParentFlows", log.Fields{"device-id": deviceID, "uni-port": uniPort, "metadata": metadata})
khenaidoo787224a2020-04-16 18:08:47 -0400823 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400824 if !agent.isRootDevice {
khenaidoo787224a2020-04-16 18:08:47 -0400825 return status.Errorf(codes.FailedPrecondition, "not-a-parent-device-%s", deviceID)
826 }
827 return agent.filterOutFlows(ctx, uniPort, metadata)
828 }
829 return status.Errorf(codes.NotFound, "%s", deviceID)
830}
831
Kent Hagerman2b216042020-04-03 18:28:56 -0400832func (dMgr *Manager) deleteFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000833 logger.Debugw(ctx, "deleteFlowsAndGroups", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530834 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
835 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400836 }
npujar1d86a522019-11-14 17:11:16 +0530837 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400838}
839
Kent Hagerman2b216042020-04-03 18:28:56 -0400840func (dMgr *Manager) updateFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000841 logger.Debugw(ctx, "updateFlowsAndGroups", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530842 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
843 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400844 }
npujar1d86a522019-11-14 17:11:16 +0530845 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400846}
847
Kent Hagerman45a13e42020-04-13 12:23:50 -0400848// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
khenaidoob3127472019-07-24 21:04:55 -0400849// following a user action
Kent Hagerman45a13e42020-04-13 12:23:50 -0400850func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000851 log.EnrichSpan(ctx, log.Fields{"device-id": configs.Id})
852
Kent Hagerman45a13e42020-04-13 12:23:50 -0400853 if configs.Id == "" {
854 return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
khenaidoob3127472019-07-24 21:04:55 -0400855 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400856 agent := dMgr.getDeviceAgent(ctx, configs.Id)
857 if agent == nil {
858 return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
859 }
860 return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
khenaidoob3127472019-07-24 21:04:55 -0400861}
862
Kent Hagerman2b216042020-04-03 18:28:56 -0400863// InitPmConfigs initialize the pm configs as defined by the adapter.
864func (dMgr *Manager) InitPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400865 if pmConfigs.Id == "" {
866 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
867 }
npujar467fe752020-01-16 20:17:45 +0530868 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
869 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400870 }
npujar1d86a522019-11-14 17:11:16 +0530871 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400872}
873
Kent Hagerman45a13e42020-04-13 12:23:50 -0400874// ListDevicePmConfigs returns pm configs of device
875func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000876 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
877
Kent Hagerman45a13e42020-04-13 12:23:50 -0400878 agent := dMgr.getDeviceAgent(ctx, id.Id)
879 if agent == nil {
880 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob3127472019-07-24 21:04:55 -0400881 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400882 return agent.listPmConfigs(ctx)
khenaidoob3127472019-07-24 21:04:55 -0400883}
884
Kent Hagerman2b216042020-04-03 18:28:56 -0400885func (dMgr *Manager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000886 logger.Debugw(ctx, "getSwitchCapability", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530887 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400888 return agent.getSwitchCapability(ctx)
889 }
npujar1d86a522019-11-14 17:11:16 +0530890 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400891}
892
Kent Hagerman2b216042020-04-03 18:28:56 -0400893func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000894 logger.Debugw(ctx, "GetPorts", log.Fields{"device-id": deviceID, "portType": portType})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400895 agent := dMgr.getDeviceAgent(ctx, deviceID)
896 if agent == nil {
897 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400898 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400899 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400900}
901
Kent Hagerman2b216042020-04-03 18:28:56 -0400902func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000903 logger.Debugw(ctx, "UpdateDeviceStatus", log.Fields{"device-id": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530904 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
905 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400906 }
npujar1d86a522019-11-14 17:11:16 +0530907 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400908}
909
Kent Hagerman2b216042020-04-03 18:28:56 -0400910func (dMgr *Manager) UpdateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000911 logger.Debugw(ctx, "UpdateChildrenStatus", log.Fields{"parent-device-id": deviceID, "operStatus": operStatus, "connStatus": connStatus})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400912 parentDevicePorts, err := dMgr.listDevicePorts(ctx, deviceID)
913 if err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400914 return status.Errorf(codes.Aborted, "%s", err.Error())
915 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400916 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
npujar467fe752020-01-16 20:17:45 +0530917 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
918 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530919 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400920 }
921 }
922 }
923 return nil
924}
925
Kent Hagerman2b216042020-04-03 18:28:56 -0400926func (dMgr *Manager) UpdatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000927 logger.Debugw(ctx, "UpdatePortState", log.Fields{"device-id": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530928 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
929 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000930 logger.Errorw(ctx, "updating-port-state-failed", log.Fields{"device-id": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400931 return err
932 }
933 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800934 // Do this for NNI and UNIs only. PON ports are not known by logical device
935 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
936 go func() {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000937 err := dMgr.logicalDeviceMgr.updatePortState(log.WithSpanFromContext(context.Background(), ctx), deviceID, portNo, operStatus)
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800938 if err != nil {
939 // While we want to handle (catch) and log when
940 // an update to a port was not able to be
941 // propagated to the logical port, we can report
942 // it as a warning and not an error because it
943 // doesn't stop or modify processing.
944 // TODO: VOL-2707
Rohan Agrawal31f21802020-06-12 05:38:46 +0000945 logger.Warnw(ctx, "unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800946 }
947 }()
948 }
khenaidoo442e7c72020-03-10 16:13:48 -0400949 return nil
khenaidoob9203542018-09-17 22:56:37 -0400950 }
npujar1d86a522019-11-14 17:11:16 +0530951 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400952}
953
Kent Hagerman2b216042020-04-03 18:28:56 -0400954func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID string) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000955 logger.Debugw(ctx, "DeleteAllPorts", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530956 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
957 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400958 return err
959 }
960 // Notify the logical device manager to remove all logical ports, if needed.
Kent Hagerman2b216042020-04-03 18:28:56 -0400961 // At this stage the device itself may gave been deleted already at a DeleteAllPorts
khenaidoo0a822f92019-05-08 15:15:57 -0400962 // typically is part of a device deletion phase.
Kent Hagermancba2f302020-07-28 13:37:36 -0400963 if device, err := dMgr.getDeviceReadOnly(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530964 go func() {
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000965 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(log.WithSpanFromContext(context.Background(), ctx), device); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000966 logger.Errorw(ctx, "unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530967 }
968 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400969 } else {
divyadesaicb8b59d2020-08-18 09:55:47 +0000970 logger.Warnw(ctx, "failed-to-retrieve-device", log.Fields{"device-id": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400971 return err
972 }
973 return nil
974 }
npujar1d86a522019-11-14 17:11:16 +0530975 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400976}
977
Kent Hagerman2b216042020-04-03 18:28:56 -0400978//UpdatePortsState updates all ports on the device
Kent Hagerman2a07b862020-06-19 15:23:07 -0400979func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, portTypeFilter uint32, state voltha.OperStatus_Types) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000980 logger.Debugw(ctx, "UpdatePortsState", log.Fields{"device-id": deviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400981 agent := dMgr.getDeviceAgent(ctx, deviceID)
982 if agent == nil {
983 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400984 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400985 if state != voltha.OperStatus_ACTIVE && state != voltha.OperStatus_UNKNOWN {
986 return status.Error(codes.Unimplemented, "state-change-not-implemented")
987 }
988 if err := agent.updatePortsOperState(ctx, portTypeFilter, state); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000989 logger.Warnw(ctx, "updatePortsOperState-failed", log.Fields{"device-id": deviceID, "error": err})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400990 return err
991 }
992 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400993}
994
Kent Hagerman2b216042020-04-03 18:28:56 -0400995func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530996 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000997 logger.Debugw(ctx, "ChildDeviceDetected", log.Fields{"parent-device-id": parentDeviceID, "parentPortNo": parentPortNo, "deviceType": deviceType, "channelId": channelID, "vendorId": vendorID, "serialNumber": serialNumber, "onuId": onuID})
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700998
npujar1d86a522019-11-14 17:11:16 +0530999 if deviceType == "" && vendorID != "" {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001000 logger.Debug(ctx, "device-type-is-nil-fetching-device-type")
Kent Hagerman45a13e42020-04-13 12:23:50 -04001001 deviceTypes, err := dMgr.adapterMgr.ListDeviceTypes(ctx, nil)
1002 if err != nil {
1003 return nil, err
1004 }
Kent Hagerman4f355f52020-03-30 16:01:33 -04001005 OLoop:
Kent Hagerman45a13e42020-04-13 12:23:50 -04001006 for _, dType := range deviceTypes.Items {
Kent Hagerman4f355f52020-03-30 16:01:33 -04001007 for _, v := range dType.VendorIds {
1008 if v == vendorID {
1009 deviceType = dType.Adapter
1010 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001011 }
1012 }
1013 }
1014 }
1015 //if no match found for the vendorid,report adapter with the custom error message
1016 if deviceType == "" {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001017 logger.Errorw(ctx, "failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +05301018 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001019 }
khenaidoob9203542018-09-17 22:56:37 -04001020
1021 // Create the ONU device
1022 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -04001023 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +05301024 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -04001025 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +05301026 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -05001027 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -04001028 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001029
khenaidoo442e7c72020-03-10 16:13:48 -04001030 // Get parent device type
1031 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
1032 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +05301033 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001034 }
khenaidoo442e7c72020-03-10 16:13:48 -04001035 if pAgent.deviceType == "" {
1036 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
1037 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001038
npujar467fe752020-01-16 20:17:45 +05301039 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001040 logger.Warnw(ctx, "child-device-exists", log.Fields{"parent-device-id": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001041 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001042 }
1043
khenaidoo442e7c72020-03-10 16:13:48 -04001044 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001045
1046 // Create and start a device agent for that device
Mahir Gunyel03de0d32020-06-03 01:36:59 -07001047 agent := newAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
Mahir Gunyel23bd8c72020-09-21 23:20:43 -07001048 insertedChildDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001049 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001050 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 -08001051 return nil, err
1052 }
khenaidoo442e7c72020-03-10 16:13:48 -04001053 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001054
1055 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301056 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301057 go func() {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001058 err := agent.enableDevice(log.WithSpanFromContext(context.Background(), ctx))
npujar1d86a522019-11-14 17:11:16 +05301059 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001060 logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301061 }
1062 }()
khenaidoob9203542018-09-17 22:56:37 -04001063 }
1064
Mahir Gunyel23bd8c72020-09-21 23:20:43 -07001065 return insertedChildDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001066}
1067
Kent Hagerman2b216042020-04-03 18:28:56 -04001068func (dMgr *Manager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
divyadesaicb8b59d2020-08-18 09:55:47 +00001069 logger.Debugw(ctx, "packetOut", log.Fields{"device-id": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301070 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1071 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001072 }
npujar1d86a522019-11-14 17:11:16 +05301073 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001074}
1075
npujar1d86a522019-11-14 17:11:16 +05301076// PacketIn receives packet from adapter
Kent Hagerman2b216042020-04-03 18:28:56 -04001077func (dMgr *Manager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
divyadesaicb8b59d2020-08-18 09:55:47 +00001078 logger.Debugw(ctx, "PacketIn", log.Fields{"device-id": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001079 // Get the logical device Id based on the deviceId
1080 var device *voltha.Device
1081 var err error
Kent Hagermancba2f302020-07-28 13:37:36 -04001082 if device, err = dMgr.getDeviceReadOnly(ctx, deviceID); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001083 logger.Errorw(ctx, "device-not-found", log.Fields{"device-id": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001084 return err
1085 }
khenaidoo43c82122018-11-22 18:38:28 -05001086 if !device.Root {
divyadesaicb8b59d2020-08-18 09:55:47 +00001087 logger.Errorw(ctx, "device-not-root", log.Fields{"device-id": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301088 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001089 }
1090
npujar467fe752020-01-16 20:17:45 +05301091 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001092 return err
1093 }
1094 return nil
1095}
1096
Kent Hagerman2b216042020-04-03 18:28:56 -04001097func (dMgr *Manager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
divyadesaicb8b59d2020-08-18 09:55:47 +00001098 logger.Debugw(ctx, "setParentId", log.Fields{"device-id": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301099 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1100 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001101 }
1102 return status.Errorf(codes.NotFound, "%s", device.Id)
1103}
1104
npujar1d86a522019-11-14 17:11:16 +05301105// CreateLogicalDevice creates logical device in core
Kent Hagerman2b216042020-04-03 18:28:56 -04001106func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001107 logger.Info(ctx, "CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001108 // Verify whether the logical device has already been created
1109 if cDevice.ParentId != "" {
divyadesaicb8b59d2020-08-18 09:55:47 +00001110 logger.Debugw(ctx, "Parent device already exist.", log.Fields{"device-id": cDevice.Id, "logical-device-id": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001111 return nil
1112 }
khenaidoob9203542018-09-17 22:56:37 -04001113 var err error
npujar467fe752020-01-16 20:17:45 +05301114 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001115 logger.Warnw(ctx, "createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001116 return err
1117 }
khenaidoob9203542018-09-17 22:56:37 -04001118 return nil
1119}
1120
npujar1d86a522019-11-14 17:11:16 +05301121// DeleteLogicalDevice deletes logical device from core
Kent Hagerman2b216042020-04-03 18:28:56 -04001122func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001123 logger.Info(ctx, "DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001124 var err error
npujar467fe752020-01-16 20:17:45 +05301125 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001126 logger.Warnw(ctx, "deleteLogical-device-error", log.Fields{"device-id": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001127 return err
1128 }
1129 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301130 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301131 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001132 return nil
1133}
1134
npujar1d86a522019-11-14 17:11:16 +05301135// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagerman2b216042020-04-03 18:28:56 -04001136func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001137 logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001138 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001139 // 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 +00001140 logger.Warnw(ctx, "deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001141 }
1142 return nil
1143}
1144
Kent Hagerman2b216042020-04-03 18:28:56 -04001145func (dMgr *Manager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001146 // Sanity check
1147 if childDevice.Root {
1148 // childDevice is the parent device
1149 return childDevice
1150 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001151 parentDevice, _ := dMgr.getDeviceReadOnly(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001152 return parentDevice
1153}
1154
Kent Hagerman2b216042020-04-03 18:28:56 -04001155//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 -04001156//cannot manage the child devices. This will trigger the Core to disable all the child devices.
Kent Hagerman2b216042020-04-03 18:28:56 -04001157func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001158 logger.Debug(ctx, "ChildDevicesLost")
Kent Hagermancba2f302020-07-28 13:37:36 -04001159 parentDevice, err := dMgr.getDeviceReadOnly(ctx, parentDeviceID)
Kent Hagerman2a07b862020-06-19 15:23:07 -04001160 if err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001161 logger.Warnw(ctx, "failed-getting-device", log.Fields{"parent-device-id": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001162 return err
1163 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001164 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001165}
1166
Kent Hagerman2b216042020-04-03 18:28:56 -04001167//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
khenaidoo0a822f92019-05-08 15:15:57 -04001168// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
Kent Hagerman2b216042020-04-03 18:28:56 -04001169func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001170 logger.Debug(ctx, "ChildDevicesDetected")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001171 parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
1172 if err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001173 logger.Warnw(ctx, "failed-getting-device", log.Fields{"device-id": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001174 return err
1175 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001176 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
khenaidoo0a822f92019-05-08 15:15:57 -04001177 if len(childDeviceIds) == 0 {
divyadesaicb8b59d2020-08-18 09:55:47 +00001178 logger.Debugw(ctx, "no-child-device", log.Fields{"parent-device-id": parentDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001179 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001180 allChildEnableRequestSent := true
Kent Hagerman2a07b862020-06-19 15:23:07 -04001181 for childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301182 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001183 // Run the children re-registration in its own routine
Kent Hagerman2a07b862020-06-19 15:23:07 -04001184 go func(ctx context.Context) {
1185 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301186 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001187 logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301188 }
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001189 }(log.WithSpanFromContext(context.Background(), ctx))
khenaidoo59ef7be2019-06-21 12:40:28 -04001190 } else {
npujar1d86a522019-11-14 17:11:16 +05301191 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
divyadesaicb8b59d2020-08-18 09:55:47 +00001192 logger.Errorw(ctx, "no-child-device-agent", log.Fields{"parent-device-id": parentDeviceID, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001193 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001194 }
1195 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001196 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001197 return err
1198 }
1199 return nil
1200}
1201
khenaidoo4d4802d2018-10-04 21:59:49 -04001202/*
1203All the functions below are callback functions where they are invoked with the latest and previous data. We can
1204therefore use the data as is without trying to get the latest from the model.
1205*/
1206
khenaidoo0a822f92019-05-08 15:15:57 -04001207//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagerman2b216042020-04-03 18:28:56 -04001208func (dMgr *Manager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001209 logger.Debug(ctx, "DisableAllChildDevices")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001210 ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
1211 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
npujar467fe752020-01-16 20:17:45 +05301212 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -04001213 if err := agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001214 // Just log the error - this error happens only if the child device was already in deleted state.
divyadesaicb8b59d2020-08-18 09:55:47 +00001215 logger.Errorw(ctx, "failure-disable-device", log.Fields{"device-id": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001216 }
1217 }
1218 }
1219 return nil
1220}
1221
khenaidoo0a822f92019-05-08 15:15:57 -04001222//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001223func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001224 logger.Debug(ctx, "DeleteAllChildDevices")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001225 ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
1226 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
npujar467fe752020-01-16 20:17:45 +05301227 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -04001228 if err := agent.deleteDevice(ctx); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001229 logger.Warnw(ctx, "failure-delete-device", log.Fields{"device-id": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001230 }
khenaidoo49085352020-01-13 19:15:43 -05001231 // No further action is required here. The deleteDevice will change the device state where the resulting
1232 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001233 }
1234 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001235 return nil
1236}
1237
Girish Gowdra408cd962020-03-11 14:31:31 -07001238//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001239func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001240 logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001241 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001242 // Just log error as logical device may already have been deleted
Rohan Agrawal31f21802020-06-12 05:38:46 +00001243 logger.Warnw(ctx, "delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001244 }
1245 return nil
1246}
1247
1248//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001249func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001250 logger.Debugw(ctx, "delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001251 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1252 if err := agent.deleteAllFlows(ctx); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001253 logger.Errorw(ctx, "error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001254 return err
1255 }
1256 return nil
1257 }
1258 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1259}
1260
khenaidoo4d4802d2018-10-04 21:59:49 -04001261//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 -04001262func (dMgr *Manager) getAllChildDeviceIds(ctx context.Context, parentDevicePorts map[uint32]*voltha.Port) map[string]struct{} {
1263 logger.Debug(ctx, "getAllChildDeviceIds")
1264 childDeviceIds := make(map[string]struct{}, len(parentDevicePorts))
1265 for _, port := range parentDevicePorts {
1266 for _, peer := range port.Peers {
1267 childDeviceIds[peer.DeviceId] = struct{}{}
khenaidoo92e62c52018-10-03 14:02:54 -04001268 }
1269 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001270 logger.Debugw(ctx, "returning-getAllChildDeviceIds", log.Fields{"childDeviceIds": childDeviceIds})
1271 return childDeviceIds
khenaidoo92e62c52018-10-03 14:02:54 -04001272}
1273
Kent Hagerman2b216042020-04-03 18:28:56 -04001274//GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1275func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +00001276 logger.Debugw(ctx, "GetAllChildDevices", log.Fields{"parent-device-id": parentDeviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -04001277 if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001278 childDevices := make([]*voltha.Device, 0)
Kent Hagerman2a07b862020-06-19 15:23:07 -04001279 for deviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
Kent Hagermancba2f302020-07-28 13:37:36 -04001280 if d, e := dMgr.getDeviceReadOnly(ctx, deviceID); e == nil && d != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -04001281 childDevices = append(childDevices, d)
khenaidoo297cd252019-02-07 22:10:23 -05001282 }
1283 }
1284 return &voltha.Devices{Items: childDevices}, nil
1285 }
npujar1d86a522019-11-14 17:11:16 +05301286 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001287}
1288
npujar1d86a522019-11-14 17:11:16 +05301289// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagerman2b216042020-04-03 18:28:56 -04001290func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Kent Hagermanf6db9f12020-07-22 17:16:19 -04001291 logger.Info(ctx, "SetupUNILogicalPorts")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001292 cDevicePorts, err := dMgr.listDevicePorts(ctx, cDevice.Id)
1293 if err != nil {
1294 return err
1295 }
1296 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice, cDevicePorts); err != nil {
Kent Hagermanf6db9f12020-07-22 17:16:19 -04001297 logger.Warnw(ctx, "setupUNILogicalPorts-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001298 return err
1299 }
1300 return nil
1301}
1302
Kent Hagerman45a13e42020-04-13 12:23:50 -04001303// convenience to avoid redefining
1304var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
1305
1306// DownloadImage execute an image download request
1307func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001308 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
1309
Rohan Agrawal31f21802020-06-12 05:38:46 +00001310 logger.Debugw(ctx, "DownloadImage", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001311 agent := dMgr.getDeviceAgent(ctx, img.Id)
1312 if agent == nil {
1313 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001314 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001315 resp, err := agent.downloadImage(ctx, img)
1316 if err != nil {
1317 return operationFailureResp, err
1318 }
1319 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001320}
1321
Kent Hagerman45a13e42020-04-13 12:23:50 -04001322// CancelImageDownload cancels image download request
1323func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001324 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
1325
Rohan Agrawal31f21802020-06-12 05:38:46 +00001326 logger.Debugw(ctx, "CancelImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001327 agent := dMgr.getDeviceAgent(ctx, img.Id)
1328 if agent == nil {
1329 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001330 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001331 resp, err := agent.cancelImageDownload(ctx, img)
1332 if err != nil {
1333 return operationFailureResp, err
1334 }
1335 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001336}
1337
Kent Hagerman45a13e42020-04-13 12:23:50 -04001338// ActivateImageUpdate activates image update request
1339func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001340 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
1341
Rohan Agrawal31f21802020-06-12 05:38:46 +00001342 logger.Debugw(ctx, "ActivateImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001343 agent := dMgr.getDeviceAgent(ctx, img.Id)
1344 if agent == nil {
1345 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001346 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001347 resp, err := agent.activateImage(ctx, img)
1348 if err != nil {
1349 return operationFailureResp, err
1350 }
1351 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001352}
1353
Kent Hagerman45a13e42020-04-13 12:23:50 -04001354// RevertImageUpdate reverts image update
1355func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001356 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
1357
Rohan Agrawal31f21802020-06-12 05:38:46 +00001358 logger.Debugw(ctx, "RevertImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001359 agent := dMgr.getDeviceAgent(ctx, img.Id)
1360 if agent == nil {
1361 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001362 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001363 resp, err := agent.revertImage(ctx, img)
1364 if err != nil {
1365 return operationFailureResp, err
1366 }
1367 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001368}
1369
Kent Hagerman45a13e42020-04-13 12:23:50 -04001370// convenience to avoid redefining
1371var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
1372
1373// GetImageDownloadStatus returns status of image download
1374func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001375 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
1376
Rohan Agrawal31f21802020-06-12 05:38:46 +00001377 logger.Debugw(ctx, "GetImageDownloadStatus", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001378 agent := dMgr.getDeviceAgent(ctx, img.Id)
1379 if agent == nil {
1380 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001381 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001382 resp, err := agent.getImageDownloadStatus(ctx, img)
1383 if err != nil {
1384 return imageDownloadFailureResp, err
1385 }
1386 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001387}
1388
Kent Hagerman2b216042020-04-03 18:28:56 -04001389func (dMgr *Manager) UpdateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001390 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
1391
Rohan Agrawal31f21802020-06-12 05:38:46 +00001392 logger.Debugw(ctx, "UpdateImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301393 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1394 if err := agent.updateImageDownload(ctx, img); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001395 logger.Debugw(ctx, "UpdateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001396 return err
1397 }
1398 } else {
1399 return status.Errorf(codes.NotFound, "%s", img.Id)
1400 }
1401 return nil
1402}
1403
Kent Hagerman45a13e42020-04-13 12:23:50 -04001404// GetImageDownload returns image download
Kent Hagerman2b216042020-04-03 18:28:56 -04001405func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001406 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
1407
Rohan Agrawal31f21802020-06-12 05:38:46 +00001408 logger.Debugw(ctx, "GetImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001409 agent := dMgr.getDeviceAgent(ctx, img.Id)
1410 if agent == nil {
1411 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001412 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001413 resp, err := agent.getImageDownload(ctx, img)
1414 if err != nil {
1415 return imageDownloadFailureResp, err
1416 }
1417 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001418}
1419
Kent Hagerman45a13e42020-04-13 12:23:50 -04001420// ListImageDownloads returns image downloads
1421func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001422 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
1423
Rohan Agrawal31f21802020-06-12 05:38:46 +00001424 logger.Debugw(ctx, "ListImageDownloads", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001425 agent := dMgr.getDeviceAgent(ctx, id.Id)
1426 if agent == nil {
1427 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001428 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001429 resp, err := agent.listImageDownloads(ctx, id.Id)
1430 if err != nil {
1431 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
1432 }
1433 return resp, nil
1434}
1435
1436// GetImages returns all images for a specific device entry
1437func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001438 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
1439
Rohan Agrawal31f21802020-06-12 05:38:46 +00001440 logger.Debugw(ctx, "GetImages", log.Fields{"device-id": id.Id})
Kent Hagermancba2f302020-07-28 13:37:36 -04001441 device, err := dMgr.getDeviceReadOnly(ctx, id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -04001442 if err != nil {
1443 return nil, err
1444 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001445 return device.Images, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001446}
1447
Rohan Agrawal31f21802020-06-12 05:38:46 +00001448func (dMgr *Manager) NotifyInvalidTransition(ctx context.Context, device *voltha.Device) error {
1449 logger.Errorw(ctx, "NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001450 "device": device.Id,
1451 "curr-admin-state": device.AdminState,
1452 "curr-oper-state": device.OperStatus,
1453 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001454 })
khenaidoo0a822f92019-05-08 15:15:57 -04001455 //TODO: notify over kafka?
1456 return nil
1457}
1458
npujar1d86a522019-11-14 17:11:16 +05301459// UpdateDeviceAttribute updates value of particular device attribute
Kent Hagerman2b216042020-04-03 18:28:56 -04001460func (dMgr *Manager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301461 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -04001462 agent.(*Agent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001463 }
1464}
1465
npujar1d86a522019-11-14 17:11:16 +05301466// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -04001467func (dMgr *Manager) GetParentDeviceID(ctx context.Context, deviceID string) string {
Kent Hagermancba2f302020-07-28 13:37:36 -04001468 if device, _ := dMgr.getDeviceReadOnly(ctx, deviceID); device != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001469 logger.Infow(ctx, "GetParentDeviceId", log.Fields{"device-id": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001470 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001471 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001472 return ""
khenaidoob9203542018-09-17 22:56:37 -04001473}
serkant.uluderya334479d2019-04-10 08:26:15 -07001474
Kent Hagerman45a13e42020-04-13 12:23:50 -04001475func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001476 logger.Debugw(ctx, "SimulateAlarm", log.Fields{"id": simulateReq.Id, "Indicator": simulateReq.Indicator, "IntfId": simulateReq.IntfId,
Kent Hagerman45a13e42020-04-13 12:23:50 -04001477 "PortTypeName": simulateReq.PortTypeName, "OnuDeviceId": simulateReq.OnuDeviceId, "InverseBitErrorRate": simulateReq.InverseBitErrorRate,
1478 "Drift": simulateReq.Drift, "NewEqd": simulateReq.NewEqd, "OnuSerialNumber": simulateReq.OnuSerialNumber, "Operation": simulateReq.Operation})
1479 agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
1480 if agent == nil {
1481 return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
serkant.uluderya334479d2019-04-10 08:26:15 -07001482 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001483 if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
1484 return nil, err
1485 }
1486 return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
serkant.uluderya334479d2019-04-10 08:26:15 -07001487}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001488
Kent Hagerman2b216042020-04-03 18:28:56 -04001489func (dMgr *Manager) UpdateDeviceReason(ctx context.Context, deviceID string, reason string) error {
divyadesaicb8b59d2020-08-18 09:55:47 +00001490 logger.Debugw(ctx, "UpdateDeviceReason", log.Fields{"device-id": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301491 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1492 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001493 }
npujar1d86a522019-11-14 17:11:16 +05301494 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001495}
kesavandbc2d1622020-01-21 00:42:01 -05001496
Kent Hagerman45a13e42020-04-13 12:23:50 -04001497func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001498 log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
1499
Rohan Agrawal31f21802020-06-12 05:38:46 +00001500 logger.Debugw(ctx, "EnablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001501 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1502 if agent == nil {
1503 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001504 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001505 return &empty.Empty{}, agent.enablePort(ctx, port.PortNo)
kesavandbc2d1622020-01-21 00:42:01 -05001506}
1507
Kent Hagerman45a13e42020-04-13 12:23:50 -04001508func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001509 log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
1510
Rohan Agrawal31f21802020-06-12 05:38:46 +00001511 logger.Debugw(ctx, "DisablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001512 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1513 if agent == nil {
1514 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001515 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001516 return &empty.Empty{}, agent.disablePort(ctx, port.PortNo)
kesavandbc2d1622020-01-21 00:42:01 -05001517}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001518
Kent Hagerman2b216042020-04-03 18:28:56 -04001519// ChildDeviceLost calls parent adapter to delete child device and all its references
1520func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001521 logger.Debugw(ctx, "childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001522 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001523 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1524 // Just log the message and let the remaining pipeline proceed.
Rohan Agrawal31f21802020-06-12 05:38:46 +00001525 logger.Warnw(ctx, "childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001526 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001527 }
khenaidooe132f522020-03-20 15:23:15 -04001528 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1529 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001530}
onkarkundargi87285252020-01-27 11:34:52 +05301531
Kent Hagerman45a13e42020-04-13 12:23:50 -04001532func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001533 log.EnrichSpan(ctx, log.Fields{"device-id": request.Id})
1534
Rohan Agrawal31f21802020-06-12 05:38:46 +00001535 logger.Debugw(ctx, "StartOmciTestAction", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001536 agent := dMgr.getDeviceAgent(ctx, request.Id)
1537 if agent == nil {
1538 return nil, status.Errorf(codes.NotFound, "%s", request.Id)
onkarkundargi87285252020-01-27 11:34:52 +05301539 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001540 return agent.startOmciTest(ctx, request)
onkarkundargi87285252020-01-27 11:34:52 +05301541}
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001542
1543func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001544 log.EnrichSpan(ctx, log.Fields{"device-id": value.Id})
1545
Girish Kumar3e8ee212020-08-19 17:50:11 +00001546 logger.Debugw(ctx, "getExtValue", log.Fields{"onu-id": value.Id})
Kent Hagermancba2f302020-07-28 13:37:36 -04001547 cDevice, err := dMgr.getDeviceReadOnly(ctx, value.Id)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001548 if err != nil {
1549 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1550 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001551 pDevice, err := dMgr.getDeviceReadOnly(ctx, cDevice.ParentId)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001552 if err != nil {
1553 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1554 }
1555 if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
1556 resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
1557 if err != nil {
1558 return nil, err
1559 }
Girish Kumar3e8ee212020-08-19 17:50:11 +00001560 logger.Debugw(ctx, "getExtValue-result", log.Fields{"result": resp})
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001561 return resp, nil
1562 }
1563 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1564
1565}
dpaul62686312020-06-23 14:17:36 +05301566
1567// SetExtValue set some given configs or value
1568func (dMgr *Manager) SetExtValue(ctx context.Context, value *voltha.ValueSet) (*empty.Empty, error) {
1569 logger.Debugw(ctx, "setExtValue", log.Fields{"onu-id": value.Id})
1570 device, err := dMgr.getDeviceReadOnly(ctx, value.Id)
1571 if err != nil {
1572 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1573 }
1574 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1575 resp, err := agent.setExtValue(ctx, device, value)
1576 if err != nil {
1577 return nil, err
1578 }
1579 logger.Debugw(ctx, "setExtValue-result", log.Fields{"result": resp})
1580 return resp, nil
1581 }
1582 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1583
1584}