blob: 6274469c804dae52023712c784ba8d00182b2756 [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
serkant.uluderyae25f6482020-12-17 21:08:38 +030025 "github.com/opencord/voltha-go/rw_core/config"
26 "github.com/opencord/voltha-lib-go/v5/pkg/probe"
27
Kent Hagerman45a13e42020-04-13 12:23:50 -040028 "github.com/golang/protobuf/ptypes/empty"
sbarbari17d7e222019-11-05 10:02:29 -050029 "github.com/opencord/voltha-go/db/model"
Kent Hagerman2b216042020-04-03 18:28:56 -040030 "github.com/opencord/voltha-go/rw_core/core/adapter"
Kent Hagermanf5a67352020-04-30 15:15:26 -040031 "github.com/opencord/voltha-go/rw_core/core/device/event"
Kent Hagerman2b216042020-04-03 18:28:56 -040032 "github.com/opencord/voltha-go/rw_core/core/device/remote"
Kent Hagerman6031aad2020-07-29 16:36:33 -040033 "github.com/opencord/voltha-go/rw_core/core/device/state"
khenaidoo3d3b8c22019-05-22 18:10:39 -040034 "github.com/opencord/voltha-go/rw_core/utils"
yasin sapli5458a1c2021-06-14 22:24:38 +000035 "github.com/opencord/voltha-lib-go/v5/pkg/events"
36 "github.com/opencord/voltha-lib-go/v5/pkg/kafka"
37 "github.com/opencord/voltha-lib-go/v5/pkg/log"
Maninderdfadc982020-10-28 14:04:33 +053038 "github.com/opencord/voltha-protos/v4/go/common"
39 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
40 "github.com/opencord/voltha-protos/v4/go/openflow_13"
41 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
42 "github.com/opencord/voltha-protos/v4/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040043 "google.golang.org/grpc/codes"
44 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040045)
46
Kent Hagerman2b216042020-04-03 18:28:56 -040047// Manager represent device manager attributes
48type Manager struct {
Himani Chawlab4c25912020-11-12 17:16:38 +053049 deviceAgents sync.Map
50 rootDevices map[string]bool
51 lockRootDeviceMap sync.RWMutex
52 adapterProxy *remote.AdapterProxy
Mahir Gunyelb0343bf2021-05-11 14:14:26 -070053 *event.Agent
Kent Hagerman2b216042020-04-03 18:28:56 -040054 adapterMgr *adapter.Manager
55 logicalDeviceMgr *LogicalManager
npujar467fe752020-01-16 20:17:45 +053056 kafkaICProxy kafka.InterContainerProxy
Kent Hagerman6031aad2020-07-29 16:36:33 -040057 stateTransitions *state.TransitionMap
Mahir Gunyel03de0d32020-06-03 01:36:59 -070058 dbPath *model.Path
Kent Hagermanf5a67352020-04-30 15:15:26 -040059 dProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053060 coreInstanceID string
khenaidoo442e7c72020-03-10 16:13:48 -040061 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040062 devicesLoadingLock sync.RWMutex
63 deviceLoadingInProgress map[string][]chan int
Maninder0aabf0c2021-03-17 14:55:14 +053064 config *config.RWCoreFlags
khenaidoob9203542018-09-17 22:56:37 -040065}
66
Mahir Gunyel03de0d32020-06-03 01:36:59 -070067//NewManagers creates the Manager and the Logical Manager.
Maninder0aabf0c2021-03-17 14:55:14 +053068func NewManagers(dbPath *model.Path, adapterMgr *adapter.Manager, kmp kafka.InterContainerProxy, endpointMgr kafka.EndpointManager, cf *config.RWCoreFlags, coreInstanceID string, eventProxy *events.EventProxy) (*Manager, *LogicalManager) {
Kent Hagerman2b216042020-04-03 18:28:56 -040069 deviceMgr := &Manager{
Kent Hagerman2b216042020-04-03 18:28:56 -040070 rootDevices: make(map[string]bool),
71 kafkaICProxy: kmp,
Maninder0aabf0c2021-03-17 14:55:14 +053072 adapterProxy: remote.NewAdapterProxy(kmp, cf.CoreTopic, endpointMgr),
Kent Hagerman2b216042020-04-03 18:28:56 -040073 coreInstanceID: coreInstanceID,
Mahir Gunyel03de0d32020-06-03 01:36:59 -070074 dbPath: dbPath,
75 dProxy: dbPath.Proxy("devices"),
Kent Hagerman2b216042020-04-03 18:28:56 -040076 adapterMgr: adapterMgr,
Maninder0aabf0c2021-03-17 14:55:14 +053077 defaultTimeout: cf.DefaultCoreTimeout,
78 Agent: event.NewAgent(eventProxy, coreInstanceID, cf.VolthaStackID),
Kent Hagerman2b216042020-04-03 18:28:56 -040079 deviceLoadingInProgress: make(map[string][]chan int),
Maninder0aabf0c2021-03-17 14:55:14 +053080 config: cf,
Kent Hagerman2b216042020-04-03 18:28:56 -040081 }
Kent Hagerman6031aad2020-07-29 16:36:33 -040082 deviceMgr.stateTransitions = state.NewTransitionMap(deviceMgr)
Kent Hagerman2f0d0552020-04-23 17:28:52 -040083
Kent Hagerman2b216042020-04-03 18:28:56 -040084 logicalDeviceMgr := &LogicalManager{
Maninder0aabf0c2021-03-17 14:55:14 +053085 Manager: event.NewManager(eventProxy, coreInstanceID, cf.VolthaStackID),
Kent Hagerman2b216042020-04-03 18:28:56 -040086 deviceMgr: deviceMgr,
87 kafkaICProxy: kmp,
Mahir Gunyel03de0d32020-06-03 01:36:59 -070088 dbPath: dbPath,
89 ldProxy: dbPath.Proxy("logical_devices"),
Maninder0aabf0c2021-03-17 14:55:14 +053090 defaultTimeout: cf.DefaultCoreTimeout,
Kent Hagerman2b216042020-04-03 18:28:56 -040091 logicalDeviceLoadingInProgress: make(map[string][]chan int),
92 }
93 deviceMgr.logicalDeviceMgr = logicalDeviceMgr
Matteo Scandolod525ae32020-04-02 17:27:29 -070094
Kent Hagerman2b216042020-04-03 18:28:56 -040095 adapterMgr.SetAdapterRestartedCallback(deviceMgr.adapterRestarted)
Matteo Scandolod525ae32020-04-02 17:27:29 -070096
Kent Hagerman2b216042020-04-03 18:28:56 -040097 return deviceMgr, logicalDeviceMgr
khenaidoob9203542018-09-17 22:56:37 -040098}
99
khenaidoo7585a962021-06-10 16:15:38 -0400100func (dMgr *Manager) Start(ctx context.Context) {
101 logger.Info(ctx, "starting-device-manager")
102 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusPreparing)
103
104 // Load all the devices from the dB
105 var devices []*voltha.Device
106 if err := dMgr.dProxy.List(ctx, &devices); err != nil {
107 // Any error from the dB means if we proceed we may end up with corrupted data
108 logger.Fatalw(ctx, "failed-to-list-devices-from-KV", log.Fields{"error": err})
109 }
110
111 for _, device := range devices {
112 // Create an agent for each device
113 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
114 if _, err := agent.start(ctx, true, device); err != nil {
115 logger.Warnw(ctx, "failure-starting-agent", log.Fields{"device-id": device.Id})
116 } else {
117 dMgr.addDeviceAgentToMap(agent)
118 }
119 }
120
121 // TODO: Need to trigger a reconcile at this point
122
123 probe.UpdateStatusFromContext(ctx, "device-manager", probe.ServiceStatusRunning)
124 logger.Info(ctx, "device-manager-started")
125}
126
Kent Hagerman2b216042020-04-03 18:28:56 -0400127func (dMgr *Manager) addDeviceAgentToMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +0530128 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
129 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -0400130 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400131 dMgr.lockRootDeviceMap.Lock()
132 defer dMgr.lockRootDeviceMap.Unlock()
Kent Hagerman2a07b862020-06-19 15:23:07 -0400133 dMgr.rootDevices[agent.deviceID] = agent.isRootDevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400134
khenaidoob9203542018-09-17 22:56:37 -0400135}
136
Kent Hagerman2b216042020-04-03 18:28:56 -0400137func (dMgr *Manager) deleteDeviceAgentFromMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +0530138 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400139 dMgr.lockRootDeviceMap.Lock()
140 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530141 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400142}
143
khenaidoo297cd252019-02-07 22:10:23 -0500144// 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 -0400145func (dMgr *Manager) getDeviceAgent(ctx context.Context, deviceID string) *Agent {
npujar1d86a522019-11-14 17:11:16 +0530146 agent, ok := dMgr.deviceAgents.Load(deviceID)
147 if ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400148 return agent.(*Agent)
khenaidoob9203542018-09-17 22:56:37 -0400149 }
khenaidoo442e7c72020-03-10 16:13:48 -0400150 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530151 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530152 if err == nil {
153 agent, ok = dMgr.deviceAgents.Load(deviceID)
154 if !ok {
155 return nil
156 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400157 return agent.(*Agent)
npujar1d86a522019-11-14 17:11:16 +0530158 }
159 //TODO: Change the return params to return an error as well
divyadesaicb8b59d2020-08-18 09:55:47 +0000160 logger.Errorw(ctx, "loading-device-failed", log.Fields{"device-id": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400161 return nil
162}
163
khenaidoo297cd252019-02-07 22:10:23 -0500164// listDeviceIdsFromMap returns the list of device IDs that are in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400165func (dMgr *Manager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500166 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400167
168 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
169 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
170 return true
171 })
172
khenaidoo7ccedd52018-12-14 16:48:54 -0500173 return result
174}
175
Kent Hagerman45a13e42020-04-13 12:23:50 -0400176// CreateDevice creates a new parent device in the data model
177func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
178 if device.MacAddress == "" && device.GetHostAndPort() == "" {
Himani Chawlab4c25912020-11-12 17:16:38 +0530179 logger.Errorf(ctx, "no-device-info-present")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400180 return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
181 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530182 ctx = utils.WithRPCMetadataContext(ctx, "CreateDevice")
Rohan Agrawal31f21802020-06-12 05:38:46 +0000183 logger.Debugw(ctx, "create-device", log.Fields{"device": *device})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400184
npujar467fe752020-01-16 20:17:45 +0530185 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530186 if err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530187 logger.Errorf(ctx, "failed-to-fetch-parent-device-info")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400188 return nil, err
Thomas Lee Se5a44012019-11-07 20:32:24 +0530189 }
190 if deviceExist {
Himani Chawlab4c25912020-11-12 17:16:38 +0530191 logger.Errorf(ctx, "device-is-pre-provisioned-already-with-same-ip-port-or-mac-address")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400192 return nil, errors.New("device is already pre-provisioned")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530193 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530194 logger.Debugw(ctx, "create-device", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400195
khenaidoo5e677ae2019-02-28 17:26:29 -0500196 // Ensure this device is set as root
197 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400198 // Create and start a device agent for that device
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700199 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
khenaidoo7585a962021-06-10 16:15:38 -0400200 device, err = agent.start(ctx, false, device)
Scott Baker80678602019-11-14 16:57:36 -0800201 if err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530202 logger.Errorw(ctx, "fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400203 return nil, err
Scott Baker80678602019-11-14 16:57:36 -0800204 }
khenaidoo442e7c72020-03-10 16:13:48 -0400205 dMgr.addDeviceAgentToMap(agent)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400206 return device, nil
khenaidoob9203542018-09-17 22:56:37 -0400207}
208
Kent Hagerman45a13e42020-04-13 12:23:50 -0400209// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
210func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530211 ctx = utils.WithRPCMetadataContext(ctx, "EnableDevice")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000212 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530213 logger.Debugw(ctx, "enable-device", 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)
khenaidoob9203542018-09-17 22:56:37 -0400217 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400218 return &empty.Empty{}, agent.enableDevice(ctx)
khenaidoob9203542018-09-17 22:56:37 -0400219}
220
Kent Hagerman45a13e42020-04-13 12:23:50 -0400221// DisableDevice disables a device along with any child device it may have
222func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530223 ctx = utils.WithRPCMetadataContext(ctx, "DisableDevice")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000224 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530225 logger.Debugw(ctx, "disable-device", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400226 agent := dMgr.getDeviceAgent(ctx, id.Id)
227 if agent == nil {
228 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400229 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400230 return &empty.Empty{}, agent.disableDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400231}
232
Kent Hagerman45a13e42020-04-13 12:23:50 -0400233//RebootDevice invoked the reboot API to the corresponding adapter
234func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530235 ctx = utils.WithRPCMetadataContext(ctx, "RebootDevice")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000236 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530237 logger.Debugw(ctx, "reboot-device", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400238 agent := dMgr.getDeviceAgent(ctx, id.Id)
239 if agent == nil {
240 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400241 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400242 return &empty.Empty{}, agent.rebootDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400243}
244
Kent Hagerman45a13e42020-04-13 12:23:50 -0400245// DeleteDevice removes a device from the data model
246func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530247 ctx = utils.WithRPCMetadataContext(ctx, "DeleteDevice")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000248 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530249 logger.Debugw(ctx, "delete-device", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400250 agent := dMgr.getDeviceAgent(ctx, id.Id)
251 if agent == nil {
252 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400253 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400254 return &empty.Empty{}, agent.deleteDevice(ctx)
255}
256
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530257// ForceDeleteDevice removes a device from the data model forcefully without successfully waiting for the adapters.
258func (dMgr *Manager) ForceDeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530259 ctx = utils.WithRPCMetadataContext(ctx, "ForceDeleteDevice")
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530260 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530261 logger.Debugw(ctx, "force-delete-device", log.Fields{"device-id": id.Id})
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530262 agent := dMgr.getDeviceAgent(ctx, id.Id)
263 if agent == nil {
264 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
265 }
266 return &empty.Empty{}, agent.deleteDeviceForce(ctx)
267}
268
Kent Hagerman2a07b862020-06-19 15:23:07 -0400269// GetDevicePort returns the port details for a specific device port entry
270func (dMgr *Manager) GetDevicePort(ctx context.Context, deviceID string, portID uint32) (*voltha.Port, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530271 logger.Debugw(ctx, "get-device-port", log.Fields{"device-id": deviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400272 agent := dMgr.getDeviceAgent(ctx, deviceID)
273 if agent == nil {
274 return nil, status.Errorf(codes.NotFound, "device-%s", deviceID)
275 }
276 return agent.getDevicePort(portID)
277}
278
Kent Hagerman45a13e42020-04-13 12:23:50 -0400279// ListDevicePorts returns the ports details for a specific device entry
280func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530281 ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePorts")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000282 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530283 logger.Debugw(ctx, "list-device-ports", log.Fields{"device-id": id.Id})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400284 agent := dMgr.getDeviceAgent(ctx, id.Id)
285 if agent == nil {
286 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400287 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400288
289 ports := agent.listDevicePorts()
290 ctr, ret := 0, make([]*voltha.Port, len(ports))
291 for _, port := range ports {
292 ret[ctr] = port
293 ctr++
294 }
295 return &voltha.Ports{Items: ret}, nil
Kent Hagerman45a13e42020-04-13 12:23:50 -0400296}
297
298// ListDeviceFlows returns the flow details for a specific device entry
299func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530300 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlows")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000301 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530302 logger.Debugw(ctx, "list-device-flows", log.Fields{"device-id": id.Id})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700303 agent := dMgr.getDeviceAgent(ctx, id.Id)
304 if agent == nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400305 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400306 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700307
308 flows := agent.listDeviceFlows()
309 ctr, ret := 0, make([]*ofp.OfpFlowStats, len(flows))
310 for _, flow := range flows {
311 ret[ctr] = flow
312 ctr++
313 }
314 return &openflow_13.Flows{Items: ret}, nil
Kent Hagerman45a13e42020-04-13 12:23:50 -0400315}
316
317// ListDeviceFlowGroups returns the flow group details for a specific device entry
318func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*voltha.FlowGroups, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530319 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlowGroups")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000320 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530321 logger.Debugw(ctx, "list-device-flow-groups", log.Fields{"device-id": id.Id})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700322 agent := dMgr.getDeviceAgent(ctx, id.Id)
323 if agent == nil {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400324 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
325 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700326 groups := agent.listDeviceGroups()
327 ctr, ret := 0, make([]*openflow_13.OfpGroupEntry, len(groups))
328 for _, group := range groups {
329 ret[ctr] = group
330 ctr++
331 }
332 return &voltha.FlowGroups{Items: ret}, nil
khenaidoo4d4802d2018-10-04 21:59:49 -0400333}
334
khenaidoo6d62c002019-05-15 21:57:03 -0400335// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
336// This function is called only in the Core that does not own this device. In the Core that owns this device then a
337// deletion deletion also includes removal of any reference of this device.
Kent Hagerman2b216042020-04-03 18:28:56 -0400338func (dMgr *Manager) stopManagingDevice(ctx context.Context, id string) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530339 logger.Infow(ctx, "stop-managing-device", log.Fields{"device-id": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400340 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
Kent Hagerman6031aad2020-07-29 16:36:33 -0400341 if device, err := dMgr.getDeviceReadOnly(ctx, id); err == nil && device.Root {
khenaidoo6d62c002019-05-15 21:57:03 -0400342 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700343 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400344 }
npujar467fe752020-01-16 20:17:45 +0530345 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400346 if err := agent.stop(ctx); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000347 logger.Warnw(ctx, "unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400348 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400349 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400350 }
351 }
352}
353
npujar1d86a522019-11-14 17:11:16 +0530354// RunPostDeviceDelete removes any reference of this device
Kent Hagerman2b216042020-04-03 18:28:56 -0400355func (dMgr *Manager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530356 logger.Infow(ctx, "run-post-device-delete", log.Fields{"device-id": cDevice.Id})
Andrea Campanella408dec62021-11-10 14:32:10 +0100357 //deleting the logical device
358 logger.Debugw(ctx, "delete-logical-device", log.Fields{"device-id": cDevice.Id})
359 if dMgr.logicalDeviceMgr != nil && cDevice.Root {
360 if err := dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
361 logger.Warnw(ctx, "failure-delete-logical-device", log.Fields{"device-id": cDevice.Id, "error": err.Error()})
362 }
363 // Remove the logical device Id from the parent device
364 logicalID := ""
365 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
366 }
serkant.uluderyae25f6482020-12-17 21:08:38 +0300367 if agent := dMgr.getDeviceAgent(ctx, cDevice.Id); agent != nil {
368 logger.Debugw(ctx, "invoking-delete-device-ports", log.Fields{"device-id": cDevice.Id})
369 //delete ports
370 if err := agent.deleteAllPorts(ctx); err != nil {
371 logger.Warnw(ctx, "failure-delete-device-ports", log.Fields{"device-id": cDevice.Id, "error": err.Error()})
372 }
373 }
npujar467fe752020-01-16 20:17:45 +0530374 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400375 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400376}
377
Kent Hagermancba2f302020-07-28 13:37:36 -0400378// GetDevice exists primarily to implement the gRPC interface.
379// Internal functions should call getDeviceReadOnly instead.
Kent Hagerman45a13e42020-04-13 12:23:50 -0400380func (dMgr *Manager) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530381 ctx = utils.WithRPCMetadataContext(ctx, "GetDevice")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000382 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Kent Hagermancba2f302020-07-28 13:37:36 -0400383 return dMgr.getDeviceReadOnly(ctx, id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400384}
385
Kent Hagermancba2f302020-07-28 13:37:36 -0400386// getDeviceReadOnly will returns a device, either from memory or from the dB, if present
387func (dMgr *Manager) getDeviceReadOnly(ctx context.Context, id string) (*voltha.Device, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530388 logger.Debugw(ctx, "get-device-read-only", log.Fields{"device-id": id})
npujar467fe752020-01-16 20:17:45 +0530389 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
Kent Hagermancba2f302020-07-28 13:37:36 -0400390 return agent.getDeviceReadOnly(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400391 }
392 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400393}
394
Kent Hagerman2a07b862020-06-19 15:23:07 -0400395func (dMgr *Manager) listDevicePorts(ctx context.Context, id string) (map[uint32]*voltha.Port, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530396 logger.Debugw(ctx, "list-device-ports", log.Fields{"device-id": id})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400397 agent := dMgr.getDeviceAgent(ctx, id)
398 if agent == nil {
399 return nil, status.Errorf(codes.NotFound, "%s", id)
400 }
401 return agent.listDevicePorts(), nil
402}
403
npujar1d86a522019-11-14 17:11:16 +0530404// GetChildDevice will return a device, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -0400405func (dMgr *Manager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530406 logger.Debugw(ctx, "get-child-device", log.Fields{"parent-device-id": parentDeviceID, "serialNumber": serialNumber,
407 "parent-port-no": parentPortNo, "onu-id": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500408
Kent Hagerman2a07b862020-06-19 15:23:07 -0400409 parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
410 if err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500411 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
412 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400413 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500414 if len(childDeviceIds) == 0 {
Himani Chawlab4c25912020-11-12 17:16:38 +0530415 logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": parentDeviceID, "serial-number": serialNumber, "onu-id": onuID})
npujar1d86a522019-11-14 17:11:16 +0530416 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500417 }
418
419 var foundChildDevice *voltha.Device
Kent Hagerman2a07b862020-06-19 15:23:07 -0400420 for childDeviceID := range childDeviceIds {
npujar1d86a522019-11-14 17:11:16 +0530421 var found bool
Kent Hagermancba2f302020-07-28 13:37:36 -0400422 if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500423
npujar1d86a522019-11-14 17:11:16 +0530424 foundOnuID := false
425 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500426 if searchDevice.ParentPortNo == uint32(parentPortNo) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530427 logger.Debugw(ctx, "found-child-by-onuid", log.Fields{"parent-device-id": parentDeviceID, "onu-id": onuID})
npujar1d86a522019-11-14 17:11:16 +0530428 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500429 }
430 }
431
432 foundSerialNumber := false
433 if searchDevice.SerialNumber == serialNumber {
Himani Chawlab4c25912020-11-12 17:16:38 +0530434 logger.Debugw(ctx, "found-child-by-serial-number", log.Fields{"parent-device-id": parentDeviceID, "serial-number": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500435 foundSerialNumber = true
436 }
437
438 // if both onuId and serialNumber are provided both must be true for the device to be found
439 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530440 if onuID > 0 && serialNumber != "" {
441 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500442 } else {
npujar1d86a522019-11-14 17:11:16 +0530443 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500444 }
445
npujar1d86a522019-11-14 17:11:16 +0530446 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500447 foundChildDevice = searchDevice
448 break
449 }
450 }
451 }
452
453 if foundChildDevice != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530454 logger.Debugw(ctx, "child-device-found", log.Fields{"parent-device-id": parentDeviceID, "found-child-device": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500455 return foundChildDevice, nil
456 }
457
divyadesaicb8b59d2020-08-18 09:55:47 +0000458 logger.Debugw(ctx, "child-device-not-found", log.Fields{"parent-device-id": parentDeviceID,
Himani Chawlab4c25912020-11-12 17:16:38 +0530459 "serial-number": serialNumber, "onu-id": onuID, "parent-port-no": parentPortNo})
npujar1d86a522019-11-14 17:11:16 +0530460 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500461}
462
npujar1d86a522019-11-14 17:11:16 +0530463// GetChildDeviceWithProxyAddress will return a device based on proxy address
Kent Hagerman2b216042020-04-03 18:28:56 -0400464func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530465 logger.Debugw(ctx, "get-child-device-with-proxy-address", log.Fields{"proxy-address": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500466
Kent Hagerman2a07b862020-06-19 15:23:07 -0400467 parentDevicePorts, err := dMgr.listDevicePorts(ctx, proxyAddress.DeviceId)
468 if err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500469 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
470 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400471 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500472 if len(childDeviceIds) == 0 {
divyadesaicb8b59d2020-08-18 09:55:47 +0000473 logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": proxyAddress.DeviceId})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500474 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
475 }
476
477 var foundChildDevice *voltha.Device
Kent Hagerman2a07b862020-06-19 15:23:07 -0400478 for childDeviceID := range childDeviceIds {
Kent Hagermancba2f302020-07-28 13:37:36 -0400479 if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500480 if searchDevice.ProxyAddress == proxyAddress {
481 foundChildDevice = searchDevice
482 break
483 }
484 }
485 }
486
487 if foundChildDevice != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530488 logger.Debugw(ctx, "child-device-found", log.Fields{"proxy-address": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500489 return foundChildDevice, nil
490 }
491
Himani Chawlab4c25912020-11-12 17:16:38 +0530492 logger.Warnw(ctx, "child-device-not-found", log.Fields{"proxy-address": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500493 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
494}
495
npujar1d86a522019-11-14 17:11:16 +0530496// IsDeviceInCache returns true if device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400497func (dMgr *Manager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400498 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500499 return exist
500}
501
Stephane Barbarieaa467942019-02-06 14:09:44 -0500502// ListDevices retrieves the latest devices from the data model
Kent Hagerman45a13e42020-04-13 12:23:50 -0400503func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530504 ctx = utils.WithRPCMetadataContext(ctx, "ListDevices")
505 logger.Debug(ctx, "list-devices")
khenaidoob9203542018-09-17 22:56:37 -0400506 result := &voltha.Devices{}
Kent Hagerman4f355f52020-03-30 16:01:33 -0400507
Esin Karamana4e4e002021-03-02 10:42:16 +0000508 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
509 result.Items = append(result.Items, value.(*Agent).device)
510 return true
511 })
Kent Hagerman4f355f52020-03-30 16:01:33 -0400512
Himani Chawlab4c25912020-11-12 17:16:38 +0530513 logger.Debugw(ctx, "list-devices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400514 return result, nil
515}
516
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530517//isParentDeviceExist checks whether device is already preprovisioned.
Kent Hagerman2b216042020-04-03 18:28:56 -0400518func (dMgr *Manager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530519 hostPort := newDevice.GetHostAndPort()
Kent Hagerman4f355f52020-03-30 16:01:33 -0400520 var devices []*voltha.Device
Kent Hagermanf5a67352020-04-30 15:15:26 -0400521 if err := dMgr.dProxy.List(ctx, &devices); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530522 logger.Errorw(ctx, "failed-to-list-devices-from-cluster-data-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530523 return false, err
524 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400525 for _, device := range devices {
526 if !device.Root {
527 continue
528 }
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530529
530 if hostPort != "" && hostPort == device.GetHostAndPort() {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400531 return true, nil
532 }
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530533 if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400534 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530535 }
536 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530537 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530538}
539
khenaidoo6d62c002019-05-15 21:57:03 -0400540//getDeviceFromModelretrieves the device data from the model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400541func (dMgr *Manager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400542 device := &voltha.Device{}
Kent Hagermanf5a67352020-04-30 15:15:26 -0400543 if have, err := dMgr.dProxy.Get(ctx, deviceID, device); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000544 logger.Errorw(ctx, "failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530545 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400546 } else if !have {
547 return nil, status.Error(codes.NotFound, deviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530548 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400549
550 return device, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400551}
552
npujar1d86a522019-11-14 17:11:16 +0530553// loadDevice loads the deviceID in memory, if not present
Kent Hagerman2b216042020-04-03 18:28:56 -0400554func (dMgr *Manager) loadDevice(ctx context.Context, deviceID string) (*Agent, error) {
npujar1d86a522019-11-14 17:11:16 +0530555 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500556 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
557 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400558 var err error
559 var device *voltha.Device
560 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530561 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
562 if !dMgr.IsDeviceInCache(deviceID) {
563 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400564 dMgr.devicesLoadingLock.Unlock()
565 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530566 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000567 logger.Debugw(ctx, "loading-device", log.Fields{"device-id": deviceID})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700568 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
khenaidoo7585a962021-06-10 16:15:38 -0400569 if _, err = agent.start(ctx, true, device); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530570 logger.Warnw(ctx, "failure-loading-device", log.Fields{"device-id": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400571 } else {
572 dMgr.addDeviceAgentToMap(agent)
573 }
574 } else {
Himani Chawlab4c25912020-11-12 17:16:38 +0530575 logger.Debugw(ctx, "device-is-not-in-model", log.Fields{"device-id": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400576 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400577 // announce completion of task to any number of waiting channels
578 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530579 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400580 for _, ch := range v {
581 close(ch)
582 }
npujar1d86a522019-11-14 17:11:16 +0530583 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400584 }
585 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400586 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400587 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500588 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400589 } else {
590 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530591 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400592 dMgr.devicesLoadingLock.Unlock()
593 // Wait for the channel to be closed, implying the process loading this device is done.
594 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500595 }
npujar1d86a522019-11-14 17:11:16 +0530596 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400597 return agent.(*Agent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500598 }
npujar1d86a522019-11-14 17:11:16 +0530599 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500600}
601
602// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
Kent Hagerman2a07b862020-06-19 15:23:07 -0400603func (dMgr *Manager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device, devicePorts map[uint32]*voltha.Port) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000604 logger.Debugw(ctx, "loading-parent-and-children", log.Fields{"device-id": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500605 if device.Root {
606 // Scenario A
607 if device.ParentId != "" {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400608 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530609 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000610 logger.Warnw(ctx, "failure-loading-logical-device", log.Fields{"logical-device-id": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500611 }
612 } else {
divyadesaicb8b59d2020-08-18 09:55:47 +0000613 logger.Debugw(ctx, "no-parent-to-load", log.Fields{"device-id": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500614 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400615 // Load all child devices, if needed
616 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, devicePorts)
617 for childDeviceID := range childDeviceIds {
618 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000619 logger.Warnw(ctx, "failure-loading-device", log.Fields{"device-id": childDeviceID, "error": err})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400620 return err
khenaidoo297cd252019-02-07 22:10:23 -0500621 }
khenaidoo297cd252019-02-07 22:10:23 -0500622 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530623 logger.Debugw(ctx, "loaded-children", log.Fields{"device-id": device.Id, "num-children": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500624 }
625 return nil
626}
627
628// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
629// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
630// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
631// and the proceed with the request.
Kent Hagerman2b216042020-04-03 18:28:56 -0400632func (dMgr *Manager) load(ctx context.Context, deviceID string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000633 logger.Debug(ctx, "load...")
khenaidoo297cd252019-02-07 22:10:23 -0500634 // 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 -0400635 var dAgent *Agent
khenaidoo297cd252019-02-07 22:10:23 -0500636 var err error
npujar467fe752020-01-16 20:17:45 +0530637 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500638 return err
639 }
640 // Get the loaded device details
Kent Hagermancba2f302020-07-28 13:37:36 -0400641 device, err := dAgent.getDeviceReadOnly(ctx)
khenaidoo442e7c72020-03-10 16:13:48 -0400642 if err != nil {
643 return err
644 }
khenaidoo297cd252019-02-07 22:10:23 -0500645
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530646 // If the device is in Pre-provisioning or getting deleted state stop here
647 if device.AdminState == voltha.AdminState_PREPROVISIONED || dAgent.isDeletionInProgress() {
khenaidoo297cd252019-02-07 22:10:23 -0500648 return nil
649 }
650
651 // Now we face two scenarios
652 if device.Root {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400653 devicePorts := dAgent.listDevicePorts()
654
khenaidoo297cd252019-02-07 22:10:23 -0500655 // Load all children as well as the parent of this device (logical_device)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400656 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device, devicePorts); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000657 logger.Warnw(ctx, "failure-loading-device-parent-and-children", log.Fields{"device-id": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500658 return err
659 }
divyadesaicb8b59d2020-08-18 09:55:47 +0000660 logger.Debugw(ctx, "successfully-loaded-parent-and-children", log.Fields{"device-id": deviceID})
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300661 } else if device.ParentId != "" {
khenaidoo297cd252019-02-07 22:10:23 -0500662 // Scenario B - use the parentId of that device (root device) to trigger the loading
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300663 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500664 }
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300665
khenaidoo297cd252019-02-07 22:10:23 -0500666 return nil
667}
668
khenaidoo7ccedd52018-12-14 16:48:54 -0500669// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000670func (dMgr *Manager) ListDeviceIds(ctx context.Context, _ *empty.Empty) (*voltha.IDs, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530671 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceIds")
672 logger.Debug(ctx, "list-device-ids")
khenaidoo7ccedd52018-12-14 16:48:54 -0500673 // Report only device IDs that are in the device agent map
674 return dMgr.listDeviceIdsFromMap(), nil
675}
676
Kent Hagerman45a13e42020-04-13 12:23:50 -0400677// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
678// trigger loading the devices along with their children and parent in memory
679func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530680 ctx = utils.WithRPCMetadataContext(ctx, "ReconcileDevices")
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300681
682 numDevices := 0
683 if ids != nil {
684 numDevices = len(ids.Items)
685 }
686
687 logger.Debugw(ctx, "reconcile-devices", log.Fields{"num-devices": numDevices})
khenaidoo4c9e5592019-09-09 16:20:41 -0400688 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500689 toReconcile := len(ids.Items)
690 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400691 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500692 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530693 if err = dMgr.load(ctx, id.Id); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000694 logger.Warnw(ctx, "failure-reconciling-device", log.Fields{"device-id": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400695 } else {
npujar1d86a522019-11-14 17:11:16 +0530696 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500697 }
698 }
699 if toReconcile != reconciled {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400700 return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500701 }
702 } else {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400703 return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
khenaidoo7ccedd52018-12-14 16:48:54 -0500704 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400705 return &empty.Empty{}, nil
khenaidoo7ccedd52018-12-14 16:48:54 -0500706}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500707
khenaidooba6b6c42019-08-02 09:11:56 -0400708// adapterRestarted is invoked whenever an adapter is restarted
Kent Hagerman2b216042020-04-03 18:28:56 -0400709func (dMgr *Manager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530710 logger.Debugw(ctx, "adapter-restarted", log.Fields{"adapter-id": adapter.Id, "vendor": adapter.Vendor,
711 "current-replica": adapter.CurrentReplica, "total-replicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidooba6b6c42019-08-02 09:11:56 -0400712
713 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700714 if len(dMgr.rootDevices) == 0 {
Himani Chawlab4c25912020-11-12 17:16:38 +0530715 logger.Debugw(ctx, "nothing-to-reconcile", log.Fields{"adapter-id": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400716 return nil
717 }
718
Maninder0aabf0c2021-03-17 14:55:14 +0530719 if len(dMgr.rootDevices) == 0 {
720 logger.Debugw(ctx, "no-managed-device-to-reconcile", log.Fields{"adapter-id": adapter.Id})
721 return nil
722 }
723
David Bainbridged1afd662020-03-26 18:27:41 -0700724 for rootDeviceID := range dMgr.rootDevices {
Mahir Gunyel12cf55f2020-12-16 17:55:03 -0800725 dAgent := dMgr.getDeviceAgent(ctx, rootDeviceID)
726 if dAgent == nil {
727 continue
728 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530729 logger.Debugw(ctx, "checking-adapter-type", log.Fields{"agentType": dAgent.deviceType, "adapter-type": adapter.Type})
Mahir Gunyel12cf55f2020-12-16 17:55:03 -0800730 if dAgent.deviceType == adapter.Type {
731 rootDevice, _ := dAgent.getDeviceReadOnly(ctx)
732 if rootDevice == nil {
733 continue
734 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000735 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(ctx, rootDeviceID, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700736 if err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530737 logger.Warnw(ctx, "is-device-owned-by-service", log.Fields{"error": err, "root-device-id": rootDeviceID, "adapter-type": adapter.Type, "replica-number": adapter.CurrentReplica})
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700738 continue
739 }
740 if isDeviceOwnedByService {
Maninder0aabf0c2021-03-17 14:55:14 +0530741 if rootDevice.AdminState != voltha.AdminState_PREPROVISIONED {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000742 logger.Debugw(ctx, "reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
Maninder0aabf0c2021-03-17 14:55:14 +0530743 go dAgent.ReconcileDevice(ctx, rootDevice)
khenaidooba6b6c42019-08-02 09:11:56 -0400744 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000745 logger.Debugw(ctx, "not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400746 }
747 } else { // Should we be reconciling the root's children instead?
Kent Hagerman2a07b862020-06-19 15:23:07 -0400748 rootDevicePorts, _ := dMgr.listDevicePorts(ctx, rootDeviceID)
khenaidooba6b6c42019-08-02 09:11:56 -0400749 childManagedByAdapter:
Kent Hagerman2a07b862020-06-19 15:23:07 -0400750 for _, port := range rootDevicePorts {
khenaidooba6b6c42019-08-02 09:11:56 -0400751 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530752 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000753 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(ctx, childDevice.Id, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700754 if err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530755 logger.Warnw(ctx, "is-device-owned-by-service", log.Fields{"error": err, "child-device-id": childDevice.Id, "adapter-type": adapter.Type, "replica-number": adapter.CurrentReplica})
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700756 }
757 if isDeviceOwnedByService {
Maninder0aabf0c2021-03-17 14:55:14 +0530758 if childDevice.AdminState != voltha.AdminState_PREPROVISIONED {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000759 logger.Debugw(ctx, "reconciling-child-device", log.Fields{"child-device-id": childDevice.Id})
Maninder0aabf0c2021-03-17 14:55:14 +0530760 go dAgent.ReconcileDevice(ctx, childDevice)
khenaidooba6b6c42019-08-02 09:11:56 -0400761 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000762 logger.Debugw(ctx, "not-reconciling-child-device", log.Fields{"child-device-id": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400763 }
764 } else {
765 // All child devices under a parent device are typically managed by the same adapter type.
766 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
767 break childManagedByAdapter
768 }
769 }
770 }
771 }
772 }
773 }
774 }
Maninder0aabf0c2021-03-17 14:55:14 +0530775 logger.Debugw(ctx, "Reconciling for device on adapter restart is initiated", log.Fields{"adapter-id": adapter.Id})
776
khenaidooba6b6c42019-08-02 09:11:56 -0400777 return nil
778}
779
Kent Hagerman2b216042020-04-03 18:28:56 -0400780func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID string) error {
Maninder0aabf0c2021-03-17 14:55:14 +0530781 dAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
782 if dAgent == nil {
783 return status.Errorf(codes.NotFound, "error-unable to get agent from device")
784 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400785 if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400786 for _, port := range parentDevicePorts {
khenaidooba6b6c42019-08-02 09:11:56 -0400787 for _, peer := range port.Peers {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400788 if childDevice, err := dMgr.getDeviceFromModel(ctx, peer.DeviceId); err == nil {
Maninder0aabf0c2021-03-17 14:55:14 +0530789 go dAgent.ReconcileDevice(ctx, childDevice)
khenaidooba6b6c42019-08-02 09:11:56 -0400790 }
791 }
792 }
Maninder0aabf0c2021-03-17 14:55:14 +0530793 logger.Debugw(ctx, "Reconcile initiated for child devices", log.Fields{"parent-device-id": parentDeviceID})
khenaidooba6b6c42019-08-02 09:11:56 -0400794 }
795 return nil
796}
797
Kent Hagerman2b216042020-04-03 18:28:56 -0400798func (dMgr *Manager) UpdateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530799 logger.Debugw(ctx, "update-device-using-adapter-data", log.Fields{"device-id": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530800 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
801 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400802 }
803 return status.Errorf(codes.NotFound, "%s", device.Id)
804}
805
khenaidoo0db4c812020-05-27 15:27:30 -0400806func (dMgr *Manager) addPeerPort(ctx context.Context, deviceID string, port *voltha.Port) error {
807 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
808 for _, peerPort := range port.Peers {
809 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
810 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
811 return err
812 }
813 }
814 }
815 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
816 // then a logical port will be added to the logical device and the device route generated. If the port is a
817 // PON port then only the device graph will be generated.
Kent Hagermancba2f302020-07-28 13:37:36 -0400818 device, err := dMgr.getDeviceReadOnly(ctx, deviceID)
khenaidoo0db4c812020-05-27 15:27:30 -0400819 if err != nil {
820 return err
821 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400822 ports, err := dMgr.listDevicePorts(ctx, deviceID)
823 if err != nil {
824 return err
825 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530826 subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
827
828 if err = dMgr.logicalDeviceMgr.updateLogicalPort(subCtx, device, ports, port); err != nil {
khenaidoo0db4c812020-05-27 15:27:30 -0400829 return err
830 }
831 return nil
832}
833
Kent Hagerman2b216042020-04-03 18:28:56 -0400834func (dMgr *Manager) AddPort(ctx context.Context, deviceID string, port *voltha.Port) error {
npujar467fe752020-01-16 20:17:45 +0530835 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530836 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530837 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400838 return err
839 }
khenaidoo0db4c812020-05-27 15:27:30 -0400840 // Setup peer ports in its own routine
841 go func() {
Himani Chawlab4c25912020-11-12 17:16:38 +0530842 subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
843 if err := dMgr.addPeerPort(subCtx, deviceID, port); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000844 logger.Errorw(ctx, "unable-to-add-peer-port", log.Fields{"error": err, "device-id": deviceID})
khenaidoo92e62c52018-10-03 14:02:54 -0400845 }
khenaidoo0db4c812020-05-27 15:27:30 -0400846 }()
khenaidoo92e62c52018-10-03 14:02:54 -0400847 return nil
khenaidoob9203542018-09-17 22:56:37 -0400848 }
npujar1d86a522019-11-14 17:11:16 +0530849 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400850}
851
Kent Hagerman2b216042020-04-03 18:28:56 -0400852func (dMgr *Manager) addFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530853 logger.Debugw(ctx, "add-flows-and-groups", log.Fields{"device-id": deviceID, "groups:": groups, "flow-metadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530854 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
855 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400856 }
npujar1d86a522019-11-14 17:11:16 +0530857 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400858}
859
khenaidoo787224a2020-04-16 18:08:47 -0400860// deleteParentFlows removes flows from the parent device based on specific attributes
861func (dMgr *Manager) deleteParentFlows(ctx context.Context, deviceID string, uniPort uint32, metadata *voltha.FlowMetadata) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530862 logger.Debugw(ctx, "delete-parent-flows", log.Fields{"device-id": deviceID, "uni-port": uniPort, "metadata": metadata})
khenaidoo787224a2020-04-16 18:08:47 -0400863 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400864 if !agent.isRootDevice {
khenaidoo787224a2020-04-16 18:08:47 -0400865 return status.Errorf(codes.FailedPrecondition, "not-a-parent-device-%s", deviceID)
866 }
867 return agent.filterOutFlows(ctx, uniPort, metadata)
868 }
869 return status.Errorf(codes.NotFound, "%s", deviceID)
870}
871
Kent Hagerman2b216042020-04-03 18:28:56 -0400872func (dMgr *Manager) deleteFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530873 logger.Debugw(ctx, "delete-flows-and-groups", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530874 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
875 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400876 }
npujar1d86a522019-11-14 17:11:16 +0530877 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400878}
879
Kent Hagerman2b216042020-04-03 18:28:56 -0400880func (dMgr *Manager) updateFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530881 logger.Debugw(ctx, "update-flows-and-groups", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530882 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
883 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400884 }
npujar1d86a522019-11-14 17:11:16 +0530885 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400886}
887
Kent Hagerman45a13e42020-04-13 12:23:50 -0400888// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
khenaidoob3127472019-07-24 21:04:55 -0400889// following a user action
Kent Hagerman45a13e42020-04-13 12:23:50 -0400890func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530891 ctx = utils.WithRPCMetadataContext(ctx, "UpdateDevicePmConfigs")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000892 log.EnrichSpan(ctx, log.Fields{"device-id": configs.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400893 if configs.Id == "" {
894 return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
khenaidoob3127472019-07-24 21:04:55 -0400895 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400896 agent := dMgr.getDeviceAgent(ctx, configs.Id)
897 if agent == nil {
898 return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
899 }
900 return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
khenaidoob3127472019-07-24 21:04:55 -0400901}
902
Kent Hagerman2b216042020-04-03 18:28:56 -0400903// InitPmConfigs initialize the pm configs as defined by the adapter.
904func (dMgr *Manager) InitPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400905 if pmConfigs.Id == "" {
906 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
907 }
npujar467fe752020-01-16 20:17:45 +0530908 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
909 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400910 }
npujar1d86a522019-11-14 17:11:16 +0530911 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400912}
913
Kent Hagerman45a13e42020-04-13 12:23:50 -0400914// ListDevicePmConfigs returns pm configs of device
915func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530916 ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePmConfigs")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000917 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400918 agent := dMgr.getDeviceAgent(ctx, id.Id)
919 if agent == nil {
920 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob3127472019-07-24 21:04:55 -0400921 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400922 return agent.listPmConfigs(ctx)
khenaidoob3127472019-07-24 21:04:55 -0400923}
924
Kent Hagerman2b216042020-04-03 18:28:56 -0400925func (dMgr *Manager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530926 logger.Debugw(ctx, "get-switch-capability", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530927 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400928 return agent.getSwitchCapability(ctx)
929 }
npujar1d86a522019-11-14 17:11:16 +0530930 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400931}
932
Kent Hagerman2b216042020-04-03 18:28:56 -0400933func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530934 logger.Debugw(ctx, "get-ports", log.Fields{"device-id": deviceID, "port-type": portType})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400935 agent := dMgr.getDeviceAgent(ctx, deviceID)
936 if agent == nil {
937 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400938 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400939 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400940}
941
Kent Hagerman2b216042020-04-03 18:28:56 -0400942func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530943 logger.Debugw(ctx, "update-device-status", log.Fields{"device-id": deviceID, "oper-status": operStatus, "conn-status": connStatus})
npujar467fe752020-01-16 20:17:45 +0530944 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
945 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400946 }
npujar1d86a522019-11-14 17:11:16 +0530947 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400948}
949
Kent Hagerman2b216042020-04-03 18:28:56 -0400950func (dMgr *Manager) UpdateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530951 logger.Debugw(ctx, "update-children-status", log.Fields{"parent-device-id": deviceID, "oper-status": operStatus, "conn-status": connStatus})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400952 parentDevicePorts, err := dMgr.listDevicePorts(ctx, deviceID)
953 if err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400954 return status.Errorf(codes.Aborted, "%s", err.Error())
955 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400956 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
npujar467fe752020-01-16 20:17:45 +0530957 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
958 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530959 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400960 }
961 }
962 }
963 return nil
964}
965
Kent Hagerman2b216042020-04-03 18:28:56 -0400966func (dMgr *Manager) UpdatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530967 logger.Debugw(ctx, "update-port-state", log.Fields{"device-id": deviceID, "port-type": portType, "port-no": portNo, "oper-status": operStatus})
npujar467fe752020-01-16 20:17:45 +0530968 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
969 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530970 logger.Errorw(ctx, "updating-port-state-failed", log.Fields{"device-id": deviceID, "port-no": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400971 return err
972 }
973 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800974 // Do this for NNI and UNIs only. PON ports are not known by logical device
975 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
976 go func() {
Himani Chawlab4c25912020-11-12 17:16:38 +0530977 subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
978 err := dMgr.logicalDeviceMgr.updatePortState(subCtx, deviceID, portNo, operStatus)
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800979 if err != nil {
980 // While we want to handle (catch) and log when
981 // an update to a port was not able to be
982 // propagated to the logical port, we can report
983 // it as a warning and not an error because it
984 // doesn't stop or modify processing.
985 // TODO: VOL-2707
Rohan Agrawal31f21802020-06-12 05:38:46 +0000986 logger.Warnw(ctx, "unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800987 }
988 }()
989 }
khenaidoo442e7c72020-03-10 16:13:48 -0400990 return nil
khenaidoob9203542018-09-17 22:56:37 -0400991 }
npujar1d86a522019-11-14 17:11:16 +0530992 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400993}
994
Kent Hagerman2b216042020-04-03 18:28:56 -0400995func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID string) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530996 logger.Debugw(ctx, "delete-all-ports", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530997 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
998 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400999 return err
1000 }
1001 // Notify the logical device manager to remove all logical ports, if needed.
Kent Hagerman2b216042020-04-03 18:28:56 -04001002 // At this stage the device itself may gave been deleted already at a DeleteAllPorts
khenaidoo0a822f92019-05-08 15:15:57 -04001003 // typically is part of a device deletion phase.
Kent Hagermancba2f302020-07-28 13:37:36 -04001004 if device, err := dMgr.getDeviceReadOnly(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +05301005 go func() {
Himani Chawlab4c25912020-11-12 17:16:38 +05301006 subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
1007 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(subCtx, device); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001008 logger.Errorw(ctx, "unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301009 }
1010 }()
khenaidoo0a822f92019-05-08 15:15:57 -04001011 } else {
divyadesaicb8b59d2020-08-18 09:55:47 +00001012 logger.Warnw(ctx, "failed-to-retrieve-device", log.Fields{"device-id": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001013 return err
1014 }
1015 return nil
1016 }
npujar1d86a522019-11-14 17:11:16 +05301017 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -04001018}
1019
Kent Hagerman2b216042020-04-03 18:28:56 -04001020//UpdatePortsState updates all ports on the device
Kent Hagerman2a07b862020-06-19 15:23:07 -04001021func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, portTypeFilter uint32, state voltha.OperStatus_Types) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301022 logger.Debugw(ctx, "update-ports-state", log.Fields{"device-id": deviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -04001023 agent := dMgr.getDeviceAgent(ctx, deviceID)
1024 if agent == nil {
1025 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -04001026 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001027 if state != voltha.OperStatus_ACTIVE && state != voltha.OperStatus_UNKNOWN {
1028 return status.Error(codes.Unimplemented, "state-change-not-implemented")
1029 }
1030 if err := agent.updatePortsOperState(ctx, portTypeFilter, state); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301031 logger.Warnw(ctx, "update-ports-state-failed", log.Fields{"device-id": deviceID, "error": err})
Kent Hagerman2a07b862020-06-19 15:23:07 -04001032 return err
1033 }
1034 return nil
khenaidoo3ab34882019-05-02 21:33:30 -04001035}
1036
Kent Hagerman2b216042020-04-03 18:28:56 -04001037func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +05301038 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301039 logger.Debugw(ctx, "child-device-detected", log.Fields{"parent-device-id": parentDeviceID, "parent-port-no": parentPortNo, "device-type": deviceType, "channel-id": channelID, "vendor-id": vendorID, "serial-number": serialNumber, "onu-id": onuID})
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001040
npujar1d86a522019-11-14 17:11:16 +05301041 if deviceType == "" && vendorID != "" {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001042 logger.Debug(ctx, "device-type-is-nil-fetching-device-type")
Kent Hagerman45a13e42020-04-13 12:23:50 -04001043 deviceTypes, err := dMgr.adapterMgr.ListDeviceTypes(ctx, nil)
1044 if err != nil {
1045 return nil, err
1046 }
Kent Hagerman4f355f52020-03-30 16:01:33 -04001047 OLoop:
Kent Hagerman45a13e42020-04-13 12:23:50 -04001048 for _, dType := range deviceTypes.Items {
Kent Hagerman4f355f52020-03-30 16:01:33 -04001049 for _, v := range dType.VendorIds {
1050 if v == vendorID {
1051 deviceType = dType.Adapter
1052 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001053 }
1054 }
1055 }
1056 }
1057 //if no match found for the vendorid,report adapter with the custom error message
1058 if deviceType == "" {
Himani Chawlab4c25912020-11-12 17:16:38 +05301059 logger.Errorw(ctx, "failed-to-fetch-adapter-name ", log.Fields{"vendor-id": vendorID})
npujar1d86a522019-11-14 17:11:16 +05301060 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001061 }
khenaidoob9203542018-09-17 22:56:37 -04001062
1063 // Create the ONU device
1064 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -04001065 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +05301066 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -04001067 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +05301068 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -05001069 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -04001070 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001071
khenaidoo442e7c72020-03-10 16:13:48 -04001072 // Get parent device type
1073 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
1074 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +05301075 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001076 }
khenaidoo442e7c72020-03-10 16:13:48 -04001077 if pAgent.deviceType == "" {
1078 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
1079 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001080
npujar467fe752020-01-16 20:17:45 +05301081 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301082 logger.Warnw(ctx, "child-device-exists", log.Fields{"parent-device-id": parentDeviceID, "serial-number": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001083 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001084 }
1085
khenaidoo442e7c72020-03-10 16:13:48 -04001086 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001087
1088 // Create and start a device agent for that device
Mahir Gunyel03de0d32020-06-03 01:36:59 -07001089 agent := newAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
khenaidoo7585a962021-06-10 16:15:38 -04001090 insertedChildDevice, err := agent.start(ctx, false, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001091 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001092 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 -08001093 return nil, err
1094 }
khenaidoo442e7c72020-03-10 16:13:48 -04001095 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001096
1097 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301098 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301099 go func() {
Maninder9a1bc0d2020-10-26 11:34:02 +05301100 subCtx := utils.WithFromTopicMetadataFromContext(utils.WithSpanAndRPCMetadataFromContext(ctx), ctx)
Himani Chawlab4c25912020-11-12 17:16:38 +05301101 err := agent.enableDevice(subCtx)
npujar1d86a522019-11-14 17:11:16 +05301102 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001103 logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301104 }
1105 }()
khenaidoob9203542018-09-17 22:56:37 -04001106 }
1107
Mahir Gunyel23bd8c72020-09-21 23:20:43 -07001108 return insertedChildDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001109}
1110
Kent Hagerman2b216042020-04-03 18:28:56 -04001111func (dMgr *Manager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301112 logger.Debugw(ctx, "packet-out", log.Fields{"device-id": deviceID, "out-port": outPort})
npujar467fe752020-01-16 20:17:45 +05301113 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1114 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001115 }
npujar1d86a522019-11-14 17:11:16 +05301116 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001117}
1118
npujar1d86a522019-11-14 17:11:16 +05301119// PacketIn receives packet from adapter
Kent Hagerman2b216042020-04-03 18:28:56 -04001120func (dMgr *Manager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301121 logger.Debugw(ctx, "packet-in", log.Fields{"device-id": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001122 // Get the logical device Id based on the deviceId
1123 var device *voltha.Device
1124 var err error
Kent Hagermancba2f302020-07-28 13:37:36 -04001125 if device, err = dMgr.getDeviceReadOnly(ctx, deviceID); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001126 logger.Errorw(ctx, "device-not-found", log.Fields{"device-id": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001127 return err
1128 }
khenaidoo43c82122018-11-22 18:38:28 -05001129 if !device.Root {
divyadesaicb8b59d2020-08-18 09:55:47 +00001130 logger.Errorw(ctx, "device-not-root", log.Fields{"device-id": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301131 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001132 }
1133
npujar467fe752020-01-16 20:17:45 +05301134 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001135 return err
1136 }
1137 return nil
1138}
1139
Kent Hagerman2b216042020-04-03 18:28:56 -04001140func (dMgr *Manager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301141 logger.Debugw(ctx, "set-parent-id", log.Fields{"device-id": device.Id, "parent-id": parentID})
npujar467fe752020-01-16 20:17:45 +05301142 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1143 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001144 }
1145 return status.Errorf(codes.NotFound, "%s", device.Id)
1146}
1147
Himani Chawlab4c25912020-11-12 17:16:38 +05301148//
1149//CreateLogicalDevice creates logical device in core
Kent Hagerman2b216042020-04-03 18:28:56 -04001150func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301151 logger.Info(ctx, "create-logical-device")
khenaidoo59ef7be2019-06-21 12:40:28 -04001152 // Verify whether the logical device has already been created
1153 if cDevice.ParentId != "" {
Himani Chawlab4c25912020-11-12 17:16:38 +05301154 logger.Debugw(ctx, "parent-device-already-exist", log.Fields{"device-id": cDevice.Id, "logical-device-id": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001155 return nil
1156 }
khenaidoob9203542018-09-17 22:56:37 -04001157 var err error
npujar467fe752020-01-16 20:17:45 +05301158 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301159 logger.Warnw(ctx, "create-logical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001160 return err
1161 }
khenaidoob9203542018-09-17 22:56:37 -04001162 return nil
1163}
1164
npujar1d86a522019-11-14 17:11:16 +05301165// DeleteLogicalDevice deletes logical device from core
Kent Hagerman2b216042020-04-03 18:28:56 -04001166func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301167 logger.Info(ctx, "delete-logical-device")
serkant.uluderyae25f6482020-12-17 21:08:38 +03001168 if err := dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -04001169 return err
1170 }
1171 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301172 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301173 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001174 return nil
1175}
1176
npujar1d86a522019-11-14 17:11:16 +05301177// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagerman2b216042020-04-03 18:28:56 -04001178func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001179 logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001180 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001181 // Just log the error. The logical device or port may already have been deleted before this callback is invoked.
Himani Chawlab4c25912020-11-12 17:16:38 +05301182 logger.Warnw(ctx, "delete-logical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001183 }
1184 return nil
1185}
1186
Kent Hagerman2b216042020-04-03 18:28:56 -04001187func (dMgr *Manager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001188 // Sanity check
1189 if childDevice.Root {
1190 // childDevice is the parent device
1191 return childDevice
1192 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001193 parentDevice, _ := dMgr.getDeviceReadOnly(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001194 return parentDevice
1195}
1196
Kent Hagerman2b216042020-04-03 18:28:56 -04001197//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 -04001198//cannot manage the child devices. This will trigger the Core to disable all the child devices.
Kent Hagerman2b216042020-04-03 18:28:56 -04001199func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301200 logger.Debug(ctx, "child-devices-lost")
Kent Hagermancba2f302020-07-28 13:37:36 -04001201 parentDevice, err := dMgr.getDeviceReadOnly(ctx, parentDeviceID)
Kent Hagerman2a07b862020-06-19 15:23:07 -04001202 if err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001203 logger.Warnw(ctx, "failed-getting-device", log.Fields{"parent-device-id": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001204 return err
1205 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001206 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001207}
1208
Kent Hagerman2b216042020-04-03 18:28:56 -04001209//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
khenaidoo0a822f92019-05-08 15:15:57 -04001210// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
Kent Hagerman2b216042020-04-03 18:28:56 -04001211func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301212 logger.Debug(ctx, "child-devices-detected")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001213 parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
1214 if err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001215 logger.Warnw(ctx, "failed-getting-device", log.Fields{"device-id": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001216 return err
1217 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001218 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
khenaidoo0a822f92019-05-08 15:15:57 -04001219 if len(childDeviceIds) == 0 {
divyadesaicb8b59d2020-08-18 09:55:47 +00001220 logger.Debugw(ctx, "no-child-device", log.Fields{"parent-device-id": parentDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001221 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001222 allChildEnableRequestSent := true
Kent Hagerman2a07b862020-06-19 15:23:07 -04001223 for childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301224 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301225 subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
khenaidoo59ef7be2019-06-21 12:40:28 -04001226 // Run the children re-registration in its own routine
Kent Hagerman2a07b862020-06-19 15:23:07 -04001227 go func(ctx context.Context) {
1228 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301229 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001230 logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301231 }
Himani Chawlab4c25912020-11-12 17:16:38 +05301232 }(subCtx)
khenaidoo59ef7be2019-06-21 12:40:28 -04001233 } else {
npujar1d86a522019-11-14 17:11:16 +05301234 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Himani Chawlab4c25912020-11-12 17:16:38 +05301235 logger.Errorw(ctx, "no-child-device-agent", log.Fields{"parent-device-id": parentDeviceID, "child-id": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001236 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001237 }
1238 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001239 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001240 return err
1241 }
1242 return nil
1243}
1244
khenaidoo4d4802d2018-10-04 21:59:49 -04001245/*
1246All the functions below are callback functions where they are invoked with the latest and previous data. We can
1247therefore use the data as is without trying to get the latest from the model.
1248*/
1249
khenaidoo0a822f92019-05-08 15:15:57 -04001250//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagerman2b216042020-04-03 18:28:56 -04001251func (dMgr *Manager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301252 logger.Debug(ctx, "disable-all-child-devices")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001253 ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
1254 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
npujar467fe752020-01-16 20:17:45 +05301255 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -04001256 if err := agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001257 // Just log the error - this error happens only if the child device was already in deleted state.
divyadesaicb8b59d2020-08-18 09:55:47 +00001258 logger.Errorw(ctx, "failure-disable-device", log.Fields{"device-id": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001259 }
1260 }
1261 }
1262 return nil
1263}
1264
khenaidoo0a822f92019-05-08 15:15:57 -04001265//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001266func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301267 logger.Debug(ctx, "delete-all-child-devices")
Himani Chawla2ba1c9c2020-10-07 13:19:03 +05301268 force := false
1269 // Get the parent device Transient state, if its FORCE_DELETED(go for force delete for child devices)
1270 // So in cases when this handler is getting called other than DELETE operation, no force option would be used.
1271 agent := dMgr.getDeviceAgent(ctx, parentCurrDevice.Id)
1272 if agent == nil {
1273 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
1274 }
1275
1276 force = agent.getTransientState() == voltha.DeviceTransientState_FORCE_DELETING
1277
Kent Hagerman2a07b862020-06-19 15:23:07 -04001278 ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
1279 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
npujar467fe752020-01-16 20:17:45 +05301280 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
Himani Chawla2ba1c9c2020-10-07 13:19:03 +05301281 if force {
1282 if err := agent.deleteDeviceForce(ctx); err != nil {
1283 logger.Warnw(ctx, "failure-delete-device-force", log.Fields{"device-id": childDeviceID,
1284 "error": err.Error()})
1285 }
1286 } else {
1287 if err := agent.deleteDevice(ctx); err != nil {
1288 logger.Warnw(ctx, "failure-delete-device", log.Fields{"device-id": childDeviceID,
1289 "error": err.Error()})
1290 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001291 }
khenaidoo49085352020-01-13 19:15:43 -05001292 // No further action is required here. The deleteDevice will change the device state where the resulting
1293 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001294 }
1295 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001296 return nil
1297}
1298
Girish Gowdra408cd962020-03-11 14:31:31 -07001299//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001300func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001301 logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001302 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001303 // Just log error as logical device may already have been deleted
Rohan Agrawal31f21802020-06-12 05:38:46 +00001304 logger.Warnw(ctx, "delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001305 }
1306 return nil
1307}
1308
1309//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001310func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001311 logger.Debugw(ctx, "delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001312 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1313 if err := agent.deleteAllFlows(ctx); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001314 logger.Errorw(ctx, "error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001315 return err
1316 }
1317 return nil
1318 }
1319 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1320}
1321
khenaidoo4d4802d2018-10-04 21:59:49 -04001322//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 -04001323func (dMgr *Manager) getAllChildDeviceIds(ctx context.Context, parentDevicePorts map[uint32]*voltha.Port) map[string]struct{} {
Himani Chawlab4c25912020-11-12 17:16:38 +05301324 logger.Debug(ctx, "get-all-child-device-ids")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001325 childDeviceIds := make(map[string]struct{}, len(parentDevicePorts))
1326 for _, port := range parentDevicePorts {
1327 for _, peer := range port.Peers {
1328 childDeviceIds[peer.DeviceId] = struct{}{}
khenaidoo92e62c52018-10-03 14:02:54 -04001329 }
1330 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001331 logger.Debugw(ctx, "returning-getAllChildDeviceIds", log.Fields{"childDeviceIds": childDeviceIds})
1332 return childDeviceIds
khenaidoo92e62c52018-10-03 14:02:54 -04001333}
1334
Kent Hagerman2b216042020-04-03 18:28:56 -04001335//GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1336func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301337 logger.Debugw(ctx, "get-all-child-devices", log.Fields{"parent-device-id": parentDeviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -04001338 if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001339 childDevices := make([]*voltha.Device, 0)
Kent Hagerman2a07b862020-06-19 15:23:07 -04001340 for deviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
Kent Hagermancba2f302020-07-28 13:37:36 -04001341 if d, e := dMgr.getDeviceReadOnly(ctx, deviceID); e == nil && d != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -04001342 childDevices = append(childDevices, d)
khenaidoo297cd252019-02-07 22:10:23 -05001343 }
1344 }
1345 return &voltha.Devices{Items: childDevices}, nil
1346 }
npujar1d86a522019-11-14 17:11:16 +05301347 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001348}
1349
npujar1d86a522019-11-14 17:11:16 +05301350// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagerman2b216042020-04-03 18:28:56 -04001351func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301352 logger.Info(ctx, "setup-uni-logical-ports")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001353 cDevicePorts, err := dMgr.listDevicePorts(ctx, cDevice.Id)
1354 if err != nil {
1355 return err
1356 }
1357 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice, cDevicePorts); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301358 logger.Warnw(ctx, "setup-uni-logical-ports-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001359 return err
1360 }
1361 return nil
1362}
1363
Kent Hagerman45a13e42020-04-13 12:23:50 -04001364// convenience to avoid redefining
1365var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
1366
1367// DownloadImage execute an image download request
1368func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301369 ctx = utils.WithRPCMetadataContext(ctx, "DownloadImage")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001370 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301371 logger.Debugw(ctx, "download-image", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001372 agent := dMgr.getDeviceAgent(ctx, img.Id)
1373 if agent == nil {
1374 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001375 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001376 resp, err := agent.downloadImage(ctx, img)
1377 if err != nil {
1378 return operationFailureResp, err
1379 }
1380 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001381}
1382
Kent Hagerman45a13e42020-04-13 12:23:50 -04001383// CancelImageDownload cancels image download request
1384func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301385 ctx = utils.WithRPCMetadataContext(ctx, "CancelImageDownload")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001386 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301387 logger.Debugw(ctx, "cancel-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001388 agent := dMgr.getDeviceAgent(ctx, img.Id)
1389 if agent == nil {
1390 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001391 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001392 resp, err := agent.cancelImageDownload(ctx, img)
1393 if err != nil {
1394 return operationFailureResp, err
1395 }
1396 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001397}
1398
Kent Hagerman45a13e42020-04-13 12:23:50 -04001399// ActivateImageUpdate activates image update request
1400func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301401 ctx = utils.WithRPCMetadataContext(ctx, "ActivateImageUpdate")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001402 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301403 logger.Debugw(ctx, "activate-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001404 agent := dMgr.getDeviceAgent(ctx, img.Id)
1405 if agent == nil {
1406 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001407 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001408 resp, err := agent.activateImage(ctx, img)
1409 if err != nil {
1410 return operationFailureResp, err
1411 }
1412 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001413}
1414
Kent Hagerman45a13e42020-04-13 12:23:50 -04001415// RevertImageUpdate reverts image update
1416func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301417 ctx = utils.WithRPCMetadataContext(ctx, "RevertImageUpdate")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001418 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301419 logger.Debugw(ctx, "rever-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001420 agent := dMgr.getDeviceAgent(ctx, img.Id)
1421 if agent == nil {
1422 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001423 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001424 resp, err := agent.revertImage(ctx, img)
1425 if err != nil {
1426 return operationFailureResp, err
1427 }
1428 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001429}
1430
Kent Hagerman45a13e42020-04-13 12:23:50 -04001431// convenience to avoid redefining
1432var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
1433
1434// GetImageDownloadStatus returns status of image download
1435func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301436 ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownloadStatus")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001437 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301438 logger.Debugw(ctx, "get-image-download-status", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001439 agent := dMgr.getDeviceAgent(ctx, img.Id)
1440 if agent == nil {
1441 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001442 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001443 resp, err := agent.getImageDownloadStatus(ctx, img)
1444 if err != nil {
1445 return imageDownloadFailureResp, err
1446 }
1447 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001448}
1449
Kent Hagerman2b216042020-04-03 18:28:56 -04001450func (dMgr *Manager) UpdateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301451 ctx = utils.WithRPCMetadataContext(ctx, "UpdateImageDownload")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001452 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301453 logger.Debugw(ctx, "update-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
npujar467fe752020-01-16 20:17:45 +05301454 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1455 if err := agent.updateImageDownload(ctx, img); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301456 logger.Debugw(ctx, "update-image-download-failed", log.Fields{"err": err, "image-name": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001457 return err
1458 }
1459 } else {
1460 return status.Errorf(codes.NotFound, "%s", img.Id)
1461 }
1462 return nil
1463}
1464
Kent Hagerman45a13e42020-04-13 12:23:50 -04001465// GetImageDownload returns image download
Kent Hagerman2b216042020-04-03 18:28:56 -04001466func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301467 ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownload")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001468 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301469 logger.Debugw(ctx, "get-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001470 agent := dMgr.getDeviceAgent(ctx, img.Id)
1471 if agent == nil {
1472 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001473 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001474 resp, err := agent.getImageDownload(ctx, img)
1475 if err != nil {
1476 return imageDownloadFailureResp, err
1477 }
1478 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001479}
1480
Kent Hagerman45a13e42020-04-13 12:23:50 -04001481// ListImageDownloads returns image downloads
1482func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301483 ctx = utils.WithRPCMetadataContext(ctx, "ListImageDownloads")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001484 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301485 logger.Debugw(ctx, "list-image-downloads", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001486 agent := dMgr.getDeviceAgent(ctx, id.Id)
1487 if agent == nil {
1488 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001489 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001490 resp, err := agent.listImageDownloads(ctx, id.Id)
1491 if err != nil {
1492 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
1493 }
1494 return resp, nil
1495}
1496
1497// GetImages returns all images for a specific device entry
1498func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301499 ctx = utils.WithRPCMetadataContext(ctx, "GetImages")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001500 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301501 logger.Debugw(ctx, "get-images", log.Fields{"device-id": id.Id})
Kent Hagermancba2f302020-07-28 13:37:36 -04001502 device, err := dMgr.getDeviceReadOnly(ctx, id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -04001503 if err != nil {
1504 return nil, err
1505 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001506 return device.Images, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001507}
1508
Rohan Agrawal31f21802020-06-12 05:38:46 +00001509func (dMgr *Manager) NotifyInvalidTransition(ctx context.Context, device *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301510 logger.Errorw(ctx, "notify-invalid-transition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001511 "device": device.Id,
1512 "curr-admin-state": device.AdminState,
1513 "curr-oper-state": device.OperStatus,
1514 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001515 })
khenaidoo0a822f92019-05-08 15:15:57 -04001516 //TODO: notify over kafka?
1517 return nil
1518}
1519
npujar1d86a522019-11-14 17:11:16 +05301520// UpdateDeviceAttribute updates value of particular device attribute
Kent Hagerman2b216042020-04-03 18:28:56 -04001521func (dMgr *Manager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301522 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -04001523 agent.(*Agent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001524 }
1525}
1526
npujar1d86a522019-11-14 17:11:16 +05301527// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -04001528func (dMgr *Manager) GetParentDeviceID(ctx context.Context, deviceID string) string {
Kent Hagermancba2f302020-07-28 13:37:36 -04001529 if device, _ := dMgr.getDeviceReadOnly(ctx, deviceID); device != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301530 logger.Infow(ctx, "get-parent-device-id", log.Fields{"device-id": device.Id, "parent-id": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001531 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001532 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001533 return ""
khenaidoob9203542018-09-17 22:56:37 -04001534}
serkant.uluderya334479d2019-04-10 08:26:15 -07001535
Kent Hagerman45a13e42020-04-13 12:23:50 -04001536func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301537 ctx = utils.WithRPCMetadataContext(ctx, "SimulateAlarm")
1538 logger.Debugw(ctx, "simulate-alarm", log.Fields{"id": simulateReq.Id, "indicator": simulateReq.Indicator, "intf-id": simulateReq.IntfId,
1539 "port-type-name": simulateReq.PortTypeName, "onu-device-id": simulateReq.OnuDeviceId, "inverse-bit-error-rate": simulateReq.InverseBitErrorRate,
1540 "drift": simulateReq.Drift, "new-eqd": simulateReq.NewEqd, "onu-serial-number": simulateReq.OnuSerialNumber, "operation": simulateReq.Operation})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001541 agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
1542 if agent == nil {
1543 return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
serkant.uluderya334479d2019-04-10 08:26:15 -07001544 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001545 if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
1546 return nil, err
1547 }
1548 return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
serkant.uluderya334479d2019-04-10 08:26:15 -07001549}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001550
Kent Hagerman2b216042020-04-03 18:28:56 -04001551func (dMgr *Manager) UpdateDeviceReason(ctx context.Context, deviceID string, reason string) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301552 logger.Debugw(ctx, "update-device-reason", log.Fields{"device-id": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301553 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1554 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001555 }
npujar1d86a522019-11-14 17:11:16 +05301556 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001557}
kesavandbc2d1622020-01-21 00:42:01 -05001558
Kent Hagerman45a13e42020-04-13 12:23:50 -04001559func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301560 ctx = utils.WithRPCMetadataContext(ctx, "EnablePort")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001561 log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
Himani Chawlab4c25912020-11-12 17:16:38 +05301562 logger.Debugw(ctx, "enable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001563 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1564 if agent == nil {
1565 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001566 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001567 return &empty.Empty{}, agent.enablePort(ctx, port.PortNo)
kesavandbc2d1622020-01-21 00:42:01 -05001568}
1569
Kent Hagerman45a13e42020-04-13 12:23:50 -04001570func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301571 ctx = utils.WithRPCMetadataContext(ctx, "DisablePort")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001572 log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
Himani Chawlab4c25912020-11-12 17:16:38 +05301573 logger.Debugw(ctx, "disable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001574 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1575 if agent == nil {
1576 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001577 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001578 return &empty.Empty{}, agent.disablePort(ctx, port.PortNo)
kesavandbc2d1622020-01-21 00:42:01 -05001579}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001580
Kent Hagerman2b216042020-04-03 18:28:56 -04001581// ChildDeviceLost calls parent adapter to delete child device and all its references
1582func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301583 logger.Debugw(ctx, "child-device-lost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001584 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001585 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1586 // Just log the message and let the remaining pipeline proceed.
Rohan Agrawal31f21802020-06-12 05:38:46 +00001587 logger.Warnw(ctx, "childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001588 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001589 }
khenaidooe132f522020-03-20 15:23:15 -04001590 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1591 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001592}
onkarkundargi87285252020-01-27 11:34:52 +05301593
Kent Hagerman45a13e42020-04-13 12:23:50 -04001594func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301595 ctx = utils.WithRPCMetadataContext(ctx, "StartOmciTestAction")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001596 log.EnrichSpan(ctx, log.Fields{"device-id": request.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301597 logger.Debugw(ctx, "start-omci-test-action", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001598 agent := dMgr.getDeviceAgent(ctx, request.Id)
1599 if agent == nil {
1600 return nil, status.Errorf(codes.NotFound, "%s", request.Id)
onkarkundargi87285252020-01-27 11:34:52 +05301601 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001602 return agent.startOmciTest(ctx, request)
onkarkundargi87285252020-01-27 11:34:52 +05301603}
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001604
1605func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301606 ctx = utils.WithRPCMetadataContext(ctx, "GetExtValue")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001607 log.EnrichSpan(ctx, log.Fields{"device-id": value.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301608 logger.Debugw(ctx, "get-ext-value", log.Fields{"onu-id": value.Id})
Kent Hagermancba2f302020-07-28 13:37:36 -04001609 cDevice, err := dMgr.getDeviceReadOnly(ctx, value.Id)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001610 if err != nil {
1611 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1612 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001613 pDevice, err := dMgr.getDeviceReadOnly(ctx, cDevice.ParentId)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001614 if err != nil {
1615 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1616 }
1617 if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
1618 resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
1619 if err != nil {
1620 return nil, err
1621 }
Himani Chawlab4c25912020-11-12 17:16:38 +05301622 logger.Debugw(ctx, "get-ext-value-result", log.Fields{"result": resp})
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001623 return resp, nil
1624 }
1625 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1626
1627}
dpaul62686312020-06-23 14:17:36 +05301628
1629// SetExtValue set some given configs or value
1630func (dMgr *Manager) SetExtValue(ctx context.Context, value *voltha.ValueSet) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301631 ctx = utils.WithRPCMetadataContext(ctx, "SetExtValue")
1632 logger.Debugw(ctx, "set-ext-value", log.Fields{"onu-id": value.Id})
dpaul62686312020-06-23 14:17:36 +05301633 device, err := dMgr.getDeviceReadOnly(ctx, value.Id)
1634 if err != nil {
1635 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1636 }
1637 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1638 resp, err := agent.setExtValue(ctx, device, value)
1639 if err != nil {
1640 return nil, err
1641 }
Himani Chawlab4c25912020-11-12 17:16:38 +05301642 logger.Debugw(ctx, "set-ext-value-result", log.Fields{"result": resp})
dpaul62686312020-06-23 14:17:36 +05301643 return resp, nil
1644 }
1645 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1646
1647}
Himani Chawlab4c25912020-11-12 17:16:38 +05301648
1649func (dMgr *Manager) SendRPCEvent(ctx context.Context, id string, rpcEvent *voltha.RPCEvent,
1650 category voltha.EventCategory_Types, subCategory *voltha.EventSubCategory_Types, raisedTs int64) {
1651 //TODO Instead of directly sending to the kafka bus, queue the message and send it asynchronously
Mahir Gunyelb0343bf2021-05-11 14:14:26 -07001652 dMgr.Agent.SendRPCEvent(ctx, id, rpcEvent, category, subCategory, raisedTs)
Himani Chawlab4c25912020-11-12 17:16:38 +05301653}
Manindera496f852021-02-22 09:57:56 +05301654
1655func (dMgr *Manager) GetTransientState(ctx context.Context, id string) (voltha.DeviceTransientState_Types, error) {
1656 agent := dMgr.getDeviceAgent(ctx, id)
1657 if agent == nil {
1658 return voltha.DeviceTransientState_NONE, status.Errorf(codes.NotFound, "%s", id)
1659 }
1660 return agent.getTransientState(), nil
1661}
ssiddiquif076cb82021-04-23 10:47:04 +05301662
1663func (dMgr *Manager) DownloadImageToDevice(ctx context.Context, request *voltha.DeviceImageDownloadRequest) (*voltha.DeviceImageResponse, error) {
1664 if err := dMgr.validateImageDownloadRequest(request); err != nil {
1665 return nil, err
1666 }
1667
1668 ctx = utils.WithRPCMetadataContext(ctx, "DownloadImageToDevice")
1669 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
1670
ssiddiquif076cb82021-04-23 10:47:04 +05301671 for index, deviceID := range request.DeviceId {
ssiddiqui6bd4de02021-06-08 12:04:17 +05301672 // Create download request per device
1673 downloadReq := &voltha.DeviceImageDownloadRequest{
1674 Image: request.Image,
1675 ActivateOnSuccess: request.ActivateOnSuccess,
1676 CommitOnSuccess: request.CommitOnSuccess,
1677 }
1678
ssiddiquif076cb82021-04-23 10:47:04 +05301679 //slice-out only single deviceID from the request
1680 downloadReq.DeviceId = request.DeviceId[index : index+1]
1681
1682 go func(deviceID string, req *voltha.DeviceImageDownloadRequest, ch chan []*voltha.DeviceImageState) {
1683 agent := dMgr.getDeviceAgent(ctx, deviceID)
1684 if agent == nil {
ssiddiquib2f526c2021-10-11 17:11:25 +05301685 logger.Errorw(ctx, "Device-agent-not-found", log.Fields{"device-id": deviceID})
1686 ch <- []*voltha.DeviceImageState{{
1687 DeviceId: deviceID,
1688 ImageState: &voltha.ImageState{
1689 Version: req.GetImage().GetVersion(),
1690 DownloadState: voltha.ImageState_DOWNLOAD_FAILED,
1691 Reason: voltha.ImageState_UNKNOWN_ERROR,
1692 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
1693 },
1694 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301695 return
1696 }
1697
1698 resp, err := agent.downloadImageToDevice(ctx, req)
1699 if err != nil {
1700 logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiquib2f526c2021-10-11 17:11:25 +05301701 ch <- []*voltha.DeviceImageState{{
1702 DeviceId: deviceID,
1703 ImageState: &voltha.ImageState{
1704 Version: req.GetImage().GetVersion(),
1705 DownloadState: voltha.ImageState_DOWNLOAD_FAILED,
1706 Reason: voltha.ImageState_UNKNOWN_ERROR,
1707 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
1708 },
1709 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301710 return
1711 }
1712
1713 err = dMgr.validateDeviceImageResponse(resp)
1714 if err != nil {
1715 logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiquib2f526c2021-10-11 17:11:25 +05301716 ch <- []*voltha.DeviceImageState{{
1717 DeviceId: deviceID,
1718 ImageState: &voltha.ImageState{
1719 Version: req.GetImage().GetVersion(),
1720 DownloadState: voltha.ImageState_DOWNLOAD_FAILED,
1721 Reason: voltha.ImageState_UNKNOWN_ERROR,
1722 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
1723 },
1724 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301725 return
1726 }
1727 ch <- resp.GetDeviceImageStates()
1728 }(deviceID.GetId(), downloadReq, respCh)
1729
1730 }
1731
1732 return dMgr.waitForAllResponses(ctx, "download-image-to-device", respCh, len(request.GetDeviceId()))
1733}
1734
1735func (dMgr *Manager) GetImageStatus(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
1736 if err := dMgr.validateImageRequest(request); err != nil {
1737 return nil, err
1738 }
1739
1740 ctx = utils.WithRPCMetadataContext(ctx, "GetImageStatus")
1741
ssiddiquif076cb82021-04-23 10:47:04 +05301742 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
1743 for index, deviceID := range request.DeviceId {
ssiddiqui6bd4de02021-06-08 12:04:17 +05301744 // Create status request per device
1745 imageStatusReq := &voltha.DeviceImageRequest{
1746 Version: request.Version,
1747 CommitOnSuccess: request.CommitOnSuccess,
1748 }
1749
ssiddiquif076cb82021-04-23 10:47:04 +05301750 //slice-out only single deviceID from the request
1751 imageStatusReq.DeviceId = request.DeviceId[index : index+1]
1752
1753 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
1754 agent := dMgr.getDeviceAgent(ctx, deviceID)
1755 if agent == nil {
ssiddiquib2f526c2021-10-11 17:11:25 +05301756 logger.Errorw(ctx, "Device-agent-not-found", log.Fields{"device-id": deviceID})
1757 ch <- []*voltha.DeviceImageState{{
1758 DeviceId: deviceID,
1759 ImageState: &voltha.ImageState{
1760 Version: request.GetVersion(),
1761 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
1762 Reason: voltha.ImageState_UNKNOWN_ERROR,
1763 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
1764 },
1765 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301766 return
1767 }
1768
1769 resp, err := agent.getImageStatus(ctx, req)
1770 if err != nil {
1771 logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiquib2f526c2021-10-11 17:11:25 +05301772 ch <- []*voltha.DeviceImageState{{
1773 DeviceId: deviceID,
1774 ImageState: &voltha.ImageState{
1775 Version: request.GetVersion(),
1776 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
1777 Reason: voltha.ImageState_UNKNOWN_ERROR,
1778 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
1779 },
1780 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301781 return
1782 }
1783
1784 err = dMgr.validateDeviceImageResponse(resp)
1785 if err != nil {
1786 logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiquib2f526c2021-10-11 17:11:25 +05301787 ch <- []*voltha.DeviceImageState{{
1788 DeviceId: deviceID,
1789 ImageState: &voltha.ImageState{
1790 Version: request.GetVersion(),
1791 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
1792 Reason: voltha.ImageState_UNKNOWN_ERROR,
1793 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
1794 },
1795 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301796 return
1797 }
1798 ch <- resp.GetDeviceImageStates()
1799 }(deviceID.GetId(), imageStatusReq, respCh)
1800
1801 }
1802
1803 return dMgr.waitForAllResponses(ctx, "get-image-status", respCh, len(request.GetDeviceId()))
1804}
1805
1806func (dMgr *Manager) AbortImageUpgradeToDevice(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
1807 if err := dMgr.validateImageRequest(request); err != nil {
1808 return nil, err
1809 }
1810
1811 ctx = utils.WithRPCMetadataContext(ctx, "AbortImageUpgradeToDevice")
1812 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
1813
ssiddiquif076cb82021-04-23 10:47:04 +05301814 for index, deviceID := range request.DeviceId {
ssiddiqui6bd4de02021-06-08 12:04:17 +05301815 // Create abort request per device
1816 abortImageReq := &voltha.DeviceImageRequest{
1817 Version: request.Version,
1818 CommitOnSuccess: request.CommitOnSuccess,
1819 }
1820
ssiddiquif076cb82021-04-23 10:47:04 +05301821 //slice-out only single deviceID from the request
1822 abortImageReq.DeviceId = request.DeviceId[index : index+1]
1823
1824 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
1825 agent := dMgr.getDeviceAgent(ctx, deviceID)
1826 if agent == nil {
ssiddiquib2f526c2021-10-11 17:11:25 +05301827 logger.Errorw(ctx, "Device-agent-not-found", log.Fields{"device-id": deviceID})
1828 ch <- []*voltha.DeviceImageState{{
1829 DeviceId: deviceID,
1830 ImageState: &voltha.ImageState{
1831 Version: request.GetVersion(),
1832 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
1833 Reason: voltha.ImageState_UNKNOWN_ERROR,
1834 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
1835 },
1836 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301837 return
1838 }
1839
1840 resp, err := agent.abortImageUpgradeToDevice(ctx, req)
1841 if err != nil {
1842 logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiquib2f526c2021-10-11 17:11:25 +05301843 ch <- []*voltha.DeviceImageState{{
1844 DeviceId: deviceID,
1845 ImageState: &voltha.ImageState{
1846 Version: request.GetVersion(),
1847 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
1848 Reason: voltha.ImageState_UNKNOWN_ERROR,
1849 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
1850 },
1851 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301852 return
1853 }
1854
1855 err = dMgr.validateDeviceImageResponse(resp)
1856 if err != nil {
1857 logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiquib2f526c2021-10-11 17:11:25 +05301858 ch <- []*voltha.DeviceImageState{{
1859 DeviceId: deviceID,
1860 ImageState: &voltha.ImageState{
1861 Version: request.GetVersion(),
1862 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
1863 Reason: voltha.ImageState_UNKNOWN_ERROR,
1864 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
1865 },
1866 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301867 return
1868 }
1869 ch <- resp.GetDeviceImageStates()
1870 }(deviceID.GetId(), abortImageReq, respCh)
1871
1872 }
1873
1874 return dMgr.waitForAllResponses(ctx, "abort-image-upgrade-to-device", respCh, len(request.GetDeviceId()))
1875}
1876
1877func (dMgr *Manager) GetOnuImages(ctx context.Context, id *common.ID) (*voltha.OnuImages, error) {
1878 if id == nil || id.Id == "" {
1879 return nil, status.Errorf(codes.InvalidArgument, "empty device id")
1880 }
1881
1882 ctx = utils.WithRPCMetadataContext(ctx, "GetOnuImages")
1883 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
1884 agent := dMgr.getDeviceAgent(ctx, id.Id)
1885 if agent == nil {
1886 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
1887 }
1888
1889 resp, err := agent.getOnuImages(ctx, id)
1890 if err != nil {
1891 return nil, err
1892 }
1893
1894 logger.Debugw(ctx, "get-onu-images-result", log.Fields{"onu-image": resp.Items})
1895
1896 return resp, nil
1897}
1898
1899func (dMgr *Manager) ActivateImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
1900 if err := dMgr.validateImageRequest(request); err != nil {
1901 return nil, err
1902 }
1903
1904 ctx = utils.WithRPCMetadataContext(ctx, "ActivateImage")
1905 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
1906
ssiddiquif076cb82021-04-23 10:47:04 +05301907 for index, deviceID := range request.DeviceId {
ssiddiqui6bd4de02021-06-08 12:04:17 +05301908 // Create activate request per device
1909 activateImageReq := &voltha.DeviceImageRequest{
1910 Version: request.Version,
1911 CommitOnSuccess: request.CommitOnSuccess,
1912 }
1913
ssiddiquif076cb82021-04-23 10:47:04 +05301914 //slice-out only single deviceID from the request
1915 activateImageReq.DeviceId = request.DeviceId[index : index+1]
1916
1917 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
1918 agent := dMgr.getDeviceAgent(ctx, deviceID)
1919 if agent == nil {
ssiddiquib2f526c2021-10-11 17:11:25 +05301920 logger.Errorw(ctx, "Device-agent-not-found", log.Fields{"device-id": deviceID})
1921 ch <- []*voltha.DeviceImageState{{
1922 DeviceId: deviceID,
1923 ImageState: &voltha.ImageState{
1924 Version: request.GetVersion(),
1925 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
1926 Reason: voltha.ImageState_UNKNOWN_ERROR,
1927 ImageState: voltha.ImageState_IMAGE_ACTIVATION_ABORTED,
1928 },
1929 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301930 return
1931 }
1932
1933 resp, err := agent.activateImageOnDevice(ctx, req)
1934 if err != nil {
1935 logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiquib2f526c2021-10-11 17:11:25 +05301936 ch <- []*voltha.DeviceImageState{{
1937 DeviceId: deviceID,
1938 ImageState: &voltha.ImageState{
1939 Version: request.GetVersion(),
1940 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
1941 Reason: voltha.ImageState_UNKNOWN_ERROR,
1942 ImageState: voltha.ImageState_IMAGE_ACTIVATION_ABORTED,
1943 },
1944 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301945 return
1946 }
1947
1948 err = dMgr.validateDeviceImageResponse(resp)
1949 if err != nil {
1950 logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiquib2f526c2021-10-11 17:11:25 +05301951 ch <- []*voltha.DeviceImageState{{
1952 DeviceId: deviceID,
1953 ImageState: &voltha.ImageState{
1954 Version: request.GetVersion(),
1955 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
1956 Reason: voltha.ImageState_UNKNOWN_ERROR,
1957 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
1958 },
1959 }}
ssiddiquif076cb82021-04-23 10:47:04 +05301960 return
1961 }
1962
1963 ch <- resp.GetDeviceImageStates()
1964 }(deviceID.GetId(), activateImageReq, respCh)
1965
1966 }
1967
1968 return dMgr.waitForAllResponses(ctx, "activate-image", respCh, len(request.GetDeviceId()))
1969}
1970
1971func (dMgr *Manager) CommitImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
1972 if err := dMgr.validateImageRequest(request); err != nil {
1973 return nil, err
1974 }
1975
1976 ctx = utils.WithRPCMetadataContext(ctx, "CommitImage")
1977 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
1978
ssiddiquif076cb82021-04-23 10:47:04 +05301979 for index, deviceID := range request.DeviceId {
ssiddiqui6bd4de02021-06-08 12:04:17 +05301980 // Create commit request per device
1981 commitImageReq := &voltha.DeviceImageRequest{
1982 Version: request.Version,
1983 CommitOnSuccess: request.CommitOnSuccess,
1984 }
ssiddiquif076cb82021-04-23 10:47:04 +05301985 //slice-out only single deviceID from the request
1986 commitImageReq.DeviceId = request.DeviceId[index : index+1]
1987
1988 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
1989 agent := dMgr.getDeviceAgent(ctx, deviceID)
1990 if agent == nil {
ssiddiquib2f526c2021-10-11 17:11:25 +05301991 logger.Errorw(ctx, "Device-agent-not-found", log.Fields{"device-id": deviceID})
1992 ch <- []*voltha.DeviceImageState{{
1993 DeviceId: deviceID,
1994 ImageState: &voltha.ImageState{
1995 Version: request.GetVersion(),
1996 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
1997 Reason: voltha.ImageState_UNKNOWN_ERROR,
1998 ImageState: voltha.ImageState_IMAGE_COMMIT_ABORTED,
1999 },
2000 }}
ssiddiquif076cb82021-04-23 10:47:04 +05302001 return
2002 }
2003
2004 resp, err := agent.commitImage(ctx, req)
2005 if err != nil {
2006 logger.Errorw(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiquib2f526c2021-10-11 17:11:25 +05302007 ch <- []*voltha.DeviceImageState{{
2008 DeviceId: deviceID,
2009 ImageState: &voltha.ImageState{
2010 Version: request.GetVersion(),
2011 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
2012 Reason: voltha.ImageState_UNKNOWN_ERROR,
2013 ImageState: voltha.ImageState_IMAGE_COMMIT_ABORTED,
2014 },
2015 }}
ssiddiquif076cb82021-04-23 10:47:04 +05302016 return
2017 }
2018
2019 err = dMgr.validateDeviceImageResponse(resp)
2020 if err != nil {
2021 logger.Errorf(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiquib2f526c2021-10-11 17:11:25 +05302022 ch <- []*voltha.DeviceImageState{{
2023 DeviceId: deviceID,
2024 ImageState: &voltha.ImageState{
2025 Version: request.GetVersion(),
2026 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
2027 Reason: voltha.ImageState_UNKNOWN_ERROR,
2028 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
2029 },
2030 }}
ssiddiquif076cb82021-04-23 10:47:04 +05302031 return
2032 }
2033 ch <- resp.GetDeviceImageStates()
2034 }(deviceID.GetId(), commitImageReq, respCh)
2035
2036 }
2037
2038 return dMgr.waitForAllResponses(ctx, "commit-image", respCh, len(request.GetDeviceId()))
2039}
2040
2041func (dMgr *Manager) validateImageDownloadRequest(request *voltha.DeviceImageDownloadRequest) error {
2042 if request == nil || request.Image == nil || len(request.DeviceId) == 0 {
2043 return status.Errorf(codes.InvalidArgument, "invalid argument")
2044 }
2045
2046 for _, deviceID := range request.DeviceId {
2047 if deviceID == nil {
2048 return status.Errorf(codes.InvalidArgument, "id is nil")
2049 }
2050 }
2051 return nil
2052}
2053
2054func (dMgr *Manager) validateImageRequest(request *voltha.DeviceImageRequest) error {
2055 if request == nil || len(request.DeviceId) == 0 || request.DeviceId[0] == nil {
2056 return status.Errorf(codes.InvalidArgument, "invalid argument")
2057 }
2058
2059 for _, deviceID := range request.DeviceId {
2060 if deviceID == nil {
2061 return status.Errorf(codes.InvalidArgument, "id is nil")
2062 }
2063 }
2064
2065 return nil
2066}
2067
2068func (dMgr *Manager) validateDeviceImageResponse(response *voltha.DeviceImageResponse) error {
2069 if response == nil || len(response.GetDeviceImageStates()) == 0 || response.GetDeviceImageStates()[0] == nil {
2070 return status.Errorf(codes.Internal, "invalid-response-from-adapter")
2071 }
2072
2073 return nil
2074}
2075
2076func (dMgr *Manager) waitForAllResponses(ctx context.Context, opName string, respCh chan []*voltha.DeviceImageState, expectedResps int) (*voltha.DeviceImageResponse, error) {
2077 response := &voltha.DeviceImageResponse{}
2078 respCount := 0
2079 for {
2080 select {
2081 case resp, ok := <-respCh:
2082 if !ok {
2083 logger.Errorw(ctx, opName+"-failed", log.Fields{"error": "channel-closed"})
2084 return response, status.Errorf(codes.Aborted, "channel-closed")
2085 }
2086
2087 if resp != nil {
2088 logger.Debugw(ctx, opName+"-result", log.Fields{"image-state": resp[0].GetImageState(), "device-id": resp[0].GetDeviceId()})
2089 response.DeviceImageStates = append(response.DeviceImageStates, resp...)
2090 }
2091
2092 respCount++
2093
2094 //check whether all responses received, if so, sent back the collated response
2095 if respCount == expectedResps {
2096 return response, nil
2097 }
2098 continue
2099 case <-ctx.Done():
2100 return nil, status.Errorf(codes.Aborted, opName+"-failed-%s", ctx.Err())
2101 }
2102 }
2103}
Maninder0aabf0c2021-03-17 14:55:14 +05302104
2105func (dMgr *Manager) ReconcilingCleanup(ctx context.Context, device *voltha.Device) error {
2106 agent := dMgr.getDeviceAgent(ctx, device.Id)
2107 if agent == nil {
2108 logger.Errorf(ctx, "Not able to get device agent.")
2109 return status.Errorf(codes.NotFound, "Not able to get device agent for device : %s", device.Id)
2110 }
2111 err := agent.reconcilingCleanup(ctx)
2112 if err != nil {
2113 logger.Errorf(ctx, err.Error())
2114 return status.Errorf(codes.Internal, err.Error())
2115 }
2116 return nil
2117}
serkant.uluderyae25f6482020-12-17 21:08:38 +03002118
2119func (dMgr *Manager) DeleteAllLogicalMeters(ctx context.Context, cDevice *voltha.Device) error {
2120 logger.Debugw(ctx, "delete-all-logical-device-meters", log.Fields{"device-id": cDevice.Id})
2121 if err := dMgr.logicalDeviceMgr.deleteAllLogicalMeters(ctx, cDevice.Id); err != nil {
2122 // Just log the error. The logical device or port may already have been deleted before this callback is invoked.
Andrea Campanella408dec62021-11-10 14:32:10 +01002123 logger.Warnw(ctx, "delete-logical-meters-error", log.Fields{"device-id": cDevice.Id, "error": err})
serkant.uluderyae25f6482020-12-17 21:08:38 +03002124 }
2125 return nil
2126
2127}