blob: f5a6cac24cef3d69051205e3d08fdcfc9c236ddf [file] [log] [blame]
khenaidoo21d51152019-02-01 13:48:37 -05001/*
2 * Copyright 2019-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 adapter
khenaidoo21d51152019-02-01 13:48:37 -050018
19import (
20 "context"
khenaidood948f772021-08-11 17:49:24 -040021 "errors"
khenaidoo21d51152019-02-01 13:48:37 -050022 "fmt"
npujar1d86a522019-11-14 17:11:16 +053023 "sync"
Kent Hagerman16ce36a2019-12-17 13:40:53 -050024 "time"
npujar1d86a522019-11-14 17:11:16 +053025
khenaidood948f772021-08-11 17:49:24 -040026 "github.com/opencord/voltha-lib-go/v7/pkg/db"
27 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo9beaaf12021-10-19 17:32:01 -040028 "github.com/opencord/voltha-protos/v5/go/adapter_service"
khenaidood948f772021-08-11 17:49:24 -040029 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoo9beaaf12021-10-19 17:32:01 -040030 "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidood948f772021-08-11 17:49:24 -040031
khenaidoo21d51152019-02-01 13:48:37 -050032 "github.com/gogo/protobuf/proto"
Kent Hagerman45a13e42020-04-13 12:23:50 -040033 "github.com/golang/protobuf/ptypes/empty"
sbarbari17d7e222019-11-05 10:02:29 -050034 "github.com/opencord/voltha-go/db/model"
khenaidood948f772021-08-11 17:49:24 -040035 "github.com/opencord/voltha-lib-go/v7/pkg/log"
36 "github.com/opencord/voltha-lib-go/v7/pkg/probe"
37 "github.com/opencord/voltha-protos/v5/go/voltha"
Kent Hagerman45a13e42020-04-13 12:23:50 -040038 "google.golang.org/grpc/codes"
39 "google.golang.org/grpc/status"
khenaidoo21d51152019-02-01 13:48:37 -050040)
41
Kent Hagerman2b216042020-04-03 18:28:56 -040042// Manager represents adapter manager attributes
43type Manager struct {
khenaidood948f772021-08-11 17:49:24 -040044 adapterAgents map[string]*agent
45 adapterEndpoints map[Endpoint]*agent
46 deviceTypes map[string]*voltha.DeviceType
47 adapterDbProxy *model.Proxy
48 deviceTypeDbProxy *model.Proxy
49 onAdapterRestart vgrpc.RestartedHandler
50 endpointMgr EndpointManager
51 lockAdapterAgentsMap sync.RWMutex
52 lockDeviceTypesMap sync.RWMutex
53 lockAdapterEndPointsMap sync.RWMutex
54 liveProbeInterval time.Duration
khenaidoo25057da2021-12-08 14:40:45 -050055 coreEndpoint string
khenaidoo21d51152019-02-01 13:48:37 -050056}
57
khenaidood948f772021-08-11 17:49:24 -040058// SetAdapterRestartedCallback is used to set the callback that needs to be invoked on an adapter restart
59func (aMgr *Manager) SetAdapterRestartedCallback(onAdapterRestart vgrpc.RestartedHandler) {
Kent Hagerman2b216042020-04-03 18:28:56 -040060 aMgr.onAdapterRestart = onAdapterRestart
61}
62
khenaidood948f772021-08-11 17:49:24 -040063func NewAdapterManager(
khenaidoo25057da2021-12-08 14:40:45 -050064 coreEndpoint string,
khenaidood948f772021-08-11 17:49:24 -040065 dbPath *model.Path,
66 coreInstanceID string,
67 backend *db.Backend,
68 liveProbeInterval time.Duration,
69) *Manager {
70 return &Manager{
71 adapterDbProxy: dbPath.Proxy("adapters"),
72 deviceTypeDbProxy: dbPath.Proxy("device_types"),
73 deviceTypes: make(map[string]*voltha.DeviceType),
74 adapterAgents: make(map[string]*agent),
75 adapterEndpoints: make(map[Endpoint]*agent),
76 endpointMgr: NewEndpointManager(backend),
77 liveProbeInterval: liveProbeInterval,
khenaidoo25057da2021-12-08 14:40:45 -050078 coreEndpoint: coreEndpoint,
khenaidood948f772021-08-11 17:49:24 -040079 }
80}
81
82func (aMgr *Manager) Start(ctx context.Context, serviceName string) {
83 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusPreparing)
84 logger.Infow(ctx, "starting-service", log.Fields{"service": serviceName})
khenaidoo21d51152019-02-01 13:48:37 -050085
86 // Load the existing adapterAgents and device types - this will also ensure the correct paths have been
87 // created if there are no data in the dB to start
Rohan Agrawal31f21802020-06-12 05:38:46 +000088 err := aMgr.loadAdaptersAndDevicetypesInMemory(ctx)
Thomas Lee Se5a44012019-11-07 20:32:24 +053089 if err != nil {
khenaidood948f772021-08-11 17:49:24 -040090 logger.Fatalw(ctx, "failed-to-load-adapters-and-device-types-in-memory", log.Fields{"service": serviceName, "error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +053091 }
khenaidoo21d51152019-02-01 13:48:37 -050092
khenaidood948f772021-08-11 17:49:24 -040093 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusRunning)
94 logger.Infow(ctx, "service-started", log.Fields{"service": serviceName})
khenaidoo21d51152019-02-01 13:48:37 -050095}
96
khenaidood948f772021-08-11 17:49:24 -040097func (aMgr *Manager) Stop(ctx context.Context) {
98 // Stop all adapters
99 aMgr.lockAdapterAgentsMap.RLock()
100 defer aMgr.lockAdapterAgentsMap.RUnlock()
khenaidooa46458b2021-12-15 16:50:44 -0500101 var wg sync.WaitGroup
khenaidood948f772021-08-11 17:49:24 -0400102 for _, adapterAgent := range aMgr.adapterAgents {
khenaidooa46458b2021-12-15 16:50:44 -0500103 // Run the agent stop in its own go routine to notify to the
104 // adapters that the Core is no longer a client
105 wg.Add(1)
106 go func(agt *agent) {
107 agt.stop(ctx)
108 wg.Done()
109 }(adapterAgent)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530110 }
khenaidooa46458b2021-12-15 16:50:44 -0500111 // Wait for all tests to complete
112 wg.Wait()
khenaidoo21d51152019-02-01 13:48:37 -0500113}
114
khenaidood948f772021-08-11 17:49:24 -0400115func (aMgr *Manager) GetAdapterEndpoint(ctx context.Context, deviceID string, deviceType string) (string, error) {
116 endPoint, err := aMgr.endpointMgr.GetEndpoint(ctx, deviceID, deviceType)
117 if err != nil {
118 return "", err
119 }
120 return string(endPoint), nil
121}
122
123func (aMgr *Manager) GetAdapterWithEndpoint(ctx context.Context, endPoint string) (*voltha.Adapter, error) {
124 aMgr.lockAdapterEndPointsMap.RLock()
125 agent, have := aMgr.adapterEndpoints[Endpoint(endPoint)]
126 aMgr.lockAdapterEndPointsMap.RUnlock()
Kent Hagerman16ce36a2019-12-17 13:40:53 -0500127
128 if have {
khenaidood948f772021-08-11 17:49:24 -0400129 return agent.getAdapter(ctx), nil
Kent Hagerman16ce36a2019-12-17 13:40:53 -0500130 }
khenaidood948f772021-08-11 17:49:24 -0400131
132 return nil, errors.New("Not found")
133}
134
135func (aMgr *Manager) GetAdapterNameWithEndpoint(ctx context.Context, endPoint string) (string, error) {
136 aMgr.lockAdapterEndPointsMap.RLock()
137 agent, have := aMgr.adapterEndpoints[Endpoint(endPoint)]
138 aMgr.lockAdapterEndPointsMap.RUnlock()
139
140 if have {
141 return agent.adapter.Id, nil
142 }
143
144 return "", errors.New("Not found")
145}
146
khenaidoo9beaaf12021-10-19 17:32:01 -0400147func (aMgr *Manager) GetAdapterClient(_ context.Context, endpoint string) (adapter_service.AdapterServiceClient, error) {
khenaidood948f772021-08-11 17:49:24 -0400148 if endpoint == "" {
149 return nil, errors.New("endpoint-cannot-be-empty")
150 }
151 aMgr.lockAdapterEndPointsMap.RLock()
152 defer aMgr.lockAdapterEndPointsMap.RUnlock()
153
154 if agent, have := aMgr.adapterEndpoints[Endpoint(endpoint)]; have {
155 return agent.getClient()
156 }
157
158 return nil, fmt.Errorf("Endpoint-not-found-%s", endpoint)
Kent Hagerman16ce36a2019-12-17 13:40:53 -0500159}
160
Rohan Agrawal31f21802020-06-12 05:38:46 +0000161func (aMgr *Manager) addAdapter(ctx context.Context, adapter *voltha.Adapter, saveToDb bool) error {
khenaidood948f772021-08-11 17:49:24 -0400162 aMgr.lockAdapterAgentsMap.Lock()
163 aMgr.lockAdapterEndPointsMap.Lock()
164 defer aMgr.lockAdapterEndPointsMap.Unlock()
165 defer aMgr.lockAdapterAgentsMap.Unlock()
Rohan Agrawal31f21802020-06-12 05:38:46 +0000166 logger.Debugw(ctx, "adding-adapter", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
Matteo Scandolod525ae32020-04-02 17:27:29 -0700167 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidoo21d51152019-02-01 13:48:37 -0500168 if _, exist := aMgr.adapterAgents[adapter.Id]; !exist {
khenaidoo21d51152019-02-01 13:48:37 -0500169 if saveToDb {
170 // Save the adapter to the KV store - first check if it already exist
khenaidood948f772021-08-11 17:49:24 -0400171 if have, err := aMgr.adapterDbProxy.Get(log.WithSpanFromContext(context.Background(), ctx), adapter.Id, &voltha.Adapter{}); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000172 logger.Errorw(ctx, "failed-to-get-adapters-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530173 return err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400174 } else if !have {
khenaidood948f772021-08-11 17:49:24 -0400175 if err := aMgr.adapterDbProxy.Set(log.WithSpanFromContext(context.Background(), ctx), adapter.Id, adapter); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000176 logger.Errorw(ctx, "failed-to-save-adapter", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
Matteo Scandolod525ae32020-04-02 17:27:29 -0700177 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint, "replica": adapter.CurrentReplica, "total": adapter.TotalReplicas})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530178 return err
179 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000180 logger.Debugw(ctx, "adapter-saved-to-KV-Store", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
Matteo Scandolod525ae32020-04-02 17:27:29 -0700181 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint, "replica": adapter.CurrentReplica, "total": adapter.TotalReplicas})
182 } else {
Girish Kumar3e8ee212020-08-19 17:50:11 +0000183 logger.Warnw(ctx, "adding-adapter-already-in-KV-store", log.Fields{
Matteo Scandolod525ae32020-04-02 17:27:29 -0700184 "adapterName": adapter.Id,
185 "adapterReplica": adapter.CurrentReplica,
186 })
khenaidoo21d51152019-02-01 13:48:37 -0500187 }
188 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500189 clonedAdapter := (proto.Clone(adapter)).(*voltha.Adapter)
khenaidood948f772021-08-11 17:49:24 -0400190 // Use a muted adapter restart handler which is invoked by the corresponding gRPC client on an adapter restart.
191 // This handler just log the restart event. The actual action taken following an adapter restart
192 // will be done when an adapter re-registers itself.
khenaidoo25057da2021-12-08 14:40:45 -0500193 aMgr.adapterAgents[adapter.Id] = newAdapterAgent(aMgr.coreEndpoint, clonedAdapter, aMgr.mutedAdapterRestartedHandler, aMgr.liveProbeInterval)
khenaidood948f772021-08-11 17:49:24 -0400194 aMgr.adapterEndpoints[Endpoint(adapter.Endpoint)] = aMgr.adapterAgents[adapter.Id]
khenaidoo21d51152019-02-01 13:48:37 -0500195 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530196 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500197}
198
Rohan Agrawal31f21802020-06-12 05:38:46 +0000199func (aMgr *Manager) addDeviceTypes(ctx context.Context, deviceTypes *voltha.DeviceTypes, saveToDb bool) error {
khenaidoo21d51152019-02-01 13:48:37 -0500200 if deviceTypes == nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530201 return fmt.Errorf("no-device-type")
khenaidoo21d51152019-02-01 13:48:37 -0500202 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000203 logger.Debugw(ctx, "adding-device-types", log.Fields{"deviceTypes": deviceTypes})
khenaidood948f772021-08-11 17:49:24 -0400204 aMgr.lockAdapterAgentsMap.Lock()
205 defer aMgr.lockAdapterAgentsMap.Unlock()
206 aMgr.lockDeviceTypesMap.Lock()
207 defer aMgr.lockDeviceTypesMap.Unlock()
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500208
Matteo Scandolod525ae32020-04-02 17:27:29 -0700209 // create an in memory map to fetch the entire voltha.DeviceType from a device.Type string
210 for _, deviceType := range deviceTypes.Items {
211 aMgr.deviceTypes[deviceType.Id] = deviceType
212 }
213
khenaidoo21d51152019-02-01 13:48:37 -0500214 if saveToDb {
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500215 // Save the device types to the KV store
khenaidoo21d51152019-02-01 13:48:37 -0500216 for _, deviceType := range deviceTypes.Items {
khenaidood948f772021-08-11 17:49:24 -0400217 if have, err := aMgr.deviceTypeDbProxy.Get(log.WithSpanFromContext(context.Background(), ctx), deviceType.Id, &voltha.DeviceType{}); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000218 logger.Errorw(ctx, "Failed-to--device-types-from-cluster-data-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530219 return err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400220 } else if !have {
khenaidoo21d51152019-02-01 13:48:37 -0500221 // Does not exist - save it
222 clonedDType := (proto.Clone(deviceType)).(*voltha.DeviceType)
khenaidood948f772021-08-11 17:49:24 -0400223 if err := aMgr.deviceTypeDbProxy.Set(log.WithSpanFromContext(context.Background(), ctx), deviceType.Id, clonedDType); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000224 logger.Errorw(ctx, "Failed-to-add-device-types-to-cluster-data-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530225 return err
226 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000227 logger.Debugw(ctx, "device-type-saved-to-KV-Store", log.Fields{"deviceType": deviceType})
khenaidoo21d51152019-02-01 13:48:37 -0500228 }
229 }
230 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530231 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500232}
233
khenaidood948f772021-08-11 17:49:24 -0400234//loadAdaptersAndDevicetypesInMemory loads the existing set of adapters and device types in memory
235func (aMgr *Manager) loadAdaptersAndDevicetypesInMemory(ctx context.Context) error {
236 // Load the adapters
237 var adapters []*voltha.Adapter
238 if err := aMgr.adapterDbProxy.List(log.WithSpanFromContext(context.Background(), ctx), &adapters); err != nil {
239 logger.Errorw(ctx, "Failed-to-list-adapters-from-cluster-data-proxy", log.Fields{"error": err})
240 return err
241 }
242
243 logger.Debugw(ctx, "retrieved-adapters", log.Fields{"count": len(adapters)})
244
245 if len(adapters) != 0 {
246 for _, adapter := range adapters {
247 if err := aMgr.addAdapter(ctx, adapter, false); err != nil {
248 logger.Errorw(ctx, "failed-to-add-adapter", log.Fields{"adapterId": adapter.Id})
249 } else {
250 logger.Debugw(ctx, "adapter-added-successfully", log.Fields{"adapterId": adapter.Id})
251 }
khenaidoo21d51152019-02-01 13:48:37 -0500252 }
253 }
khenaidoo21d51152019-02-01 13:48:37 -0500254
khenaidood948f772021-08-11 17:49:24 -0400255 // Load the device types
256 var deviceTypes []*voltha.DeviceType
257 if err := aMgr.deviceTypeDbProxy.List(log.WithSpanFromContext(context.Background(), ctx), &deviceTypes); err != nil {
258 logger.Errorw(ctx, "Failed-to-list-device-types-from-cluster-data-proxy", log.Fields{"error": err})
259 return err
khenaidoo21d51152019-02-01 13:48:37 -0500260 }
khenaidood948f772021-08-11 17:49:24 -0400261
262 logger.Debugw(ctx, "retrieved-devicetypes", log.Fields{"count": len(deviceTypes)})
263
264 if len(deviceTypes) != 0 {
265 dTypes := &voltha.DeviceTypes{Items: []*voltha.DeviceType{}}
266 for _, dType := range deviceTypes {
267 logger.Debugw(ctx, "found-existing-device-types", log.Fields{"deviceTypes": deviceTypes})
268 dTypes.Items = append(dTypes.Items, dType)
269 }
270 if err := aMgr.addDeviceTypes(ctx, dTypes, false); err != nil {
271 logger.Errorw(ctx, "failed-to-add-device-type", log.Fields{"deviceTypes": deviceTypes})
272 } else {
273 logger.Debugw(ctx, "device-type-added-successfully", log.Fields{"deviceTypes": deviceTypes})
274 }
275 }
276
277 // Start the adapter agents - this will trigger the connection to the adapter
278 aMgr.lockAdapterAgentsMap.RLock()
279 defer aMgr.lockAdapterAgentsMap.RUnlock()
280 for _, adapterAgent := range aMgr.adapterAgents {
281 subCtx := log.WithSpanFromContext(context.Background(), ctx)
282 if err := adapterAgent.start(subCtx); err != nil {
283 logger.Errorw(ctx, "failed-to-start-adapter", log.Fields{"adapter-endpoint": adapterAgent.adapterAPIEndPoint})
284 }
285 }
286
287 logger.Debug(ctx, "no-existing-device-type-found")
288
khenaidoo21d51152019-02-01 13:48:37 -0500289 return nil
290}
291
khenaidoo9beaaf12021-10-19 17:32:01 -0400292func (aMgr *Manager) RegisterAdapter(ctx context.Context, registration *core_adapter.AdapterRegistration) (*empty.Empty, error) {
khenaidood948f772021-08-11 17:49:24 -0400293 adapter := registration.Adapter
294 deviceTypes := registration.DTypes
295 logger.Infow(ctx, "RegisterAdapter", log.Fields{"adapter": adapter, "deviceTypes": deviceTypes.Items})
khenaidoo21d51152019-02-01 13:48:37 -0500296
Matteo Scandolo57ee9aa2020-04-17 09:20:42 -0700297 if adapter.Type == "" {
Girish Kumar3e8ee212020-08-19 17:50:11 +0000298 logger.Errorw(ctx, "adapter-not-specifying-type", log.Fields{
Matteo Scandolo57ee9aa2020-04-17 09:20:42 -0700299 "adapterId": adapter.Id,
300 "vendor": adapter.Vendor,
301 "type": adapter.Type,
302 })
303 return nil, status.Error(codes.InvalidArgument, "adapter-not-specifying-type")
304 }
305
khenaidood948f772021-08-11 17:49:24 -0400306 if adpt, _ := aMgr.getAdapter(ctx, adapter.Id); adpt != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400307 // Already registered - Adapter may have restarted. Trigger the reconcile process for that adapter
khenaidood948f772021-08-11 17:49:24 -0400308 logger.Warnw(ctx, "adapter-restarted", log.Fields{"adapter": adpt.Id, "endpoint": adpt.Endpoint})
309
310 // First reset the adapter connection
311 agt, err := aMgr.getAgent(ctx, adpt.Id)
312 if err != nil {
313 logger.Errorw(ctx, "no-adapter-agent", log.Fields{"error": err})
314 return nil, err
315 }
316 agt.resetConnection(ctx)
317
npujar1d86a522019-11-14 17:11:16 +0530318 go func() {
khenaidood948f772021-08-11 17:49:24 -0400319 err := aMgr.onAdapterRestart(log.WithSpanFromContext(context.Background(), ctx), adpt.Endpoint)
npujar1d86a522019-11-14 17:11:16 +0530320 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000321 logger.Errorw(ctx, "unable-to-restart-adapter", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530322 }
323 }()
khenaidood948f772021-08-11 17:49:24 -0400324 return &empty.Empty{}, nil
khenaidoo21d51152019-02-01 13:48:37 -0500325 }
326 // Save the adapter and the device types
Rohan Agrawal31f21802020-06-12 05:38:46 +0000327 if err := aMgr.addAdapter(ctx, adapter, true); err != nil {
328 logger.Errorw(ctx, "failed-to-add-adapter", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530329 return nil, err
330 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000331 if err := aMgr.addDeviceTypes(ctx, deviceTypes, true); err != nil {
332 logger.Errorw(ctx, "failed-to-add-device-types", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530333 return nil, err
334 }
khenaidoo21d51152019-02-01 13:48:37 -0500335
Rohan Agrawal31f21802020-06-12 05:38:46 +0000336 logger.Debugw(ctx, "adapter-registered", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
Matteo Scandolod525ae32020-04-02 17:27:29 -0700337 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidoo21d51152019-02-01 13:48:37 -0500338
khenaidood948f772021-08-11 17:49:24 -0400339 // Setup the endpoints for this adapter
340 if err := aMgr.endpointMgr.RegisterAdapter(ctx, adapter, deviceTypes); err != nil {
341 logger.Errorw(ctx, "failed-to-register-adapter", log.Fields{"error": err})
342 }
343
344 // Start adapter instance - this will trigger the connection to the adapter
345 if agent, err := aMgr.getAgent(ctx, adapter.Id); agent != nil {
346 subCtx := log.WithSpanFromContext(context.Background(), ctx)
347 if err := agent.start(subCtx); err != nil {
348 logger.Errorw(ctx, "failed-to-start-adapter", log.Fields{"error": err})
349 return nil, err
350 }
351 } else {
352 logger.Fatalw(ctx, "adapter-absent", log.Fields{"error": err, "adapter": adapter.Id})
353 }
354
355 return &empty.Empty{}, nil
khenaidoo21d51152019-02-01 13:48:37 -0500356}
357
khenaidood948f772021-08-11 17:49:24 -0400358func (aMgr *Manager) GetAdapterTypeByVendorID(vendorID string) (string, error) {
359 aMgr.lockDeviceTypesMap.RLock()
360 defer aMgr.lockDeviceTypesMap.RUnlock()
361 for _, dType := range aMgr.deviceTypes {
362 for _, v := range dType.VendorIds {
363 if v == vendorID {
364 return dType.AdapterType, nil
365 }
366 }
367 }
368 return "", fmt.Errorf("vendor id %s not found", vendorID)
369}
370
371// GetAdapterType returns the name of the device adapter that services this device type
Kent Hagerman2b216042020-04-03 18:28:56 -0400372func (aMgr *Manager) GetAdapterType(deviceType string) (string, error) {
khenaidood948f772021-08-11 17:49:24 -0400373 aMgr.lockDeviceTypesMap.Lock()
374 defer aMgr.lockDeviceTypesMap.Unlock()
375 for _, dt := range aMgr.deviceTypes {
376 if deviceType == dt.Id {
377 return dt.AdapterType, nil
Matteo Scandolod525ae32020-04-02 17:27:29 -0700378 }
khenaidoo21d51152019-02-01 13:48:37 -0500379 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400380 return "", fmt.Errorf("adapter-not-registered-for-device-type %s", deviceType)
khenaidoo21d51152019-02-01 13:48:37 -0500381}
382
Kent Hagerman45a13e42020-04-13 12:23:50 -0400383// ListDeviceTypes returns all the device types known to the system
Rohan Agrawal31f21802020-06-12 05:38:46 +0000384func (aMgr *Manager) ListDeviceTypes(ctx context.Context, _ *empty.Empty) (*voltha.DeviceTypes, error) {
385 logger.Debug(ctx, "ListDeviceTypes")
khenaidood948f772021-08-11 17:49:24 -0400386 aMgr.lockDeviceTypesMap.Lock()
387 defer aMgr.lockDeviceTypesMap.Unlock()
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500388
Matteo Scandolod525ae32020-04-02 17:27:29 -0700389 deviceTypes := make([]*voltha.DeviceType, 0, len(aMgr.deviceTypes))
Matteo Scandolod525ae32020-04-02 17:27:29 -0700390 for _, deviceType := range aMgr.deviceTypes {
391 deviceTypes = append(deviceTypes, deviceType)
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500392 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400393 return &voltha.DeviceTypes{Items: deviceTypes}, nil
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500394}
395
Kent Hagerman45a13e42020-04-13 12:23:50 -0400396// GetDeviceType returns the device type proto definition given the name of the device type
khenaidood948f772021-08-11 17:49:24 -0400397func (aMgr *Manager) GetDeviceType(ctx context.Context, deviceType *common.ID) (*voltha.DeviceType, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000398 logger.Debugw(ctx, "GetDeviceType", log.Fields{"typeid": deviceType.Id})
khenaidood948f772021-08-11 17:49:24 -0400399 aMgr.lockDeviceTypesMap.Lock()
400 defer aMgr.lockDeviceTypesMap.Unlock()
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500401
Kent Hagerman45a13e42020-04-13 12:23:50 -0400402 dType, exist := aMgr.deviceTypes[deviceType.Id]
403 if !exist {
404 return nil, status.Errorf(codes.NotFound, "device_type-%s", deviceType.Id)
khenaidoo21d51152019-02-01 13:48:37 -0500405 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400406 return dType, nil
khenaidoo21d51152019-02-01 13:48:37 -0500407}
khenaidood948f772021-08-11 17:49:24 -0400408
409// ListAdapters returns the contents of all adapters known to the system
410func (aMgr *Manager) ListAdapters(ctx context.Context, _ *empty.Empty) (*voltha.Adapters, error) {
411 logger.Debug(ctx, "Listing adapters")
412 result := &voltha.Adapters{Items: []*voltha.Adapter{}}
413 aMgr.lockAdapterAgentsMap.RLock()
414 defer aMgr.lockAdapterAgentsMap.RUnlock()
415 for _, adapterAgent := range aMgr.adapterAgents {
416 if a := adapterAgent.getAdapter(ctx); a != nil {
417 result.Items = append(result.Items, (proto.Clone(a)).(*voltha.Adapter))
418 }
419 }
420 logger.Debugw(ctx, "Listing adapters", log.Fields{"result": result})
421 return result, nil
422}
423
424func (aMgr *Manager) getAgent(ctx context.Context, adapterID string) (*agent, error) {
425 aMgr.lockAdapterAgentsMap.RLock()
426 defer aMgr.lockAdapterAgentsMap.RUnlock()
427 if adapterAgent, ok := aMgr.adapterAgents[adapterID]; ok {
428 return adapterAgent, nil
429 }
430 return nil, errors.New("Not found")
431}
432
433func (aMgr *Manager) getAdapter(ctx context.Context, adapterID string) (*voltha.Adapter, error) {
434 aMgr.lockAdapterAgentsMap.RLock()
435 defer aMgr.lockAdapterAgentsMap.RUnlock()
436 if adapterAgent, ok := aMgr.adapterAgents[adapterID]; ok {
437 return adapterAgent.getAdapter(ctx), nil
438 }
439 return nil, errors.New("Not found")
440}
441
442// mutedAdapterRestartedHandler will be invoked by the grpc client on an adapter restart.
443// Since the Adapter will re-register itself and that will trigger the reconcile process,
444// therefore this handler does nothing, other than logging the event.
445func (aMgr *Manager) mutedAdapterRestartedHandler(ctx context.Context, endpoint string) error {
446 logger.Infow(ctx, "muted-adapter-restarted", log.Fields{"endpoint": endpoint})
447 return nil
448}
449
450func (aMgr *Manager) WaitUntilConnectionsToAdaptersAreUp(ctx context.Context, connectionRetryInterval time.Duration) error {
451 logger.Infow(ctx, "waiting-for-adapters-to-be-up", log.Fields{"retry-interval": connectionRetryInterval})
452 for {
453 aMgr.lockAdapterAgentsMap.Lock()
454 numAdapters := len(aMgr.adapterAgents)
455 if numAdapters == 0 {
456 // No adapter registered yet
457 aMgr.lockAdapterAgentsMap.Unlock()
458 logger.Info(ctx, "no-adapter-registered")
459 return nil
460 }
461 // A case of Core restart
462 agentsUp := true
463 adapterloop:
464 for _, agt := range aMgr.adapterAgents {
465 agentsUp = agentsUp && agt.IsConnectionUp()
466 if !agentsUp {
467 break adapterloop
468 }
469 }
470 aMgr.lockAdapterAgentsMap.Unlock()
471 if agentsUp {
472 logger.Infow(ctx, "adapter-connections-ready", log.Fields{"adapter-count": numAdapters})
473 return nil
474 }
475 logger.Warnw(ctx, "adapter-connections-not-ready", log.Fields{"adapter-count": numAdapters})
476 select {
477 case <-time.After(connectionRetryInterval):
478 logger.Infow(ctx, "retrying-adapter-connections", log.Fields{"adapter-count": numAdapters})
479 continue
480 case <-ctx.Done():
481 logger.Errorw(ctx, "context-timeout", log.Fields{"adapter-count": numAdapters, "err": ctx.Err()})
482 return ctx.Err()
483 }
484 }
485}