blob: 9982611d35f986ef735c16958161e58ec24f5d69 [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"
Maninder0aabf0c2021-03-17 14:55:14 +053022 "github.com/opencord/voltha-go/rw_core/config"
David Bainbridged1afd662020-03-26 18:27:41 -070023 "sync"
24 "time"
25
Kent Hagerman45a13e42020-04-13 12:23:50 -040026 "github.com/golang/protobuf/ptypes/empty"
sbarbari17d7e222019-11-05 10:02:29 -050027 "github.com/opencord/voltha-go/db/model"
Kent Hagerman2b216042020-04-03 18:28:56 -040028 "github.com/opencord/voltha-go/rw_core/core/adapter"
Kent Hagermanf5a67352020-04-30 15:15:26 -040029 "github.com/opencord/voltha-go/rw_core/core/device/event"
Kent Hagerman2b216042020-04-03 18:28:56 -040030 "github.com/opencord/voltha-go/rw_core/core/device/remote"
Kent Hagerman6031aad2020-07-29 16:36:33 -040031 "github.com/opencord/voltha-go/rw_core/core/device/state"
khenaidoo3d3b8c22019-05-22 18:10:39 -040032 "github.com/opencord/voltha-go/rw_core/utils"
Himani Chawlab4c25912020-11-12 17:16:38 +053033 "github.com/opencord/voltha-lib-go/v4/pkg/events"
Maninderdfadc982020-10-28 14:04:33 +053034 "github.com/opencord/voltha-lib-go/v4/pkg/kafka"
35 "github.com/opencord/voltha-lib-go/v4/pkg/log"
36 "github.com/opencord/voltha-protos/v4/go/common"
37 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
38 "github.com/opencord/voltha-protos/v4/go/openflow_13"
39 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
40 "github.com/opencord/voltha-protos/v4/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040041 "google.golang.org/grpc/codes"
42 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040043)
44
Kent Hagerman2b216042020-04-03 18:28:56 -040045// Manager represent device manager attributes
46type Manager struct {
Himani Chawlab4c25912020-11-12 17:16:38 +053047 deviceAgents sync.Map
48 rootDevices map[string]bool
49 lockRootDeviceMap sync.RWMutex
50 adapterProxy *remote.AdapterProxy
Mahir Gunyelb0343bf2021-05-11 14:14:26 -070051 *event.Agent
Kent Hagerman2b216042020-04-03 18:28:56 -040052 adapterMgr *adapter.Manager
53 logicalDeviceMgr *LogicalManager
npujar467fe752020-01-16 20:17:45 +053054 kafkaICProxy kafka.InterContainerProxy
Kent Hagerman6031aad2020-07-29 16:36:33 -040055 stateTransitions *state.TransitionMap
Mahir Gunyel03de0d32020-06-03 01:36:59 -070056 dbPath *model.Path
Kent Hagermanf5a67352020-04-30 15:15:26 -040057 dProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053058 coreInstanceID string
khenaidoo442e7c72020-03-10 16:13:48 -040059 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040060 devicesLoadingLock sync.RWMutex
61 deviceLoadingInProgress map[string][]chan int
Maninder0aabf0c2021-03-17 14:55:14 +053062 config *config.RWCoreFlags
khenaidoob9203542018-09-17 22:56:37 -040063}
64
Mahir Gunyel03de0d32020-06-03 01:36:59 -070065//NewManagers creates the Manager and the Logical Manager.
Maninder0aabf0c2021-03-17 14:55:14 +053066func 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 -040067 deviceMgr := &Manager{
Kent Hagerman2b216042020-04-03 18:28:56 -040068 rootDevices: make(map[string]bool),
69 kafkaICProxy: kmp,
Maninder0aabf0c2021-03-17 14:55:14 +053070 adapterProxy: remote.NewAdapterProxy(kmp, cf.CoreTopic, endpointMgr),
Kent Hagerman2b216042020-04-03 18:28:56 -040071 coreInstanceID: coreInstanceID,
Mahir Gunyel03de0d32020-06-03 01:36:59 -070072 dbPath: dbPath,
73 dProxy: dbPath.Proxy("devices"),
Kent Hagerman2b216042020-04-03 18:28:56 -040074 adapterMgr: adapterMgr,
Maninder0aabf0c2021-03-17 14:55:14 +053075 defaultTimeout: cf.DefaultCoreTimeout,
76 Agent: event.NewAgent(eventProxy, coreInstanceID, cf.VolthaStackID),
Kent Hagerman2b216042020-04-03 18:28:56 -040077 deviceLoadingInProgress: make(map[string][]chan int),
Maninder0aabf0c2021-03-17 14:55:14 +053078 config: cf,
Kent Hagerman2b216042020-04-03 18:28:56 -040079 }
Kent Hagerman6031aad2020-07-29 16:36:33 -040080 deviceMgr.stateTransitions = state.NewTransitionMap(deviceMgr)
Kent Hagerman2f0d0552020-04-23 17:28:52 -040081
Kent Hagerman2b216042020-04-03 18:28:56 -040082 logicalDeviceMgr := &LogicalManager{
Maninder0aabf0c2021-03-17 14:55:14 +053083 Manager: event.NewManager(eventProxy, coreInstanceID, cf.VolthaStackID),
Kent Hagerman2b216042020-04-03 18:28:56 -040084 deviceMgr: deviceMgr,
85 kafkaICProxy: kmp,
Mahir Gunyel03de0d32020-06-03 01:36:59 -070086 dbPath: dbPath,
87 ldProxy: dbPath.Proxy("logical_devices"),
Maninder0aabf0c2021-03-17 14:55:14 +053088 defaultTimeout: cf.DefaultCoreTimeout,
Kent Hagerman2b216042020-04-03 18:28:56 -040089 logicalDeviceLoadingInProgress: make(map[string][]chan int),
90 }
91 deviceMgr.logicalDeviceMgr = logicalDeviceMgr
Matteo Scandolod525ae32020-04-02 17:27:29 -070092
Kent Hagerman2b216042020-04-03 18:28:56 -040093 adapterMgr.SetAdapterRestartedCallback(deviceMgr.adapterRestarted)
Matteo Scandolod525ae32020-04-02 17:27:29 -070094
Kent Hagerman2b216042020-04-03 18:28:56 -040095 return deviceMgr, logicalDeviceMgr
khenaidoob9203542018-09-17 22:56:37 -040096}
97
Kent Hagerman2b216042020-04-03 18:28:56 -040098func (dMgr *Manager) addDeviceAgentToMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +053099 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
100 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -0400101 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400102 dMgr.lockRootDeviceMap.Lock()
103 defer dMgr.lockRootDeviceMap.Unlock()
Kent Hagerman2a07b862020-06-19 15:23:07 -0400104 dMgr.rootDevices[agent.deviceID] = agent.isRootDevice
khenaidoo2c6a0992019-04-29 13:46:56 -0400105
khenaidoob9203542018-09-17 22:56:37 -0400106}
107
Kent Hagerman2b216042020-04-03 18:28:56 -0400108func (dMgr *Manager) deleteDeviceAgentFromMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +0530109 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400110 dMgr.lockRootDeviceMap.Lock()
111 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530112 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400113}
114
khenaidoo297cd252019-02-07 22:10:23 -0500115// 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 -0400116func (dMgr *Manager) getDeviceAgent(ctx context.Context, deviceID string) *Agent {
npujar1d86a522019-11-14 17:11:16 +0530117 agent, ok := dMgr.deviceAgents.Load(deviceID)
118 if ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400119 return agent.(*Agent)
khenaidoob9203542018-09-17 22:56:37 -0400120 }
khenaidoo442e7c72020-03-10 16:13:48 -0400121 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530122 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530123 if err == nil {
124 agent, ok = dMgr.deviceAgents.Load(deviceID)
125 if !ok {
126 return nil
127 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400128 return agent.(*Agent)
npujar1d86a522019-11-14 17:11:16 +0530129 }
130 //TODO: Change the return params to return an error as well
divyadesaicb8b59d2020-08-18 09:55:47 +0000131 logger.Errorw(ctx, "loading-device-failed", log.Fields{"device-id": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400132 return nil
133}
134
khenaidoo297cd252019-02-07 22:10:23 -0500135// listDeviceIdsFromMap returns the list of device IDs that are in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400136func (dMgr *Manager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500137 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400138
139 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
140 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
141 return true
142 })
143
khenaidoo7ccedd52018-12-14 16:48:54 -0500144 return result
145}
146
Kent Hagerman45a13e42020-04-13 12:23:50 -0400147// CreateDevice creates a new parent device in the data model
148func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
149 if device.MacAddress == "" && device.GetHostAndPort() == "" {
Himani Chawlab4c25912020-11-12 17:16:38 +0530150 logger.Errorf(ctx, "no-device-info-present")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400151 return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
152 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530153 ctx = utils.WithRPCMetadataContext(ctx, "CreateDevice")
Rohan Agrawal31f21802020-06-12 05:38:46 +0000154 logger.Debugw(ctx, "create-device", log.Fields{"device": *device})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400155
npujar467fe752020-01-16 20:17:45 +0530156 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530157 if err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530158 logger.Errorf(ctx, "failed-to-fetch-parent-device-info")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400159 return nil, err
Thomas Lee Se5a44012019-11-07 20:32:24 +0530160 }
161 if deviceExist {
Himani Chawlab4c25912020-11-12 17:16:38 +0530162 logger.Errorf(ctx, "device-is-pre-provisioned-already-with-same-ip-port-or-mac-address")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400163 return nil, errors.New("device is already pre-provisioned")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530164 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530165 logger.Debugw(ctx, "create-device", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400166
khenaidoo5e677ae2019-02-28 17:26:29 -0500167 // Ensure this device is set as root
168 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400169 // Create and start a device agent for that device
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700170 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530171 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800172 if err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530173 logger.Errorw(ctx, "fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400174 return nil, err
Scott Baker80678602019-11-14 16:57:36 -0800175 }
khenaidoo442e7c72020-03-10 16:13:48 -0400176 dMgr.addDeviceAgentToMap(agent)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400177 return device, nil
khenaidoob9203542018-09-17 22:56:37 -0400178}
179
Kent Hagerman45a13e42020-04-13 12:23:50 -0400180// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
181func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530182 ctx = utils.WithRPCMetadataContext(ctx, "EnableDevice")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000183 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530184 logger.Debugw(ctx, "enable-device", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400185 agent := dMgr.getDeviceAgent(ctx, id.Id)
186 if agent == nil {
187 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400188 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400189 return &empty.Empty{}, agent.enableDevice(ctx)
khenaidoob9203542018-09-17 22:56:37 -0400190}
191
Kent Hagerman45a13e42020-04-13 12:23:50 -0400192// DisableDevice disables a device along with any child device it may have
193func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530194 ctx = utils.WithRPCMetadataContext(ctx, "DisableDevice")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000195 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530196 logger.Debugw(ctx, "disable-device", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400197 agent := dMgr.getDeviceAgent(ctx, id.Id)
198 if agent == nil {
199 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400200 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400201 return &empty.Empty{}, agent.disableDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400202}
203
Kent Hagerman45a13e42020-04-13 12:23:50 -0400204//RebootDevice invoked the reboot API to the corresponding adapter
205func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530206 ctx = utils.WithRPCMetadataContext(ctx, "RebootDevice")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000207 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530208 logger.Debugw(ctx, "reboot-device", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400209 agent := dMgr.getDeviceAgent(ctx, id.Id)
210 if agent == nil {
211 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400212 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400213 return &empty.Empty{}, agent.rebootDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400214}
215
Kent Hagerman45a13e42020-04-13 12:23:50 -0400216// DeleteDevice removes a device from the data model
217func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530218 ctx = utils.WithRPCMetadataContext(ctx, "DeleteDevice")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000219 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530220 logger.Debugw(ctx, "delete-device", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400221 agent := dMgr.getDeviceAgent(ctx, id.Id)
222 if agent == nil {
223 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400224 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400225 return &empty.Empty{}, agent.deleteDevice(ctx)
226}
227
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530228// ForceDeleteDevice removes a device from the data model forcefully without successfully waiting for the adapters.
229func (dMgr *Manager) ForceDeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530230 ctx = utils.WithRPCMetadataContext(ctx, "ForceDeleteDevice")
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530231 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530232 logger.Debugw(ctx, "force-delete-device", log.Fields{"device-id": id.Id})
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530233 agent := dMgr.getDeviceAgent(ctx, id.Id)
234 if agent == nil {
235 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
236 }
237 return &empty.Empty{}, agent.deleteDeviceForce(ctx)
238}
239
Kent Hagerman2a07b862020-06-19 15:23:07 -0400240// GetDevicePort returns the port details for a specific device port entry
241func (dMgr *Manager) GetDevicePort(ctx context.Context, deviceID string, portID uint32) (*voltha.Port, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530242 logger.Debugw(ctx, "get-device-port", log.Fields{"device-id": deviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400243 agent := dMgr.getDeviceAgent(ctx, deviceID)
244 if agent == nil {
245 return nil, status.Errorf(codes.NotFound, "device-%s", deviceID)
246 }
247 return agent.getDevicePort(portID)
248}
249
Kent Hagerman45a13e42020-04-13 12:23:50 -0400250// ListDevicePorts returns the ports details for a specific device entry
251func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530252 ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePorts")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000253 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530254 logger.Debugw(ctx, "list-device-ports", log.Fields{"device-id": id.Id})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400255 agent := dMgr.getDeviceAgent(ctx, id.Id)
256 if agent == nil {
257 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400258 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400259
260 ports := agent.listDevicePorts()
261 ctr, ret := 0, make([]*voltha.Port, len(ports))
262 for _, port := range ports {
263 ret[ctr] = port
264 ctr++
265 }
266 return &voltha.Ports{Items: ret}, nil
Kent Hagerman45a13e42020-04-13 12:23:50 -0400267}
268
269// ListDeviceFlows returns the flow details for a specific device entry
270func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530271 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlows")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000272 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530273 logger.Debugw(ctx, "list-device-flows", log.Fields{"device-id": id.Id})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700274 agent := dMgr.getDeviceAgent(ctx, id.Id)
275 if agent == nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400276 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400277 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700278
279 flows := agent.listDeviceFlows()
280 ctr, ret := 0, make([]*ofp.OfpFlowStats, len(flows))
281 for _, flow := range flows {
282 ret[ctr] = flow
283 ctr++
284 }
285 return &openflow_13.Flows{Items: ret}, nil
Kent Hagerman45a13e42020-04-13 12:23:50 -0400286}
287
288// ListDeviceFlowGroups returns the flow group details for a specific device entry
289func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*voltha.FlowGroups, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530290 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlowGroups")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000291 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +0530292 logger.Debugw(ctx, "list-device-flow-groups", log.Fields{"device-id": id.Id})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700293 agent := dMgr.getDeviceAgent(ctx, id.Id)
294 if agent == nil {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400295 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
296 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700297 groups := agent.listDeviceGroups()
298 ctr, ret := 0, make([]*openflow_13.OfpGroupEntry, len(groups))
299 for _, group := range groups {
300 ret[ctr] = group
301 ctr++
302 }
303 return &voltha.FlowGroups{Items: ret}, nil
khenaidoo4d4802d2018-10-04 21:59:49 -0400304}
305
khenaidoo6d62c002019-05-15 21:57:03 -0400306// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
307// This function is called only in the Core that does not own this device. In the Core that owns this device then a
308// deletion deletion also includes removal of any reference of this device.
Kent Hagerman2b216042020-04-03 18:28:56 -0400309func (dMgr *Manager) stopManagingDevice(ctx context.Context, id string) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530310 logger.Infow(ctx, "stop-managing-device", log.Fields{"device-id": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400311 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
Kent Hagerman6031aad2020-07-29 16:36:33 -0400312 if device, err := dMgr.getDeviceReadOnly(ctx, id); err == nil && device.Root {
khenaidoo6d62c002019-05-15 21:57:03 -0400313 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700314 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400315 }
npujar467fe752020-01-16 20:17:45 +0530316 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400317 if err := agent.stop(ctx); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000318 logger.Warnw(ctx, "unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400319 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400320 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400321 }
322 }
323}
324
npujar1d86a522019-11-14 17:11:16 +0530325// RunPostDeviceDelete removes any reference of this device
Kent Hagerman2b216042020-04-03 18:28:56 -0400326func (dMgr *Manager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530327 logger.Infow(ctx, "run-post-device-delete", log.Fields{"device-id": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530328 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400329 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400330}
331
Kent Hagermancba2f302020-07-28 13:37:36 -0400332// GetDevice exists primarily to implement the gRPC interface.
333// Internal functions should call getDeviceReadOnly instead.
Kent Hagerman45a13e42020-04-13 12:23:50 -0400334func (dMgr *Manager) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530335 ctx = utils.WithRPCMetadataContext(ctx, "GetDevice")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000336 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Kent Hagermancba2f302020-07-28 13:37:36 -0400337 return dMgr.getDeviceReadOnly(ctx, id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400338}
339
Kent Hagermancba2f302020-07-28 13:37:36 -0400340// getDeviceReadOnly will returns a device, either from memory or from the dB, if present
341func (dMgr *Manager) getDeviceReadOnly(ctx context.Context, id string) (*voltha.Device, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530342 logger.Debugw(ctx, "get-device-read-only", log.Fields{"device-id": id})
npujar467fe752020-01-16 20:17:45 +0530343 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
Kent Hagermancba2f302020-07-28 13:37:36 -0400344 return agent.getDeviceReadOnly(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400345 }
346 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400347}
348
Kent Hagerman2a07b862020-06-19 15:23:07 -0400349func (dMgr *Manager) listDevicePorts(ctx context.Context, id string) (map[uint32]*voltha.Port, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530350 logger.Debugw(ctx, "list-device-ports", log.Fields{"device-id": id})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400351 agent := dMgr.getDeviceAgent(ctx, id)
352 if agent == nil {
353 return nil, status.Errorf(codes.NotFound, "%s", id)
354 }
355 return agent.listDevicePorts(), nil
356}
357
npujar1d86a522019-11-14 17:11:16 +0530358// GetChildDevice will return a device, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -0400359func (dMgr *Manager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530360 logger.Debugw(ctx, "get-child-device", log.Fields{"parent-device-id": parentDeviceID, "serialNumber": serialNumber,
361 "parent-port-no": parentPortNo, "onu-id": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500362
Kent Hagerman2a07b862020-06-19 15:23:07 -0400363 parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
364 if err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500365 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
366 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400367 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500368 if len(childDeviceIds) == 0 {
Himani Chawlab4c25912020-11-12 17:16:38 +0530369 logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": parentDeviceID, "serial-number": serialNumber, "onu-id": onuID})
npujar1d86a522019-11-14 17:11:16 +0530370 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500371 }
372
373 var foundChildDevice *voltha.Device
Kent Hagerman2a07b862020-06-19 15:23:07 -0400374 for childDeviceID := range childDeviceIds {
npujar1d86a522019-11-14 17:11:16 +0530375 var found bool
Kent Hagermancba2f302020-07-28 13:37:36 -0400376 if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500377
npujar1d86a522019-11-14 17:11:16 +0530378 foundOnuID := false
379 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500380 if searchDevice.ParentPortNo == uint32(parentPortNo) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530381 logger.Debugw(ctx, "found-child-by-onuid", log.Fields{"parent-device-id": parentDeviceID, "onu-id": onuID})
npujar1d86a522019-11-14 17:11:16 +0530382 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500383 }
384 }
385
386 foundSerialNumber := false
387 if searchDevice.SerialNumber == serialNumber {
Himani Chawlab4c25912020-11-12 17:16:38 +0530388 logger.Debugw(ctx, "found-child-by-serial-number", log.Fields{"parent-device-id": parentDeviceID, "serial-number": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500389 foundSerialNumber = true
390 }
391
392 // if both onuId and serialNumber are provided both must be true for the device to be found
393 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530394 if onuID > 0 && serialNumber != "" {
395 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500396 } else {
npujar1d86a522019-11-14 17:11:16 +0530397 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500398 }
399
npujar1d86a522019-11-14 17:11:16 +0530400 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500401 foundChildDevice = searchDevice
402 break
403 }
404 }
405 }
406
407 if foundChildDevice != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530408 logger.Debugw(ctx, "child-device-found", log.Fields{"parent-device-id": parentDeviceID, "found-child-device": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500409 return foundChildDevice, nil
410 }
411
divyadesaicb8b59d2020-08-18 09:55:47 +0000412 logger.Debugw(ctx, "child-device-not-found", log.Fields{"parent-device-id": parentDeviceID,
Himani Chawlab4c25912020-11-12 17:16:38 +0530413 "serial-number": serialNumber, "onu-id": onuID, "parent-port-no": parentPortNo})
npujar1d86a522019-11-14 17:11:16 +0530414 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500415}
416
npujar1d86a522019-11-14 17:11:16 +0530417// GetChildDeviceWithProxyAddress will return a device based on proxy address
Kent Hagerman2b216042020-04-03 18:28:56 -0400418func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530419 logger.Debugw(ctx, "get-child-device-with-proxy-address", log.Fields{"proxy-address": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500420
Kent Hagerman2a07b862020-06-19 15:23:07 -0400421 parentDevicePorts, err := dMgr.listDevicePorts(ctx, proxyAddress.DeviceId)
422 if err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500423 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
424 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400425 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500426 if len(childDeviceIds) == 0 {
divyadesaicb8b59d2020-08-18 09:55:47 +0000427 logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": proxyAddress.DeviceId})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500428 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
429 }
430
431 var foundChildDevice *voltha.Device
Kent Hagerman2a07b862020-06-19 15:23:07 -0400432 for childDeviceID := range childDeviceIds {
Kent Hagermancba2f302020-07-28 13:37:36 -0400433 if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500434 if searchDevice.ProxyAddress == proxyAddress {
435 foundChildDevice = searchDevice
436 break
437 }
438 }
439 }
440
441 if foundChildDevice != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530442 logger.Debugw(ctx, "child-device-found", log.Fields{"proxy-address": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500443 return foundChildDevice, nil
444 }
445
Himani Chawlab4c25912020-11-12 17:16:38 +0530446 logger.Warnw(ctx, "child-device-not-found", log.Fields{"proxy-address": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500447 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
448}
449
npujar1d86a522019-11-14 17:11:16 +0530450// IsDeviceInCache returns true if device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400451func (dMgr *Manager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400452 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500453 return exist
454}
455
Stephane Barbarieaa467942019-02-06 14:09:44 -0500456// ListDevices retrieves the latest devices from the data model
Kent Hagerman45a13e42020-04-13 12:23:50 -0400457func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530458 ctx = utils.WithRPCMetadataContext(ctx, "ListDevices")
459 logger.Debug(ctx, "list-devices")
khenaidoob9203542018-09-17 22:56:37 -0400460 result := &voltha.Devices{}
Kent Hagerman4f355f52020-03-30 16:01:33 -0400461
Esin Karamana4e4e002021-03-02 10:42:16 +0000462 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
463 result.Items = append(result.Items, value.(*Agent).device)
464 return true
465 })
Kent Hagerman4f355f52020-03-30 16:01:33 -0400466
Himani Chawlab4c25912020-11-12 17:16:38 +0530467 logger.Debugw(ctx, "list-devices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400468 return result, nil
469}
470
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530471//isParentDeviceExist checks whether device is already preprovisioned.
Kent Hagerman2b216042020-04-03 18:28:56 -0400472func (dMgr *Manager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530473 hostPort := newDevice.GetHostAndPort()
Kent Hagerman4f355f52020-03-30 16:01:33 -0400474 var devices []*voltha.Device
Kent Hagermanf5a67352020-04-30 15:15:26 -0400475 if err := dMgr.dProxy.List(ctx, &devices); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530476 logger.Errorw(ctx, "failed-to-list-devices-from-cluster-data-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530477 return false, err
478 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400479 for _, device := range devices {
480 if !device.Root {
481 continue
482 }
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530483
484 if hostPort != "" && hostPort == device.GetHostAndPort() {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400485 return true, nil
486 }
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530487 if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400488 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530489 }
490 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530491 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530492}
493
khenaidoo6d62c002019-05-15 21:57:03 -0400494//getDeviceFromModelretrieves the device data from the model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400495func (dMgr *Manager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400496 device := &voltha.Device{}
Kent Hagermanf5a67352020-04-30 15:15:26 -0400497 if have, err := dMgr.dProxy.Get(ctx, deviceID, device); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000498 logger.Errorw(ctx, "failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530499 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400500 } else if !have {
501 return nil, status.Error(codes.NotFound, deviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530502 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400503
504 return device, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400505}
506
npujar1d86a522019-11-14 17:11:16 +0530507// loadDevice loads the deviceID in memory, if not present
Kent Hagerman2b216042020-04-03 18:28:56 -0400508func (dMgr *Manager) loadDevice(ctx context.Context, deviceID string) (*Agent, error) {
npujar1d86a522019-11-14 17:11:16 +0530509 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500510 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
511 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400512 var err error
513 var device *voltha.Device
514 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530515 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
516 if !dMgr.IsDeviceInCache(deviceID) {
517 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400518 dMgr.devicesLoadingLock.Unlock()
519 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530520 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000521 logger.Debugw(ctx, "loading-device", log.Fields{"device-id": deviceID})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700522 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530523 if _, err = agent.start(ctx, nil); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530524 logger.Warnw(ctx, "failure-loading-device", log.Fields{"device-id": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400525 } else {
526 dMgr.addDeviceAgentToMap(agent)
527 }
528 } else {
Himani Chawlab4c25912020-11-12 17:16:38 +0530529 logger.Debugw(ctx, "device-is-not-in-model", log.Fields{"device-id": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400530 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400531 // announce completion of task to any number of waiting channels
532 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530533 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400534 for _, ch := range v {
535 close(ch)
536 }
npujar1d86a522019-11-14 17:11:16 +0530537 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400538 }
539 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400540 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400541 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500542 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400543 } else {
544 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530545 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400546 dMgr.devicesLoadingLock.Unlock()
547 // Wait for the channel to be closed, implying the process loading this device is done.
548 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500549 }
npujar1d86a522019-11-14 17:11:16 +0530550 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400551 return agent.(*Agent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500552 }
npujar1d86a522019-11-14 17:11:16 +0530553 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500554}
555
556// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
Kent Hagerman2a07b862020-06-19 15:23:07 -0400557func (dMgr *Manager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device, devicePorts map[uint32]*voltha.Port) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000558 logger.Debugw(ctx, "loading-parent-and-children", log.Fields{"device-id": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500559 if device.Root {
560 // Scenario A
561 if device.ParentId != "" {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400562 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530563 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000564 logger.Warnw(ctx, "failure-loading-logical-device", log.Fields{"logical-device-id": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500565 }
566 } else {
divyadesaicb8b59d2020-08-18 09:55:47 +0000567 logger.Debugw(ctx, "no-parent-to-load", log.Fields{"device-id": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500568 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400569 // Load all child devices, if needed
570 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, devicePorts)
571 for childDeviceID := range childDeviceIds {
572 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000573 logger.Warnw(ctx, "failure-loading-device", log.Fields{"device-id": childDeviceID, "error": err})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400574 return err
khenaidoo297cd252019-02-07 22:10:23 -0500575 }
khenaidoo297cd252019-02-07 22:10:23 -0500576 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530577 logger.Debugw(ctx, "loaded-children", log.Fields{"device-id": device.Id, "num-children": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500578 }
579 return nil
580}
581
582// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
583// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
584// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
585// and the proceed with the request.
Kent Hagerman2b216042020-04-03 18:28:56 -0400586func (dMgr *Manager) load(ctx context.Context, deviceID string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000587 logger.Debug(ctx, "load...")
khenaidoo297cd252019-02-07 22:10:23 -0500588 // 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 -0400589 var dAgent *Agent
khenaidoo297cd252019-02-07 22:10:23 -0500590 var err error
npujar467fe752020-01-16 20:17:45 +0530591 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500592 return err
593 }
594 // Get the loaded device details
Kent Hagermancba2f302020-07-28 13:37:36 -0400595 device, err := dAgent.getDeviceReadOnly(ctx)
khenaidoo442e7c72020-03-10 16:13:48 -0400596 if err != nil {
597 return err
598 }
khenaidoo297cd252019-02-07 22:10:23 -0500599
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530600 // If the device is in Pre-provisioning or getting deleted state stop here
601 if device.AdminState == voltha.AdminState_PREPROVISIONED || dAgent.isDeletionInProgress() {
khenaidoo297cd252019-02-07 22:10:23 -0500602 return nil
603 }
604
605 // Now we face two scenarios
606 if device.Root {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400607 devicePorts := dAgent.listDevicePorts()
608
khenaidoo297cd252019-02-07 22:10:23 -0500609 // Load all children as well as the parent of this device (logical_device)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400610 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device, devicePorts); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000611 logger.Warnw(ctx, "failure-loading-device-parent-and-children", log.Fields{"device-id": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500612 return err
613 }
divyadesaicb8b59d2020-08-18 09:55:47 +0000614 logger.Debugw(ctx, "successfully-loaded-parent-and-children", log.Fields{"device-id": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500615 } else {
616 // Scenario B - use the parentId of that device (root device) to trigger the loading
617 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530618 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500619 }
620 }
621 return nil
622}
623
khenaidoo7ccedd52018-12-14 16:48:54 -0500624// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000625func (dMgr *Manager) ListDeviceIds(ctx context.Context, _ *empty.Empty) (*voltha.IDs, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530626 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceIds")
627 logger.Debug(ctx, "list-device-ids")
khenaidoo7ccedd52018-12-14 16:48:54 -0500628 // Report only device IDs that are in the device agent map
629 return dMgr.listDeviceIdsFromMap(), nil
630}
631
Kent Hagerman45a13e42020-04-13 12:23:50 -0400632// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
633// trigger loading the devices along with their children and parent in memory
634func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530635 ctx = utils.WithRPCMetadataContext(ctx, "ReconcileDevices")
636 logger.Debugw(ctx, "reconcile-devices", log.Fields{"num-devices": len(ids.Items)})
khenaidoo4c9e5592019-09-09 16:20:41 -0400637 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500638 toReconcile := len(ids.Items)
639 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400640 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500641 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530642 if err = dMgr.load(ctx, id.Id); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000643 logger.Warnw(ctx, "failure-reconciling-device", log.Fields{"device-id": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400644 } else {
npujar1d86a522019-11-14 17:11:16 +0530645 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500646 }
647 }
648 if toReconcile != reconciled {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400649 return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500650 }
651 } else {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400652 return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
khenaidoo7ccedd52018-12-14 16:48:54 -0500653 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400654 return &empty.Empty{}, nil
khenaidoo7ccedd52018-12-14 16:48:54 -0500655}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500656
khenaidooba6b6c42019-08-02 09:11:56 -0400657// adapterRestarted is invoked whenever an adapter is restarted
Kent Hagerman2b216042020-04-03 18:28:56 -0400658func (dMgr *Manager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530659 logger.Debugw(ctx, "adapter-restarted", log.Fields{"adapter-id": adapter.Id, "vendor": adapter.Vendor,
660 "current-replica": adapter.CurrentReplica, "total-replicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidooba6b6c42019-08-02 09:11:56 -0400661
662 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700663 if len(dMgr.rootDevices) == 0 {
Himani Chawlab4c25912020-11-12 17:16:38 +0530664 logger.Debugw(ctx, "nothing-to-reconcile", log.Fields{"adapter-id": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400665 return nil
666 }
667
Maninder0aabf0c2021-03-17 14:55:14 +0530668 if len(dMgr.rootDevices) == 0 {
669 logger.Debugw(ctx, "no-managed-device-to-reconcile", log.Fields{"adapter-id": adapter.Id})
670 return nil
671 }
672
David Bainbridged1afd662020-03-26 18:27:41 -0700673 for rootDeviceID := range dMgr.rootDevices {
Mahir Gunyel12cf55f2020-12-16 17:55:03 -0800674 dAgent := dMgr.getDeviceAgent(ctx, rootDeviceID)
675 if dAgent == nil {
676 continue
677 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530678 logger.Debugw(ctx, "checking-adapter-type", log.Fields{"agentType": dAgent.deviceType, "adapter-type": adapter.Type})
Mahir Gunyel12cf55f2020-12-16 17:55:03 -0800679 if dAgent.deviceType == adapter.Type {
680 rootDevice, _ := dAgent.getDeviceReadOnly(ctx)
681 if rootDevice == nil {
682 continue
683 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000684 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(ctx, rootDeviceID, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700685 if err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530686 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 -0700687 continue
688 }
689 if isDeviceOwnedByService {
Maninder0aabf0c2021-03-17 14:55:14 +0530690 if rootDevice.AdminState != voltha.AdminState_PREPROVISIONED {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000691 logger.Debugw(ctx, "reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
Maninder0aabf0c2021-03-17 14:55:14 +0530692 go dAgent.ReconcileDevice(ctx, rootDevice)
khenaidooba6b6c42019-08-02 09:11:56 -0400693 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000694 logger.Debugw(ctx, "not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400695 }
696 } else { // Should we be reconciling the root's children instead?
Kent Hagerman2a07b862020-06-19 15:23:07 -0400697 rootDevicePorts, _ := dMgr.listDevicePorts(ctx, rootDeviceID)
khenaidooba6b6c42019-08-02 09:11:56 -0400698 childManagedByAdapter:
Kent Hagerman2a07b862020-06-19 15:23:07 -0400699 for _, port := range rootDevicePorts {
khenaidooba6b6c42019-08-02 09:11:56 -0400700 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530701 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000702 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(ctx, childDevice.Id, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700703 if err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530704 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 -0700705 }
706 if isDeviceOwnedByService {
Maninder0aabf0c2021-03-17 14:55:14 +0530707 if childDevice.AdminState != voltha.AdminState_PREPROVISIONED {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000708 logger.Debugw(ctx, "reconciling-child-device", log.Fields{"child-device-id": childDevice.Id})
Maninder0aabf0c2021-03-17 14:55:14 +0530709 go dAgent.ReconcileDevice(ctx, childDevice)
khenaidooba6b6c42019-08-02 09:11:56 -0400710 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000711 logger.Debugw(ctx, "not-reconciling-child-device", log.Fields{"child-device-id": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400712 }
713 } else {
714 // All child devices under a parent device are typically managed by the same adapter type.
715 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
716 break childManagedByAdapter
717 }
718 }
719 }
720 }
721 }
722 }
723 }
Maninder0aabf0c2021-03-17 14:55:14 +0530724 logger.Debugw(ctx, "Reconciling for device on adapter restart is initiated", log.Fields{"adapter-id": adapter.Id})
725
khenaidooba6b6c42019-08-02 09:11:56 -0400726 return nil
727}
728
Kent Hagerman2b216042020-04-03 18:28:56 -0400729func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID string) error {
Maninder0aabf0c2021-03-17 14:55:14 +0530730 dAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
731 if dAgent == nil {
732 return status.Errorf(codes.NotFound, "error-unable to get agent from device")
733 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400734 if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400735 for _, port := range parentDevicePorts {
khenaidooba6b6c42019-08-02 09:11:56 -0400736 for _, peer := range port.Peers {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400737 if childDevice, err := dMgr.getDeviceFromModel(ctx, peer.DeviceId); err == nil {
Maninder0aabf0c2021-03-17 14:55:14 +0530738 go dAgent.ReconcileDevice(ctx, childDevice)
khenaidooba6b6c42019-08-02 09:11:56 -0400739 }
740 }
741 }
Maninder0aabf0c2021-03-17 14:55:14 +0530742 logger.Debugw(ctx, "Reconcile initiated for child devices", log.Fields{"parent-device-id": parentDeviceID})
khenaidooba6b6c42019-08-02 09:11:56 -0400743 }
744 return nil
745}
746
Kent Hagerman2b216042020-04-03 18:28:56 -0400747func (dMgr *Manager) UpdateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530748 logger.Debugw(ctx, "update-device-using-adapter-data", log.Fields{"device-id": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530749 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
750 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400751 }
752 return status.Errorf(codes.NotFound, "%s", device.Id)
753}
754
khenaidoo0db4c812020-05-27 15:27:30 -0400755func (dMgr *Manager) addPeerPort(ctx context.Context, deviceID string, port *voltha.Port) error {
756 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
757 for _, peerPort := range port.Peers {
758 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
759 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
760 return err
761 }
762 }
763 }
764 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
765 // then a logical port will be added to the logical device and the device route generated. If the port is a
766 // PON port then only the device graph will be generated.
Kent Hagermancba2f302020-07-28 13:37:36 -0400767 device, err := dMgr.getDeviceReadOnly(ctx, deviceID)
khenaidoo0db4c812020-05-27 15:27:30 -0400768 if err != nil {
769 return err
770 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400771 ports, err := dMgr.listDevicePorts(ctx, deviceID)
772 if err != nil {
773 return err
774 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530775 subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
776
777 if err = dMgr.logicalDeviceMgr.updateLogicalPort(subCtx, device, ports, port); err != nil {
khenaidoo0db4c812020-05-27 15:27:30 -0400778 return err
779 }
780 return nil
781}
782
Kent Hagerman2b216042020-04-03 18:28:56 -0400783func (dMgr *Manager) AddPort(ctx context.Context, deviceID string, port *voltha.Port) error {
npujar467fe752020-01-16 20:17:45 +0530784 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530785 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530786 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400787 return err
788 }
khenaidoo0db4c812020-05-27 15:27:30 -0400789 // Setup peer ports in its own routine
790 go func() {
Himani Chawlab4c25912020-11-12 17:16:38 +0530791 subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
792 if err := dMgr.addPeerPort(subCtx, deviceID, port); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000793 logger.Errorw(ctx, "unable-to-add-peer-port", log.Fields{"error": err, "device-id": deviceID})
khenaidoo92e62c52018-10-03 14:02:54 -0400794 }
khenaidoo0db4c812020-05-27 15:27:30 -0400795 }()
khenaidoo92e62c52018-10-03 14:02:54 -0400796 return nil
khenaidoob9203542018-09-17 22:56:37 -0400797 }
npujar1d86a522019-11-14 17:11:16 +0530798 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400799}
800
Kent Hagerman2b216042020-04-03 18:28:56 -0400801func (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 +0530802 logger.Debugw(ctx, "add-flows-and-groups", log.Fields{"device-id": deviceID, "groups:": groups, "flow-metadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530803 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
804 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400805 }
npujar1d86a522019-11-14 17:11:16 +0530806 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400807}
808
khenaidoo787224a2020-04-16 18:08:47 -0400809// deleteParentFlows removes flows from the parent device based on specific attributes
810func (dMgr *Manager) deleteParentFlows(ctx context.Context, deviceID string, uniPort uint32, metadata *voltha.FlowMetadata) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530811 logger.Debugw(ctx, "delete-parent-flows", log.Fields{"device-id": deviceID, "uni-port": uniPort, "metadata": metadata})
khenaidoo787224a2020-04-16 18:08:47 -0400812 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400813 if !agent.isRootDevice {
khenaidoo787224a2020-04-16 18:08:47 -0400814 return status.Errorf(codes.FailedPrecondition, "not-a-parent-device-%s", deviceID)
815 }
816 return agent.filterOutFlows(ctx, uniPort, metadata)
817 }
818 return status.Errorf(codes.NotFound, "%s", deviceID)
819}
820
Kent Hagerman2b216042020-04-03 18:28:56 -0400821func (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 +0530822 logger.Debugw(ctx, "delete-flows-and-groups", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530823 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
824 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400825 }
npujar1d86a522019-11-14 17:11:16 +0530826 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400827}
828
Kent Hagerman2b216042020-04-03 18:28:56 -0400829func (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 +0530830 logger.Debugw(ctx, "update-flows-and-groups", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530831 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
832 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400833 }
npujar1d86a522019-11-14 17:11:16 +0530834 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400835}
836
Kent Hagerman45a13e42020-04-13 12:23:50 -0400837// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
khenaidoob3127472019-07-24 21:04:55 -0400838// following a user action
Kent Hagerman45a13e42020-04-13 12:23:50 -0400839func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530840 ctx = utils.WithRPCMetadataContext(ctx, "UpdateDevicePmConfigs")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000841 log.EnrichSpan(ctx, log.Fields{"device-id": configs.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400842 if configs.Id == "" {
843 return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
khenaidoob3127472019-07-24 21:04:55 -0400844 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400845 agent := dMgr.getDeviceAgent(ctx, configs.Id)
846 if agent == nil {
847 return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
848 }
849 return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
khenaidoob3127472019-07-24 21:04:55 -0400850}
851
Kent Hagerman2b216042020-04-03 18:28:56 -0400852// InitPmConfigs initialize the pm configs as defined by the adapter.
853func (dMgr *Manager) InitPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400854 if pmConfigs.Id == "" {
855 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
856 }
npujar467fe752020-01-16 20:17:45 +0530857 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
858 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400859 }
npujar1d86a522019-11-14 17:11:16 +0530860 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400861}
862
Kent Hagerman45a13e42020-04-13 12:23:50 -0400863// ListDevicePmConfigs returns pm configs of device
864func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530865 ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePmConfigs")
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000866 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400867 agent := dMgr.getDeviceAgent(ctx, id.Id)
868 if agent == nil {
869 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob3127472019-07-24 21:04:55 -0400870 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400871 return agent.listPmConfigs(ctx)
khenaidoob3127472019-07-24 21:04:55 -0400872}
873
Kent Hagerman2b216042020-04-03 18:28:56 -0400874func (dMgr *Manager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530875 logger.Debugw(ctx, "get-switch-capability", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530876 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400877 return agent.getSwitchCapability(ctx)
878 }
npujar1d86a522019-11-14 17:11:16 +0530879 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400880}
881
Kent Hagerman2b216042020-04-03 18:28:56 -0400882func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530883 logger.Debugw(ctx, "get-ports", log.Fields{"device-id": deviceID, "port-type": portType})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400884 agent := dMgr.getDeviceAgent(ctx, deviceID)
885 if agent == nil {
886 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400887 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400888 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400889}
890
Kent Hagerman2b216042020-04-03 18:28:56 -0400891func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530892 logger.Debugw(ctx, "update-device-status", log.Fields{"device-id": deviceID, "oper-status": operStatus, "conn-status": connStatus})
npujar467fe752020-01-16 20:17:45 +0530893 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
894 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400895 }
npujar1d86a522019-11-14 17:11:16 +0530896 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400897}
898
Kent Hagerman2b216042020-04-03 18:28:56 -0400899func (dMgr *Manager) UpdateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530900 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 -0400901 parentDevicePorts, err := dMgr.listDevicePorts(ctx, deviceID)
902 if err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400903 return status.Errorf(codes.Aborted, "%s", err.Error())
904 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400905 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
npujar467fe752020-01-16 20:17:45 +0530906 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
907 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530908 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400909 }
910 }
911 }
912 return nil
913}
914
Kent Hagerman2b216042020-04-03 18:28:56 -0400915func (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 +0530916 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 +0530917 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
918 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530919 logger.Errorw(ctx, "updating-port-state-failed", log.Fields{"device-id": deviceID, "port-no": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400920 return err
921 }
922 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800923 // Do this for NNI and UNIs only. PON ports are not known by logical device
924 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
925 go func() {
Himani Chawlab4c25912020-11-12 17:16:38 +0530926 subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
927 err := dMgr.logicalDeviceMgr.updatePortState(subCtx, deviceID, portNo, operStatus)
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800928 if err != nil {
929 // While we want to handle (catch) and log when
930 // an update to a port was not able to be
931 // propagated to the logical port, we can report
932 // it as a warning and not an error because it
933 // doesn't stop or modify processing.
934 // TODO: VOL-2707
Rohan Agrawal31f21802020-06-12 05:38:46 +0000935 logger.Warnw(ctx, "unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800936 }
937 }()
938 }
khenaidoo442e7c72020-03-10 16:13:48 -0400939 return nil
khenaidoob9203542018-09-17 22:56:37 -0400940 }
npujar1d86a522019-11-14 17:11:16 +0530941 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400942}
943
Kent Hagerman2b216042020-04-03 18:28:56 -0400944func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID string) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530945 logger.Debugw(ctx, "delete-all-ports", log.Fields{"device-id": deviceID})
npujar467fe752020-01-16 20:17:45 +0530946 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
947 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400948 return err
949 }
950 // Notify the logical device manager to remove all logical ports, if needed.
Kent Hagerman2b216042020-04-03 18:28:56 -0400951 // At this stage the device itself may gave been deleted already at a DeleteAllPorts
khenaidoo0a822f92019-05-08 15:15:57 -0400952 // typically is part of a device deletion phase.
Kent Hagermancba2f302020-07-28 13:37:36 -0400953 if device, err := dMgr.getDeviceReadOnly(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530954 go func() {
Himani Chawlab4c25912020-11-12 17:16:38 +0530955 subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
956 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(subCtx, device); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000957 logger.Errorw(ctx, "unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530958 }
959 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400960 } else {
divyadesaicb8b59d2020-08-18 09:55:47 +0000961 logger.Warnw(ctx, "failed-to-retrieve-device", log.Fields{"device-id": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400962 return err
963 }
964 return nil
965 }
npujar1d86a522019-11-14 17:11:16 +0530966 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400967}
968
Kent Hagerman2b216042020-04-03 18:28:56 -0400969//UpdatePortsState updates all ports on the device
Kent Hagerman2a07b862020-06-19 15:23:07 -0400970func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, portTypeFilter uint32, state voltha.OperStatus_Types) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530971 logger.Debugw(ctx, "update-ports-state", log.Fields{"device-id": deviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400972 agent := dMgr.getDeviceAgent(ctx, deviceID)
973 if agent == nil {
974 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400975 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400976 if state != voltha.OperStatus_ACTIVE && state != voltha.OperStatus_UNKNOWN {
977 return status.Error(codes.Unimplemented, "state-change-not-implemented")
978 }
979 if err := agent.updatePortsOperState(ctx, portTypeFilter, state); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +0530980 logger.Warnw(ctx, "update-ports-state-failed", log.Fields{"device-id": deviceID, "error": err})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400981 return err
982 }
983 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400984}
985
Kent Hagerman2b216042020-04-03 18:28:56 -0400986func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530987 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530988 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 -0700989
npujar1d86a522019-11-14 17:11:16 +0530990 if deviceType == "" && vendorID != "" {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000991 logger.Debug(ctx, "device-type-is-nil-fetching-device-type")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400992 deviceTypes, err := dMgr.adapterMgr.ListDeviceTypes(ctx, nil)
993 if err != nil {
994 return nil, err
995 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400996 OLoop:
Kent Hagerman45a13e42020-04-13 12:23:50 -0400997 for _, dType := range deviceTypes.Items {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400998 for _, v := range dType.VendorIds {
999 if v == vendorID {
1000 deviceType = dType.Adapter
1001 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001002 }
1003 }
1004 }
1005 }
1006 //if no match found for the vendorid,report adapter with the custom error message
1007 if deviceType == "" {
Himani Chawlab4c25912020-11-12 17:16:38 +05301008 logger.Errorw(ctx, "failed-to-fetch-adapter-name ", log.Fields{"vendor-id": vendorID})
npujar1d86a522019-11-14 17:11:16 +05301009 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001010 }
khenaidoob9203542018-09-17 22:56:37 -04001011
1012 // Create the ONU device
1013 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -04001014 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +05301015 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -04001016 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +05301017 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -05001018 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -04001019 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001020
khenaidoo442e7c72020-03-10 16:13:48 -04001021 // Get parent device type
1022 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
1023 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +05301024 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001025 }
khenaidoo442e7c72020-03-10 16:13:48 -04001026 if pAgent.deviceType == "" {
1027 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
1028 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001029
npujar467fe752020-01-16 20:17:45 +05301030 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301031 logger.Warnw(ctx, "child-device-exists", log.Fields{"parent-device-id": parentDeviceID, "serial-number": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001032 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001033 }
1034
khenaidoo442e7c72020-03-10 16:13:48 -04001035 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001036
1037 // Create and start a device agent for that device
Mahir Gunyel03de0d32020-06-03 01:36:59 -07001038 agent := newAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.defaultTimeout)
Mahir Gunyel23bd8c72020-09-21 23:20:43 -07001039 insertedChildDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001040 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001041 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 -08001042 return nil, err
1043 }
khenaidoo442e7c72020-03-10 16:13:48 -04001044 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001045
1046 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301047 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301048 go func() {
Maninder9a1bc0d2020-10-26 11:34:02 +05301049 subCtx := utils.WithFromTopicMetadataFromContext(utils.WithSpanAndRPCMetadataFromContext(ctx), ctx)
Himani Chawlab4c25912020-11-12 17:16:38 +05301050 err := agent.enableDevice(subCtx)
npujar1d86a522019-11-14 17:11:16 +05301051 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001052 logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301053 }
1054 }()
khenaidoob9203542018-09-17 22:56:37 -04001055 }
1056
Mahir Gunyel23bd8c72020-09-21 23:20:43 -07001057 return insertedChildDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001058}
1059
Kent Hagerman2b216042020-04-03 18:28:56 -04001060func (dMgr *Manager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301061 logger.Debugw(ctx, "packet-out", log.Fields{"device-id": deviceID, "out-port": outPort})
npujar467fe752020-01-16 20:17:45 +05301062 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1063 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001064 }
npujar1d86a522019-11-14 17:11:16 +05301065 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001066}
1067
npujar1d86a522019-11-14 17:11:16 +05301068// PacketIn receives packet from adapter
Kent Hagerman2b216042020-04-03 18:28:56 -04001069func (dMgr *Manager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301070 logger.Debugw(ctx, "packet-in", log.Fields{"device-id": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001071 // Get the logical device Id based on the deviceId
1072 var device *voltha.Device
1073 var err error
Kent Hagermancba2f302020-07-28 13:37:36 -04001074 if device, err = dMgr.getDeviceReadOnly(ctx, deviceID); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001075 logger.Errorw(ctx, "device-not-found", log.Fields{"device-id": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001076 return err
1077 }
khenaidoo43c82122018-11-22 18:38:28 -05001078 if !device.Root {
divyadesaicb8b59d2020-08-18 09:55:47 +00001079 logger.Errorw(ctx, "device-not-root", log.Fields{"device-id": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301080 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001081 }
1082
npujar467fe752020-01-16 20:17:45 +05301083 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001084 return err
1085 }
1086 return nil
1087}
1088
Kent Hagerman2b216042020-04-03 18:28:56 -04001089func (dMgr *Manager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301090 logger.Debugw(ctx, "set-parent-id", log.Fields{"device-id": device.Id, "parent-id": parentID})
npujar467fe752020-01-16 20:17:45 +05301091 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1092 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001093 }
1094 return status.Errorf(codes.NotFound, "%s", device.Id)
1095}
1096
Himani Chawlab4c25912020-11-12 17:16:38 +05301097//
1098//CreateLogicalDevice creates logical device in core
Kent Hagerman2b216042020-04-03 18:28:56 -04001099func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301100 logger.Info(ctx, "create-logical-device")
khenaidoo59ef7be2019-06-21 12:40:28 -04001101 // Verify whether the logical device has already been created
1102 if cDevice.ParentId != "" {
Himani Chawlab4c25912020-11-12 17:16:38 +05301103 logger.Debugw(ctx, "parent-device-already-exist", log.Fields{"device-id": cDevice.Id, "logical-device-id": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001104 return nil
1105 }
khenaidoob9203542018-09-17 22:56:37 -04001106 var err error
npujar467fe752020-01-16 20:17:45 +05301107 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301108 logger.Warnw(ctx, "create-logical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001109 return err
1110 }
khenaidoob9203542018-09-17 22:56:37 -04001111 return nil
1112}
1113
npujar1d86a522019-11-14 17:11:16 +05301114// DeleteLogicalDevice deletes logical device from core
Kent Hagerman2b216042020-04-03 18:28:56 -04001115func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301116 logger.Info(ctx, "delete-logical-device")
khenaidoo92e62c52018-10-03 14:02:54 -04001117 var err error
npujar467fe752020-01-16 20:17:45 +05301118 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301119 logger.Warnw(ctx, "delete-logical-device-error", log.Fields{"device-id": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001120 return err
1121 }
1122 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301123 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301124 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001125 return nil
1126}
1127
npujar1d86a522019-11-14 17:11:16 +05301128// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagerman2b216042020-04-03 18:28:56 -04001129func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001130 logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001131 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001132 // 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 +05301133 logger.Warnw(ctx, "delete-logical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001134 }
1135 return nil
1136}
1137
Kent Hagerman2b216042020-04-03 18:28:56 -04001138func (dMgr *Manager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001139 // Sanity check
1140 if childDevice.Root {
1141 // childDevice is the parent device
1142 return childDevice
1143 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001144 parentDevice, _ := dMgr.getDeviceReadOnly(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001145 return parentDevice
1146}
1147
Kent Hagerman2b216042020-04-03 18:28:56 -04001148//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 -04001149//cannot manage the child devices. This will trigger the Core to disable all the child devices.
Kent Hagerman2b216042020-04-03 18:28:56 -04001150func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301151 logger.Debug(ctx, "child-devices-lost")
Kent Hagermancba2f302020-07-28 13:37:36 -04001152 parentDevice, err := dMgr.getDeviceReadOnly(ctx, parentDeviceID)
Kent Hagerman2a07b862020-06-19 15:23:07 -04001153 if err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001154 logger.Warnw(ctx, "failed-getting-device", log.Fields{"parent-device-id": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001155 return err
1156 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001157 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001158}
1159
Kent Hagerman2b216042020-04-03 18:28:56 -04001160//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
khenaidoo0a822f92019-05-08 15:15:57 -04001161// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
Kent Hagerman2b216042020-04-03 18:28:56 -04001162func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301163 logger.Debug(ctx, "child-devices-detected")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001164 parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID)
1165 if err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +00001166 logger.Warnw(ctx, "failed-getting-device", log.Fields{"device-id": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001167 return err
1168 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001169 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDevicePorts)
khenaidoo0a822f92019-05-08 15:15:57 -04001170 if len(childDeviceIds) == 0 {
divyadesaicb8b59d2020-08-18 09:55:47 +00001171 logger.Debugw(ctx, "no-child-device", log.Fields{"parent-device-id": parentDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001172 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001173 allChildEnableRequestSent := true
Kent Hagerman2a07b862020-06-19 15:23:07 -04001174 for childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301175 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301176 subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
khenaidoo59ef7be2019-06-21 12:40:28 -04001177 // Run the children re-registration in its own routine
Kent Hagerman2a07b862020-06-19 15:23:07 -04001178 go func(ctx context.Context) {
1179 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301180 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001181 logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301182 }
Himani Chawlab4c25912020-11-12 17:16:38 +05301183 }(subCtx)
khenaidoo59ef7be2019-06-21 12:40:28 -04001184 } else {
npujar1d86a522019-11-14 17:11:16 +05301185 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Himani Chawlab4c25912020-11-12 17:16:38 +05301186 logger.Errorw(ctx, "no-child-device-agent", log.Fields{"parent-device-id": parentDeviceID, "child-id": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001187 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001188 }
1189 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001190 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001191 return err
1192 }
1193 return nil
1194}
1195
khenaidoo4d4802d2018-10-04 21:59:49 -04001196/*
1197All the functions below are callback functions where they are invoked with the latest and previous data. We can
1198therefore use the data as is without trying to get the latest from the model.
1199*/
1200
khenaidoo0a822f92019-05-08 15:15:57 -04001201//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagerman2b216042020-04-03 18:28:56 -04001202func (dMgr *Manager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301203 logger.Debug(ctx, "disable-all-child-devices")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001204 ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
1205 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
npujar467fe752020-01-16 20:17:45 +05301206 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -04001207 if err := agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001208 // Just log the error - this error happens only if the child device was already in deleted state.
divyadesaicb8b59d2020-08-18 09:55:47 +00001209 logger.Errorw(ctx, "failure-disable-device", log.Fields{"device-id": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001210 }
1211 }
1212 }
1213 return nil
1214}
1215
khenaidoo0a822f92019-05-08 15:15:57 -04001216//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001217func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301218 logger.Debug(ctx, "delete-all-child-devices")
Himani Chawla2ba1c9c2020-10-07 13:19:03 +05301219 force := false
1220 // Get the parent device Transient state, if its FORCE_DELETED(go for force delete for child devices)
1221 // So in cases when this handler is getting called other than DELETE operation, no force option would be used.
1222 agent := dMgr.getDeviceAgent(ctx, parentCurrDevice.Id)
1223 if agent == nil {
1224 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
1225 }
1226
1227 force = agent.getTransientState() == voltha.DeviceTransientState_FORCE_DELETING
1228
Kent Hagerman2a07b862020-06-19 15:23:07 -04001229 ports, _ := dMgr.listDevicePorts(ctx, parentCurrDevice.Id)
1230 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ports) {
npujar467fe752020-01-16 20:17:45 +05301231 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
Himani Chawla2ba1c9c2020-10-07 13:19:03 +05301232 if force {
1233 if err := agent.deleteDeviceForce(ctx); err != nil {
1234 logger.Warnw(ctx, "failure-delete-device-force", log.Fields{"device-id": childDeviceID,
1235 "error": err.Error()})
1236 }
1237 } else {
1238 if err := agent.deleteDevice(ctx); err != nil {
1239 logger.Warnw(ctx, "failure-delete-device", log.Fields{"device-id": childDeviceID,
1240 "error": err.Error()})
1241 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001242 }
khenaidoo49085352020-01-13 19:15:43 -05001243 // No further action is required here. The deleteDevice will change the device state where the resulting
1244 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001245 }
1246 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001247 return nil
1248}
1249
Girish Gowdra408cd962020-03-11 14:31:31 -07001250//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001251func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001252 logger.Debugw(ctx, "delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001253 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001254 // Just log error as logical device may already have been deleted
Rohan Agrawal31f21802020-06-12 05:38:46 +00001255 logger.Warnw(ctx, "delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001256 }
1257 return nil
1258}
1259
1260//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001261func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001262 logger.Debugw(ctx, "delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001263 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1264 if err := agent.deleteAllFlows(ctx); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +00001265 logger.Errorw(ctx, "error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001266 return err
1267 }
1268 return nil
1269 }
1270 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1271}
1272
khenaidoo4d4802d2018-10-04 21:59:49 -04001273//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 -04001274func (dMgr *Manager) getAllChildDeviceIds(ctx context.Context, parentDevicePorts map[uint32]*voltha.Port) map[string]struct{} {
Himani Chawlab4c25912020-11-12 17:16:38 +05301275 logger.Debug(ctx, "get-all-child-device-ids")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001276 childDeviceIds := make(map[string]struct{}, len(parentDevicePorts))
1277 for _, port := range parentDevicePorts {
1278 for _, peer := range port.Peers {
1279 childDeviceIds[peer.DeviceId] = struct{}{}
khenaidoo92e62c52018-10-03 14:02:54 -04001280 }
1281 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001282 logger.Debugw(ctx, "returning-getAllChildDeviceIds", log.Fields{"childDeviceIds": childDeviceIds})
1283 return childDeviceIds
khenaidoo92e62c52018-10-03 14:02:54 -04001284}
1285
Kent Hagerman2b216042020-04-03 18:28:56 -04001286//GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1287func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301288 logger.Debugw(ctx, "get-all-child-devices", log.Fields{"parent-device-id": parentDeviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -04001289 if parentDevicePorts, err := dMgr.listDevicePorts(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001290 childDevices := make([]*voltha.Device, 0)
Kent Hagerman2a07b862020-06-19 15:23:07 -04001291 for deviceID := range dMgr.getAllChildDeviceIds(ctx, parentDevicePorts) {
Kent Hagermancba2f302020-07-28 13:37:36 -04001292 if d, e := dMgr.getDeviceReadOnly(ctx, deviceID); e == nil && d != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -04001293 childDevices = append(childDevices, d)
khenaidoo297cd252019-02-07 22:10:23 -05001294 }
1295 }
1296 return &voltha.Devices{Items: childDevices}, nil
1297 }
npujar1d86a522019-11-14 17:11:16 +05301298 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001299}
1300
npujar1d86a522019-11-14 17:11:16 +05301301// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagerman2b216042020-04-03 18:28:56 -04001302func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301303 logger.Info(ctx, "setup-uni-logical-ports")
Kent Hagerman2a07b862020-06-19 15:23:07 -04001304 cDevicePorts, err := dMgr.listDevicePorts(ctx, cDevice.Id)
1305 if err != nil {
1306 return err
1307 }
1308 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice, cDevicePorts); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301309 logger.Warnw(ctx, "setup-uni-logical-ports-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001310 return err
1311 }
1312 return nil
1313}
1314
Kent Hagerman45a13e42020-04-13 12:23:50 -04001315// convenience to avoid redefining
1316var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
1317
1318// DownloadImage execute an image download request
1319func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301320 ctx = utils.WithRPCMetadataContext(ctx, "DownloadImage")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001321 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301322 logger.Debugw(ctx, "download-image", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001323 agent := dMgr.getDeviceAgent(ctx, img.Id)
1324 if agent == nil {
1325 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001326 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001327 resp, err := agent.downloadImage(ctx, img)
1328 if err != nil {
1329 return operationFailureResp, err
1330 }
1331 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001332}
1333
Kent Hagerman45a13e42020-04-13 12:23:50 -04001334// CancelImageDownload cancels image download request
1335func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301336 ctx = utils.WithRPCMetadataContext(ctx, "CancelImageDownload")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001337 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301338 logger.Debugw(ctx, "cancel-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001339 agent := dMgr.getDeviceAgent(ctx, img.Id)
1340 if agent == nil {
1341 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001342 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001343 resp, err := agent.cancelImageDownload(ctx, img)
1344 if err != nil {
1345 return operationFailureResp, err
1346 }
1347 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001348}
1349
Kent Hagerman45a13e42020-04-13 12:23:50 -04001350// ActivateImageUpdate activates image update request
1351func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301352 ctx = utils.WithRPCMetadataContext(ctx, "ActivateImageUpdate")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001353 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301354 logger.Debugw(ctx, "activate-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001355 agent := dMgr.getDeviceAgent(ctx, img.Id)
1356 if agent == nil {
1357 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001358 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001359 resp, err := agent.activateImage(ctx, img)
1360 if err != nil {
1361 return operationFailureResp, err
1362 }
1363 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001364}
1365
Kent Hagerman45a13e42020-04-13 12:23:50 -04001366// RevertImageUpdate reverts image update
1367func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301368 ctx = utils.WithRPCMetadataContext(ctx, "RevertImageUpdate")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001369 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301370 logger.Debugw(ctx, "rever-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001371 agent := dMgr.getDeviceAgent(ctx, img.Id)
1372 if agent == nil {
1373 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001374 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001375 resp, err := agent.revertImage(ctx, img)
1376 if err != nil {
1377 return operationFailureResp, err
1378 }
1379 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001380}
1381
Kent Hagerman45a13e42020-04-13 12:23:50 -04001382// convenience to avoid redefining
1383var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
1384
1385// GetImageDownloadStatus returns status of image download
1386func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301387 ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownloadStatus")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001388 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301389 logger.Debugw(ctx, "get-image-download-status", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001390 agent := dMgr.getDeviceAgent(ctx, img.Id)
1391 if agent == nil {
1392 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001393 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001394 resp, err := agent.getImageDownloadStatus(ctx, img)
1395 if err != nil {
1396 return imageDownloadFailureResp, err
1397 }
1398 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001399}
1400
Kent Hagerman2b216042020-04-03 18:28:56 -04001401func (dMgr *Manager) UpdateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301402 ctx = utils.WithRPCMetadataContext(ctx, "UpdateImageDownload")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001403 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301404 logger.Debugw(ctx, "update-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
npujar467fe752020-01-16 20:17:45 +05301405 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1406 if err := agent.updateImageDownload(ctx, img); err != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301407 logger.Debugw(ctx, "update-image-download-failed", log.Fields{"err": err, "image-name": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001408 return err
1409 }
1410 } else {
1411 return status.Errorf(codes.NotFound, "%s", img.Id)
1412 }
1413 return nil
1414}
1415
Kent Hagerman45a13e42020-04-13 12:23:50 -04001416// GetImageDownload returns image download
Kent Hagerman2b216042020-04-03 18:28:56 -04001417func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301418 ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownload")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001419 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301420 logger.Debugw(ctx, "get-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001421 agent := dMgr.getDeviceAgent(ctx, img.Id)
1422 if agent == nil {
1423 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001424 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001425 resp, err := agent.getImageDownload(ctx, img)
1426 if err != nil {
1427 return imageDownloadFailureResp, err
1428 }
1429 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001430}
1431
Kent Hagerman45a13e42020-04-13 12:23:50 -04001432// ListImageDownloads returns image downloads
1433func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301434 ctx = utils.WithRPCMetadataContext(ctx, "ListImageDownloads")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001435 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301436 logger.Debugw(ctx, "list-image-downloads", log.Fields{"device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001437 agent := dMgr.getDeviceAgent(ctx, id.Id)
1438 if agent == nil {
1439 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001440 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001441 resp, err := agent.listImageDownloads(ctx, id.Id)
1442 if err != nil {
1443 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
1444 }
1445 return resp, nil
1446}
1447
1448// GetImages returns all images for a specific device entry
1449func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301450 ctx = utils.WithRPCMetadataContext(ctx, "GetImages")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001451 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301452 logger.Debugw(ctx, "get-images", log.Fields{"device-id": id.Id})
Kent Hagermancba2f302020-07-28 13:37:36 -04001453 device, err := dMgr.getDeviceReadOnly(ctx, id.Id)
Kent Hagerman45a13e42020-04-13 12:23:50 -04001454 if err != nil {
1455 return nil, err
1456 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001457 return device.Images, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001458}
1459
Rohan Agrawal31f21802020-06-12 05:38:46 +00001460func (dMgr *Manager) NotifyInvalidTransition(ctx context.Context, device *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301461 logger.Errorw(ctx, "notify-invalid-transition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001462 "device": device.Id,
1463 "curr-admin-state": device.AdminState,
1464 "curr-oper-state": device.OperStatus,
1465 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001466 })
khenaidoo0a822f92019-05-08 15:15:57 -04001467 //TODO: notify over kafka?
1468 return nil
1469}
1470
npujar1d86a522019-11-14 17:11:16 +05301471// UpdateDeviceAttribute updates value of particular device attribute
Kent Hagerman2b216042020-04-03 18:28:56 -04001472func (dMgr *Manager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301473 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -04001474 agent.(*Agent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001475 }
1476}
1477
npujar1d86a522019-11-14 17:11:16 +05301478// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -04001479func (dMgr *Manager) GetParentDeviceID(ctx context.Context, deviceID string) string {
Kent Hagermancba2f302020-07-28 13:37:36 -04001480 if device, _ := dMgr.getDeviceReadOnly(ctx, deviceID); device != nil {
Himani Chawlab4c25912020-11-12 17:16:38 +05301481 logger.Infow(ctx, "get-parent-device-id", log.Fields{"device-id": device.Id, "parent-id": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001482 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001483 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001484 return ""
khenaidoob9203542018-09-17 22:56:37 -04001485}
serkant.uluderya334479d2019-04-10 08:26:15 -07001486
Kent Hagerman45a13e42020-04-13 12:23:50 -04001487func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301488 ctx = utils.WithRPCMetadataContext(ctx, "SimulateAlarm")
1489 logger.Debugw(ctx, "simulate-alarm", log.Fields{"id": simulateReq.Id, "indicator": simulateReq.Indicator, "intf-id": simulateReq.IntfId,
1490 "port-type-name": simulateReq.PortTypeName, "onu-device-id": simulateReq.OnuDeviceId, "inverse-bit-error-rate": simulateReq.InverseBitErrorRate,
1491 "drift": simulateReq.Drift, "new-eqd": simulateReq.NewEqd, "onu-serial-number": simulateReq.OnuSerialNumber, "operation": simulateReq.Operation})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001492 agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
1493 if agent == nil {
1494 return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
serkant.uluderya334479d2019-04-10 08:26:15 -07001495 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001496 if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
1497 return nil, err
1498 }
1499 return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
serkant.uluderya334479d2019-04-10 08:26:15 -07001500}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001501
Kent Hagerman2b216042020-04-03 18:28:56 -04001502func (dMgr *Manager) UpdateDeviceReason(ctx context.Context, deviceID string, reason string) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301503 logger.Debugw(ctx, "update-device-reason", log.Fields{"device-id": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301504 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1505 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001506 }
npujar1d86a522019-11-14 17:11:16 +05301507 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001508}
kesavandbc2d1622020-01-21 00:42:01 -05001509
Kent Hagerman45a13e42020-04-13 12:23:50 -04001510func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301511 ctx = utils.WithRPCMetadataContext(ctx, "EnablePort")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001512 log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
Himani Chawlab4c25912020-11-12 17:16:38 +05301513 logger.Debugw(ctx, "enable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001514 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1515 if agent == nil {
1516 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001517 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001518 return &empty.Empty{}, agent.enablePort(ctx, port.PortNo)
kesavandbc2d1622020-01-21 00:42:01 -05001519}
1520
Kent Hagerman45a13e42020-04-13 12:23:50 -04001521func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301522 ctx = utils.WithRPCMetadataContext(ctx, "DisablePort")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001523 log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
Himani Chawlab4c25912020-11-12 17:16:38 +05301524 logger.Debugw(ctx, "disable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001525 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1526 if agent == nil {
1527 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001528 }
Kent Hagerman2a07b862020-06-19 15:23:07 -04001529 return &empty.Empty{}, agent.disablePort(ctx, port.PortNo)
kesavandbc2d1622020-01-21 00:42:01 -05001530}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001531
Kent Hagerman2b216042020-04-03 18:28:56 -04001532// ChildDeviceLost calls parent adapter to delete child device and all its references
1533func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Himani Chawlab4c25912020-11-12 17:16:38 +05301534 logger.Debugw(ctx, "child-device-lost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001535 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001536 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1537 // Just log the message and let the remaining pipeline proceed.
Rohan Agrawal31f21802020-06-12 05:38:46 +00001538 logger.Warnw(ctx, "childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001539 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001540 }
khenaidooe132f522020-03-20 15:23:15 -04001541 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1542 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001543}
onkarkundargi87285252020-01-27 11:34:52 +05301544
Kent Hagerman45a13e42020-04-13 12:23:50 -04001545func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301546 ctx = utils.WithRPCMetadataContext(ctx, "StartOmciTestAction")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001547 log.EnrichSpan(ctx, log.Fields{"device-id": request.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301548 logger.Debugw(ctx, "start-omci-test-action", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001549 agent := dMgr.getDeviceAgent(ctx, request.Id)
1550 if agent == nil {
1551 return nil, status.Errorf(codes.NotFound, "%s", request.Id)
onkarkundargi87285252020-01-27 11:34:52 +05301552 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001553 return agent.startOmciTest(ctx, request)
onkarkundargi87285252020-01-27 11:34:52 +05301554}
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001555
1556func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301557 ctx = utils.WithRPCMetadataContext(ctx, "GetExtValue")
Rohan Agrawalcf12f202020-08-03 04:42:01 +00001558 log.EnrichSpan(ctx, log.Fields{"device-id": value.Id})
Himani Chawlab4c25912020-11-12 17:16:38 +05301559 logger.Debugw(ctx, "get-ext-value", log.Fields{"onu-id": value.Id})
Kent Hagermancba2f302020-07-28 13:37:36 -04001560 cDevice, err := dMgr.getDeviceReadOnly(ctx, value.Id)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001561 if err != nil {
1562 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1563 }
Kent Hagermancba2f302020-07-28 13:37:36 -04001564 pDevice, err := dMgr.getDeviceReadOnly(ctx, cDevice.ParentId)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001565 if err != nil {
1566 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1567 }
1568 if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
1569 resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
1570 if err != nil {
1571 return nil, err
1572 }
Himani Chawlab4c25912020-11-12 17:16:38 +05301573 logger.Debugw(ctx, "get-ext-value-result", log.Fields{"result": resp})
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001574 return resp, nil
1575 }
1576 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1577
1578}
dpaul62686312020-06-23 14:17:36 +05301579
1580// SetExtValue set some given configs or value
1581func (dMgr *Manager) SetExtValue(ctx context.Context, value *voltha.ValueSet) (*empty.Empty, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +05301582 ctx = utils.WithRPCMetadataContext(ctx, "SetExtValue")
1583 logger.Debugw(ctx, "set-ext-value", log.Fields{"onu-id": value.Id})
dpaul62686312020-06-23 14:17:36 +05301584 device, err := dMgr.getDeviceReadOnly(ctx, value.Id)
1585 if err != nil {
1586 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1587 }
1588 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1589 resp, err := agent.setExtValue(ctx, device, value)
1590 if err != nil {
1591 return nil, err
1592 }
Himani Chawlab4c25912020-11-12 17:16:38 +05301593 logger.Debugw(ctx, "set-ext-value-result", log.Fields{"result": resp})
dpaul62686312020-06-23 14:17:36 +05301594 return resp, nil
1595 }
1596 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1597
1598}
Himani Chawlab4c25912020-11-12 17:16:38 +05301599
1600func (dMgr *Manager) SendRPCEvent(ctx context.Context, id string, rpcEvent *voltha.RPCEvent,
1601 category voltha.EventCategory_Types, subCategory *voltha.EventSubCategory_Types, raisedTs int64) {
1602 //TODO Instead of directly sending to the kafka bus, queue the message and send it asynchronously
Mahir Gunyelb0343bf2021-05-11 14:14:26 -07001603 dMgr.Agent.SendRPCEvent(ctx, id, rpcEvent, category, subCategory, raisedTs)
Himani Chawlab4c25912020-11-12 17:16:38 +05301604}
Manindera496f852021-02-22 09:57:56 +05301605
1606func (dMgr *Manager) GetTransientState(ctx context.Context, id string) (voltha.DeviceTransientState_Types, error) {
1607 agent := dMgr.getDeviceAgent(ctx, id)
1608 if agent == nil {
1609 return voltha.DeviceTransientState_NONE, status.Errorf(codes.NotFound, "%s", id)
1610 }
1611 return agent.getTransientState(), nil
1612}
ssiddiquif076cb82021-04-23 10:47:04 +05301613
1614func (dMgr *Manager) DownloadImageToDevice(ctx context.Context, request *voltha.DeviceImageDownloadRequest) (*voltha.DeviceImageResponse, error) {
1615 if err := dMgr.validateImageDownloadRequest(request); err != nil {
1616 return nil, err
1617 }
1618
1619 ctx = utils.WithRPCMetadataContext(ctx, "DownloadImageToDevice")
1620 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
1621
ssiddiquif076cb82021-04-23 10:47:04 +05301622 for index, deviceID := range request.DeviceId {
ssiddiqui6bd4de02021-06-08 12:04:17 +05301623 // Create download request per device
1624 downloadReq := &voltha.DeviceImageDownloadRequest{
1625 Image: request.Image,
1626 ActivateOnSuccess: request.ActivateOnSuccess,
1627 CommitOnSuccess: request.CommitOnSuccess,
1628 }
1629
ssiddiquif076cb82021-04-23 10:47:04 +05301630 //slice-out only single deviceID from the request
1631 downloadReq.DeviceId = request.DeviceId[index : index+1]
1632
1633 go func(deviceID string, req *voltha.DeviceImageDownloadRequest, ch chan []*voltha.DeviceImageState) {
1634 agent := dMgr.getDeviceAgent(ctx, deviceID)
1635 if agent == nil {
1636 logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
1637 ch <- nil
1638 return
1639 }
1640
1641 resp, err := agent.downloadImageToDevice(ctx, req)
1642 if err != nil {
1643 logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
1644 ch <- nil
1645 return
1646 }
1647
1648 err = dMgr.validateDeviceImageResponse(resp)
1649 if err != nil {
1650 logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
1651 ch <- nil
1652 return
1653 }
1654 ch <- resp.GetDeviceImageStates()
1655 }(deviceID.GetId(), downloadReq, respCh)
1656
1657 }
1658
1659 return dMgr.waitForAllResponses(ctx, "download-image-to-device", respCh, len(request.GetDeviceId()))
1660}
1661
1662func (dMgr *Manager) GetImageStatus(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
1663 if err := dMgr.validateImageRequest(request); err != nil {
1664 return nil, err
1665 }
1666
1667 ctx = utils.WithRPCMetadataContext(ctx, "GetImageStatus")
1668
ssiddiquif076cb82021-04-23 10:47:04 +05301669 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
1670 for index, deviceID := range request.DeviceId {
ssiddiqui6bd4de02021-06-08 12:04:17 +05301671 // Create status request per device
1672 imageStatusReq := &voltha.DeviceImageRequest{
1673 Version: request.Version,
1674 CommitOnSuccess: request.CommitOnSuccess,
1675 }
1676
ssiddiquif076cb82021-04-23 10:47:04 +05301677 //slice-out only single deviceID from the request
1678 imageStatusReq.DeviceId = request.DeviceId[index : index+1]
1679
1680 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
1681 agent := dMgr.getDeviceAgent(ctx, deviceID)
1682 if agent == nil {
1683 logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
1684 ch <- nil
1685 return
1686 }
1687
1688 resp, err := agent.getImageStatus(ctx, req)
1689 if err != nil {
1690 logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
1691 ch <- nil
1692 return
1693 }
1694
1695 err = dMgr.validateDeviceImageResponse(resp)
1696 if err != nil {
1697 logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
1698 ch <- nil
1699 return
1700 }
1701 ch <- resp.GetDeviceImageStates()
1702 }(deviceID.GetId(), imageStatusReq, respCh)
1703
1704 }
1705
1706 return dMgr.waitForAllResponses(ctx, "get-image-status", respCh, len(request.GetDeviceId()))
1707}
1708
1709func (dMgr *Manager) AbortImageUpgradeToDevice(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
1710 if err := dMgr.validateImageRequest(request); err != nil {
1711 return nil, err
1712 }
1713
1714 ctx = utils.WithRPCMetadataContext(ctx, "AbortImageUpgradeToDevice")
1715 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
1716
ssiddiquif076cb82021-04-23 10:47:04 +05301717 for index, deviceID := range request.DeviceId {
ssiddiqui6bd4de02021-06-08 12:04:17 +05301718 // Create abort request per device
1719 abortImageReq := &voltha.DeviceImageRequest{
1720 Version: request.Version,
1721 CommitOnSuccess: request.CommitOnSuccess,
1722 }
1723
ssiddiquif076cb82021-04-23 10:47:04 +05301724 //slice-out only single deviceID from the request
1725 abortImageReq.DeviceId = request.DeviceId[index : index+1]
1726
1727 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
1728 agent := dMgr.getDeviceAgent(ctx, deviceID)
1729 if agent == nil {
1730 logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
1731 ch <- nil
1732 return
1733 }
1734
1735 resp, err := agent.abortImageUpgradeToDevice(ctx, req)
1736 if err != nil {
1737 logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
1738 ch <- nil
1739 return
1740 }
1741
1742 err = dMgr.validateDeviceImageResponse(resp)
1743 if err != nil {
1744 logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
1745 ch <- nil
1746 return
1747 }
1748 ch <- resp.GetDeviceImageStates()
1749 }(deviceID.GetId(), abortImageReq, respCh)
1750
1751 }
1752
1753 return dMgr.waitForAllResponses(ctx, "abort-image-upgrade-to-device", respCh, len(request.GetDeviceId()))
1754}
1755
1756func (dMgr *Manager) GetOnuImages(ctx context.Context, id *common.ID) (*voltha.OnuImages, error) {
1757 if id == nil || id.Id == "" {
1758 return nil, status.Errorf(codes.InvalidArgument, "empty device id")
1759 }
1760
1761 ctx = utils.WithRPCMetadataContext(ctx, "GetOnuImages")
1762 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
1763 agent := dMgr.getDeviceAgent(ctx, id.Id)
1764 if agent == nil {
1765 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
1766 }
1767
1768 resp, err := agent.getOnuImages(ctx, id)
1769 if err != nil {
1770 return nil, err
1771 }
1772
1773 logger.Debugw(ctx, "get-onu-images-result", log.Fields{"onu-image": resp.Items})
1774
1775 return resp, nil
1776}
1777
1778func (dMgr *Manager) ActivateImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
1779 if err := dMgr.validateImageRequest(request); err != nil {
1780 return nil, err
1781 }
1782
1783 ctx = utils.WithRPCMetadataContext(ctx, "ActivateImage")
1784 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
1785
ssiddiquif076cb82021-04-23 10:47:04 +05301786 for index, deviceID := range request.DeviceId {
ssiddiqui6bd4de02021-06-08 12:04:17 +05301787 // Create activate request per device
1788 activateImageReq := &voltha.DeviceImageRequest{
1789 Version: request.Version,
1790 CommitOnSuccess: request.CommitOnSuccess,
1791 }
1792
ssiddiquif076cb82021-04-23 10:47:04 +05301793 //slice-out only single deviceID from the request
1794 activateImageReq.DeviceId = request.DeviceId[index : index+1]
1795
1796 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
1797 agent := dMgr.getDeviceAgent(ctx, deviceID)
1798 if agent == nil {
1799 logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
1800 ch <- nil
1801 return
1802 }
1803
1804 resp, err := agent.activateImageOnDevice(ctx, req)
1805 if err != nil {
1806 logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
1807 ch <- nil
1808 return
1809 }
1810
1811 err = dMgr.validateDeviceImageResponse(resp)
1812 if err != nil {
1813 logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
1814 ch <- nil
1815 return
1816 }
1817
1818 ch <- resp.GetDeviceImageStates()
1819 }(deviceID.GetId(), activateImageReq, respCh)
1820
1821 }
1822
1823 return dMgr.waitForAllResponses(ctx, "activate-image", respCh, len(request.GetDeviceId()))
1824}
1825
1826func (dMgr *Manager) CommitImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
1827 if err := dMgr.validateImageRequest(request); err != nil {
1828 return nil, err
1829 }
1830
1831 ctx = utils.WithRPCMetadataContext(ctx, "CommitImage")
1832 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
1833
ssiddiquif076cb82021-04-23 10:47:04 +05301834 for index, deviceID := range request.DeviceId {
ssiddiqui6bd4de02021-06-08 12:04:17 +05301835 // Create commit request per device
1836 commitImageReq := &voltha.DeviceImageRequest{
1837 Version: request.Version,
1838 CommitOnSuccess: request.CommitOnSuccess,
1839 }
ssiddiquif076cb82021-04-23 10:47:04 +05301840 //slice-out only single deviceID from the request
1841 commitImageReq.DeviceId = request.DeviceId[index : index+1]
1842
1843 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
1844 agent := dMgr.getDeviceAgent(ctx, deviceID)
1845 if agent == nil {
1846 logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
1847 ch <- nil
1848 return
1849 }
1850
1851 resp, err := agent.commitImage(ctx, req)
1852 if err != nil {
1853 logger.Errorw(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
1854 ch <- nil
1855 return
1856 }
1857
1858 err = dMgr.validateDeviceImageResponse(resp)
1859 if err != nil {
1860 logger.Errorf(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
1861 ch <- nil
1862 return
1863 }
1864 ch <- resp.GetDeviceImageStates()
1865 }(deviceID.GetId(), commitImageReq, respCh)
1866
1867 }
1868
1869 return dMgr.waitForAllResponses(ctx, "commit-image", respCh, len(request.GetDeviceId()))
1870}
1871
1872func (dMgr *Manager) validateImageDownloadRequest(request *voltha.DeviceImageDownloadRequest) error {
1873 if request == nil || request.Image == nil || len(request.DeviceId) == 0 {
1874 return status.Errorf(codes.InvalidArgument, "invalid argument")
1875 }
1876
1877 for _, deviceID := range request.DeviceId {
1878 if deviceID == nil {
1879 return status.Errorf(codes.InvalidArgument, "id is nil")
1880 }
1881 }
1882 return nil
1883}
1884
1885func (dMgr *Manager) validateImageRequest(request *voltha.DeviceImageRequest) error {
1886 if request == nil || len(request.DeviceId) == 0 || request.DeviceId[0] == nil {
1887 return status.Errorf(codes.InvalidArgument, "invalid argument")
1888 }
1889
1890 for _, deviceID := range request.DeviceId {
1891 if deviceID == nil {
1892 return status.Errorf(codes.InvalidArgument, "id is nil")
1893 }
1894 }
1895
1896 return nil
1897}
1898
1899func (dMgr *Manager) validateDeviceImageResponse(response *voltha.DeviceImageResponse) error {
1900 if response == nil || len(response.GetDeviceImageStates()) == 0 || response.GetDeviceImageStates()[0] == nil {
1901 return status.Errorf(codes.Internal, "invalid-response-from-adapter")
1902 }
1903
1904 return nil
1905}
1906
1907func (dMgr *Manager) waitForAllResponses(ctx context.Context, opName string, respCh chan []*voltha.DeviceImageState, expectedResps int) (*voltha.DeviceImageResponse, error) {
1908 response := &voltha.DeviceImageResponse{}
1909 respCount := 0
1910 for {
1911 select {
1912 case resp, ok := <-respCh:
1913 if !ok {
1914 logger.Errorw(ctx, opName+"-failed", log.Fields{"error": "channel-closed"})
1915 return response, status.Errorf(codes.Aborted, "channel-closed")
1916 }
1917
1918 if resp != nil {
1919 logger.Debugw(ctx, opName+"-result", log.Fields{"image-state": resp[0].GetImageState(), "device-id": resp[0].GetDeviceId()})
1920 response.DeviceImageStates = append(response.DeviceImageStates, resp...)
1921 }
1922
1923 respCount++
1924
1925 //check whether all responses received, if so, sent back the collated response
1926 if respCount == expectedResps {
1927 return response, nil
1928 }
1929 continue
1930 case <-ctx.Done():
1931 return nil, status.Errorf(codes.Aborted, opName+"-failed-%s", ctx.Err())
1932 }
1933 }
1934}
Maninder0aabf0c2021-03-17 14:55:14 +05301935
1936func (dMgr *Manager) ReconcilingCleanup(ctx context.Context, device *voltha.Device) error {
1937 agent := dMgr.getDeviceAgent(ctx, device.Id)
1938 if agent == nil {
1939 logger.Errorf(ctx, "Not able to get device agent.")
1940 return status.Errorf(codes.NotFound, "Not able to get device agent for device : %s", device.Id)
1941 }
1942 err := agent.reconcilingCleanup(ctx)
1943 if err != nil {
1944 logger.Errorf(ctx, err.Error())
1945 return status.Errorf(codes.Internal, err.Error())
1946 }
1947 return nil
1948}