blob: 790a670d7e2c105eb98a51c91ee72a301ba38f66 [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
khenaidoo21d51152019-02-01 13:48:37 -050055}
56
khenaidood948f772021-08-11 17:49:24 -040057// SetAdapterRestartedCallback is used to set the callback that needs to be invoked on an adapter restart
58func (aMgr *Manager) SetAdapterRestartedCallback(onAdapterRestart vgrpc.RestartedHandler) {
Kent Hagerman2b216042020-04-03 18:28:56 -040059 aMgr.onAdapterRestart = onAdapterRestart
60}
61
khenaidood948f772021-08-11 17:49:24 -040062func NewAdapterManager(
63 dbPath *model.Path,
64 coreInstanceID string,
65 backend *db.Backend,
66 liveProbeInterval time.Duration,
67) *Manager {
68 return &Manager{
69 adapterDbProxy: dbPath.Proxy("adapters"),
70 deviceTypeDbProxy: dbPath.Proxy("device_types"),
71 deviceTypes: make(map[string]*voltha.DeviceType),
72 adapterAgents: make(map[string]*agent),
73 adapterEndpoints: make(map[Endpoint]*agent),
74 endpointMgr: NewEndpointManager(backend),
75 liveProbeInterval: liveProbeInterval,
76 }
77}
78
79func (aMgr *Manager) Start(ctx context.Context, serviceName string) {
80 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusPreparing)
81 logger.Infow(ctx, "starting-service", log.Fields{"service": serviceName})
khenaidoo21d51152019-02-01 13:48:37 -050082
83 // Load the existing adapterAgents and device types - this will also ensure the correct paths have been
84 // created if there are no data in the dB to start
Rohan Agrawal31f21802020-06-12 05:38:46 +000085 err := aMgr.loadAdaptersAndDevicetypesInMemory(ctx)
Thomas Lee Se5a44012019-11-07 20:32:24 +053086 if err != nil {
khenaidood948f772021-08-11 17:49:24 -040087 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 +053088 }
khenaidoo21d51152019-02-01 13:48:37 -050089
khenaidood948f772021-08-11 17:49:24 -040090 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusRunning)
91 logger.Infow(ctx, "service-started", log.Fields{"service": serviceName})
khenaidoo21d51152019-02-01 13:48:37 -050092}
93
khenaidood948f772021-08-11 17:49:24 -040094func (aMgr *Manager) Stop(ctx context.Context) {
95 // Stop all adapters
96 aMgr.lockAdapterAgentsMap.RLock()
97 defer aMgr.lockAdapterAgentsMap.RUnlock()
98 for _, adapterAgent := range aMgr.adapterAgents {
99 adapterAgent.stop(ctx)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530100 }
khenaidoo21d51152019-02-01 13:48:37 -0500101}
102
khenaidood948f772021-08-11 17:49:24 -0400103func (aMgr *Manager) GetAdapterEndpoint(ctx context.Context, deviceID string, deviceType string) (string, error) {
104 endPoint, err := aMgr.endpointMgr.GetEndpoint(ctx, deviceID, deviceType)
105 if err != nil {
106 return "", err
107 }
108 return string(endPoint), nil
109}
110
111func (aMgr *Manager) GetAdapterWithEndpoint(ctx context.Context, endPoint string) (*voltha.Adapter, error) {
112 aMgr.lockAdapterEndPointsMap.RLock()
113 agent, have := aMgr.adapterEndpoints[Endpoint(endPoint)]
114 aMgr.lockAdapterEndPointsMap.RUnlock()
Kent Hagerman16ce36a2019-12-17 13:40:53 -0500115
116 if have {
khenaidood948f772021-08-11 17:49:24 -0400117 return agent.getAdapter(ctx), nil
Kent Hagerman16ce36a2019-12-17 13:40:53 -0500118 }
khenaidood948f772021-08-11 17:49:24 -0400119
120 return nil, errors.New("Not found")
121}
122
123func (aMgr *Manager) GetAdapterNameWithEndpoint(ctx context.Context, endPoint string) (string, error) {
124 aMgr.lockAdapterEndPointsMap.RLock()
125 agent, have := aMgr.adapterEndpoints[Endpoint(endPoint)]
126 aMgr.lockAdapterEndPointsMap.RUnlock()
127
128 if have {
129 return agent.adapter.Id, nil
130 }
131
132 return "", errors.New("Not found")
133}
134
khenaidoo9beaaf12021-10-19 17:32:01 -0400135func (aMgr *Manager) GetAdapterClient(_ context.Context, endpoint string) (adapter_service.AdapterServiceClient, error) {
khenaidood948f772021-08-11 17:49:24 -0400136 if endpoint == "" {
137 return nil, errors.New("endpoint-cannot-be-empty")
138 }
139 aMgr.lockAdapterEndPointsMap.RLock()
140 defer aMgr.lockAdapterEndPointsMap.RUnlock()
141
142 if agent, have := aMgr.adapterEndpoints[Endpoint(endpoint)]; have {
143 return agent.getClient()
144 }
145
146 return nil, fmt.Errorf("Endpoint-not-found-%s", endpoint)
Kent Hagerman16ce36a2019-12-17 13:40:53 -0500147}
148
Rohan Agrawal31f21802020-06-12 05:38:46 +0000149func (aMgr *Manager) addAdapter(ctx context.Context, adapter *voltha.Adapter, saveToDb bool) error {
khenaidood948f772021-08-11 17:49:24 -0400150 aMgr.lockAdapterAgentsMap.Lock()
151 aMgr.lockAdapterEndPointsMap.Lock()
152 defer aMgr.lockAdapterEndPointsMap.Unlock()
153 defer aMgr.lockAdapterAgentsMap.Unlock()
Rohan Agrawal31f21802020-06-12 05:38:46 +0000154 logger.Debugw(ctx, "adding-adapter", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
Matteo Scandolod525ae32020-04-02 17:27:29 -0700155 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidoo21d51152019-02-01 13:48:37 -0500156 if _, exist := aMgr.adapterAgents[adapter.Id]; !exist {
khenaidoo21d51152019-02-01 13:48:37 -0500157 if saveToDb {
158 // Save the adapter to the KV store - first check if it already exist
khenaidood948f772021-08-11 17:49:24 -0400159 if have, err := aMgr.adapterDbProxy.Get(log.WithSpanFromContext(context.Background(), ctx), adapter.Id, &voltha.Adapter{}); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000160 logger.Errorw(ctx, "failed-to-get-adapters-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530161 return err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400162 } else if !have {
khenaidood948f772021-08-11 17:49:24 -0400163 if err := aMgr.adapterDbProxy.Set(log.WithSpanFromContext(context.Background(), ctx), adapter.Id, adapter); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000164 logger.Errorw(ctx, "failed-to-save-adapter", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
Matteo Scandolod525ae32020-04-02 17:27:29 -0700165 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint, "replica": adapter.CurrentReplica, "total": adapter.TotalReplicas})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530166 return err
167 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000168 logger.Debugw(ctx, "adapter-saved-to-KV-Store", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
Matteo Scandolod525ae32020-04-02 17:27:29 -0700169 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint, "replica": adapter.CurrentReplica, "total": adapter.TotalReplicas})
170 } else {
Girish Kumar3e8ee212020-08-19 17:50:11 +0000171 logger.Warnw(ctx, "adding-adapter-already-in-KV-store", log.Fields{
Matteo Scandolod525ae32020-04-02 17:27:29 -0700172 "adapterName": adapter.Id,
173 "adapterReplica": adapter.CurrentReplica,
174 })
khenaidoo21d51152019-02-01 13:48:37 -0500175 }
176 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500177 clonedAdapter := (proto.Clone(adapter)).(*voltha.Adapter)
khenaidood948f772021-08-11 17:49:24 -0400178 // Use a muted adapter restart handler which is invoked by the corresponding gRPC client on an adapter restart.
179 // This handler just log the restart event. The actual action taken following an adapter restart
180 // will be done when an adapter re-registers itself.
181 aMgr.adapterAgents[adapter.Id] = newAdapterAgent(clonedAdapter, aMgr.mutedAdapterRestartedHandler, aMgr.liveProbeInterval)
182 aMgr.adapterEndpoints[Endpoint(adapter.Endpoint)] = aMgr.adapterAgents[adapter.Id]
khenaidoo21d51152019-02-01 13:48:37 -0500183 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530184 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500185}
186
Rohan Agrawal31f21802020-06-12 05:38:46 +0000187func (aMgr *Manager) addDeviceTypes(ctx context.Context, deviceTypes *voltha.DeviceTypes, saveToDb bool) error {
khenaidoo21d51152019-02-01 13:48:37 -0500188 if deviceTypes == nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530189 return fmt.Errorf("no-device-type")
khenaidoo21d51152019-02-01 13:48:37 -0500190 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000191 logger.Debugw(ctx, "adding-device-types", log.Fields{"deviceTypes": deviceTypes})
khenaidood948f772021-08-11 17:49:24 -0400192 aMgr.lockAdapterAgentsMap.Lock()
193 defer aMgr.lockAdapterAgentsMap.Unlock()
194 aMgr.lockDeviceTypesMap.Lock()
195 defer aMgr.lockDeviceTypesMap.Unlock()
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500196
Matteo Scandolod525ae32020-04-02 17:27:29 -0700197 // create an in memory map to fetch the entire voltha.DeviceType from a device.Type string
198 for _, deviceType := range deviceTypes.Items {
199 aMgr.deviceTypes[deviceType.Id] = deviceType
200 }
201
khenaidoo21d51152019-02-01 13:48:37 -0500202 if saveToDb {
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500203 // Save the device types to the KV store
khenaidoo21d51152019-02-01 13:48:37 -0500204 for _, deviceType := range deviceTypes.Items {
khenaidood948f772021-08-11 17:49:24 -0400205 if have, err := aMgr.deviceTypeDbProxy.Get(log.WithSpanFromContext(context.Background(), ctx), deviceType.Id, &voltha.DeviceType{}); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000206 logger.Errorw(ctx, "Failed-to--device-types-from-cluster-data-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530207 return err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400208 } else if !have {
khenaidoo21d51152019-02-01 13:48:37 -0500209 // Does not exist - save it
210 clonedDType := (proto.Clone(deviceType)).(*voltha.DeviceType)
khenaidood948f772021-08-11 17:49:24 -0400211 if err := aMgr.deviceTypeDbProxy.Set(log.WithSpanFromContext(context.Background(), ctx), deviceType.Id, clonedDType); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000212 logger.Errorw(ctx, "Failed-to-add-device-types-to-cluster-data-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530213 return err
214 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000215 logger.Debugw(ctx, "device-type-saved-to-KV-Store", log.Fields{"deviceType": deviceType})
khenaidoo21d51152019-02-01 13:48:37 -0500216 }
217 }
218 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530219 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500220}
221
khenaidood948f772021-08-11 17:49:24 -0400222//loadAdaptersAndDevicetypesInMemory loads the existing set of adapters and device types in memory
223func (aMgr *Manager) loadAdaptersAndDevicetypesInMemory(ctx context.Context) error {
224 // Load the adapters
225 var adapters []*voltha.Adapter
226 if err := aMgr.adapterDbProxy.List(log.WithSpanFromContext(context.Background(), ctx), &adapters); err != nil {
227 logger.Errorw(ctx, "Failed-to-list-adapters-from-cluster-data-proxy", log.Fields{"error": err})
228 return err
229 }
230
231 logger.Debugw(ctx, "retrieved-adapters", log.Fields{"count": len(adapters)})
232
233 if len(adapters) != 0 {
234 for _, adapter := range adapters {
235 if err := aMgr.addAdapter(ctx, adapter, false); err != nil {
236 logger.Errorw(ctx, "failed-to-add-adapter", log.Fields{"adapterId": adapter.Id})
237 } else {
238 logger.Debugw(ctx, "adapter-added-successfully", log.Fields{"adapterId": adapter.Id})
239 }
khenaidoo21d51152019-02-01 13:48:37 -0500240 }
241 }
khenaidoo21d51152019-02-01 13:48:37 -0500242
khenaidood948f772021-08-11 17:49:24 -0400243 // Load the device types
244 var deviceTypes []*voltha.DeviceType
245 if err := aMgr.deviceTypeDbProxy.List(log.WithSpanFromContext(context.Background(), ctx), &deviceTypes); err != nil {
246 logger.Errorw(ctx, "Failed-to-list-device-types-from-cluster-data-proxy", log.Fields{"error": err})
247 return err
khenaidoo21d51152019-02-01 13:48:37 -0500248 }
khenaidood948f772021-08-11 17:49:24 -0400249
250 logger.Debugw(ctx, "retrieved-devicetypes", log.Fields{"count": len(deviceTypes)})
251
252 if len(deviceTypes) != 0 {
253 dTypes := &voltha.DeviceTypes{Items: []*voltha.DeviceType{}}
254 for _, dType := range deviceTypes {
255 logger.Debugw(ctx, "found-existing-device-types", log.Fields{"deviceTypes": deviceTypes})
256 dTypes.Items = append(dTypes.Items, dType)
257 }
258 if err := aMgr.addDeviceTypes(ctx, dTypes, false); err != nil {
259 logger.Errorw(ctx, "failed-to-add-device-type", log.Fields{"deviceTypes": deviceTypes})
260 } else {
261 logger.Debugw(ctx, "device-type-added-successfully", log.Fields{"deviceTypes": deviceTypes})
262 }
263 }
264
265 // Start the adapter agents - this will trigger the connection to the adapter
266 aMgr.lockAdapterAgentsMap.RLock()
267 defer aMgr.lockAdapterAgentsMap.RUnlock()
268 for _, adapterAgent := range aMgr.adapterAgents {
269 subCtx := log.WithSpanFromContext(context.Background(), ctx)
270 if err := adapterAgent.start(subCtx); err != nil {
271 logger.Errorw(ctx, "failed-to-start-adapter", log.Fields{"adapter-endpoint": adapterAgent.adapterAPIEndPoint})
272 }
273 }
274
275 logger.Debug(ctx, "no-existing-device-type-found")
276
khenaidoo21d51152019-02-01 13:48:37 -0500277 return nil
278}
279
khenaidoo9beaaf12021-10-19 17:32:01 -0400280func (aMgr *Manager) RegisterAdapter(ctx context.Context, registration *core_adapter.AdapterRegistration) (*empty.Empty, error) {
khenaidood948f772021-08-11 17:49:24 -0400281 adapter := registration.Adapter
282 deviceTypes := registration.DTypes
283 logger.Infow(ctx, "RegisterAdapter", log.Fields{"adapter": adapter, "deviceTypes": deviceTypes.Items})
khenaidoo21d51152019-02-01 13:48:37 -0500284
Matteo Scandolo57ee9aa2020-04-17 09:20:42 -0700285 if adapter.Type == "" {
Girish Kumar3e8ee212020-08-19 17:50:11 +0000286 logger.Errorw(ctx, "adapter-not-specifying-type", log.Fields{
Matteo Scandolo57ee9aa2020-04-17 09:20:42 -0700287 "adapterId": adapter.Id,
288 "vendor": adapter.Vendor,
289 "type": adapter.Type,
290 })
291 return nil, status.Error(codes.InvalidArgument, "adapter-not-specifying-type")
292 }
293
khenaidood948f772021-08-11 17:49:24 -0400294 if adpt, _ := aMgr.getAdapter(ctx, adapter.Id); adpt != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400295 // Already registered - Adapter may have restarted. Trigger the reconcile process for that adapter
khenaidood948f772021-08-11 17:49:24 -0400296 logger.Warnw(ctx, "adapter-restarted", log.Fields{"adapter": adpt.Id, "endpoint": adpt.Endpoint})
297
298 // First reset the adapter connection
299 agt, err := aMgr.getAgent(ctx, adpt.Id)
300 if err != nil {
301 logger.Errorw(ctx, "no-adapter-agent", log.Fields{"error": err})
302 return nil, err
303 }
304 agt.resetConnection(ctx)
305
npujar1d86a522019-11-14 17:11:16 +0530306 go func() {
khenaidood948f772021-08-11 17:49:24 -0400307 err := aMgr.onAdapterRestart(log.WithSpanFromContext(context.Background(), ctx), adpt.Endpoint)
npujar1d86a522019-11-14 17:11:16 +0530308 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000309 logger.Errorw(ctx, "unable-to-restart-adapter", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530310 }
311 }()
khenaidood948f772021-08-11 17:49:24 -0400312 return &empty.Empty{}, nil
khenaidoo21d51152019-02-01 13:48:37 -0500313 }
314 // Save the adapter and the device types
Rohan Agrawal31f21802020-06-12 05:38:46 +0000315 if err := aMgr.addAdapter(ctx, adapter, true); err != nil {
316 logger.Errorw(ctx, "failed-to-add-adapter", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530317 return nil, err
318 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000319 if err := aMgr.addDeviceTypes(ctx, deviceTypes, true); err != nil {
320 logger.Errorw(ctx, "failed-to-add-device-types", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530321 return nil, err
322 }
khenaidoo21d51152019-02-01 13:48:37 -0500323
Rohan Agrawal31f21802020-06-12 05:38:46 +0000324 logger.Debugw(ctx, "adapter-registered", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
Matteo Scandolod525ae32020-04-02 17:27:29 -0700325 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidoo21d51152019-02-01 13:48:37 -0500326
khenaidood948f772021-08-11 17:49:24 -0400327 // Setup the endpoints for this adapter
328 if err := aMgr.endpointMgr.RegisterAdapter(ctx, adapter, deviceTypes); err != nil {
329 logger.Errorw(ctx, "failed-to-register-adapter", log.Fields{"error": err})
330 }
331
332 // Start adapter instance - this will trigger the connection to the adapter
333 if agent, err := aMgr.getAgent(ctx, adapter.Id); agent != nil {
334 subCtx := log.WithSpanFromContext(context.Background(), ctx)
335 if err := agent.start(subCtx); err != nil {
336 logger.Errorw(ctx, "failed-to-start-adapter", log.Fields{"error": err})
337 return nil, err
338 }
339 } else {
340 logger.Fatalw(ctx, "adapter-absent", log.Fields{"error": err, "adapter": adapter.Id})
341 }
342
343 return &empty.Empty{}, nil
khenaidoo21d51152019-02-01 13:48:37 -0500344}
345
khenaidood948f772021-08-11 17:49:24 -0400346func (aMgr *Manager) GetAdapterTypeByVendorID(vendorID string) (string, error) {
347 aMgr.lockDeviceTypesMap.RLock()
348 defer aMgr.lockDeviceTypesMap.RUnlock()
349 for _, dType := range aMgr.deviceTypes {
350 for _, v := range dType.VendorIds {
351 if v == vendorID {
352 return dType.AdapterType, nil
353 }
354 }
355 }
356 return "", fmt.Errorf("vendor id %s not found", vendorID)
357}
358
359// GetAdapterType returns the name of the device adapter that services this device type
Kent Hagerman2b216042020-04-03 18:28:56 -0400360func (aMgr *Manager) GetAdapterType(deviceType string) (string, error) {
khenaidood948f772021-08-11 17:49:24 -0400361 aMgr.lockDeviceTypesMap.Lock()
362 defer aMgr.lockDeviceTypesMap.Unlock()
363 for _, dt := range aMgr.deviceTypes {
364 if deviceType == dt.Id {
365 return dt.AdapterType, nil
Matteo Scandolod525ae32020-04-02 17:27:29 -0700366 }
khenaidoo21d51152019-02-01 13:48:37 -0500367 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400368 return "", fmt.Errorf("adapter-not-registered-for-device-type %s", deviceType)
khenaidoo21d51152019-02-01 13:48:37 -0500369}
370
Kent Hagerman45a13e42020-04-13 12:23:50 -0400371// ListDeviceTypes returns all the device types known to the system
Rohan Agrawal31f21802020-06-12 05:38:46 +0000372func (aMgr *Manager) ListDeviceTypes(ctx context.Context, _ *empty.Empty) (*voltha.DeviceTypes, error) {
373 logger.Debug(ctx, "ListDeviceTypes")
khenaidood948f772021-08-11 17:49:24 -0400374 aMgr.lockDeviceTypesMap.Lock()
375 defer aMgr.lockDeviceTypesMap.Unlock()
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500376
Matteo Scandolod525ae32020-04-02 17:27:29 -0700377 deviceTypes := make([]*voltha.DeviceType, 0, len(aMgr.deviceTypes))
Matteo Scandolod525ae32020-04-02 17:27:29 -0700378 for _, deviceType := range aMgr.deviceTypes {
379 deviceTypes = append(deviceTypes, deviceType)
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500380 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400381 return &voltha.DeviceTypes{Items: deviceTypes}, nil
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500382}
383
Kent Hagerman45a13e42020-04-13 12:23:50 -0400384// GetDeviceType returns the device type proto definition given the name of the device type
khenaidood948f772021-08-11 17:49:24 -0400385func (aMgr *Manager) GetDeviceType(ctx context.Context, deviceType *common.ID) (*voltha.DeviceType, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000386 logger.Debugw(ctx, "GetDeviceType", log.Fields{"typeid": deviceType.Id})
khenaidood948f772021-08-11 17:49:24 -0400387 aMgr.lockDeviceTypesMap.Lock()
388 defer aMgr.lockDeviceTypesMap.Unlock()
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500389
Kent Hagerman45a13e42020-04-13 12:23:50 -0400390 dType, exist := aMgr.deviceTypes[deviceType.Id]
391 if !exist {
392 return nil, status.Errorf(codes.NotFound, "device_type-%s", deviceType.Id)
khenaidoo21d51152019-02-01 13:48:37 -0500393 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400394 return dType, nil
khenaidoo21d51152019-02-01 13:48:37 -0500395}
khenaidood948f772021-08-11 17:49:24 -0400396
397// ListAdapters returns the contents of all adapters known to the system
398func (aMgr *Manager) ListAdapters(ctx context.Context, _ *empty.Empty) (*voltha.Adapters, error) {
399 logger.Debug(ctx, "Listing adapters")
400 result := &voltha.Adapters{Items: []*voltha.Adapter{}}
401 aMgr.lockAdapterAgentsMap.RLock()
402 defer aMgr.lockAdapterAgentsMap.RUnlock()
403 for _, adapterAgent := range aMgr.adapterAgents {
404 if a := adapterAgent.getAdapter(ctx); a != nil {
405 result.Items = append(result.Items, (proto.Clone(a)).(*voltha.Adapter))
406 }
407 }
408 logger.Debugw(ctx, "Listing adapters", log.Fields{"result": result})
409 return result, nil
410}
411
412func (aMgr *Manager) getAgent(ctx context.Context, adapterID string) (*agent, error) {
413 aMgr.lockAdapterAgentsMap.RLock()
414 defer aMgr.lockAdapterAgentsMap.RUnlock()
415 if adapterAgent, ok := aMgr.adapterAgents[adapterID]; ok {
416 return adapterAgent, nil
417 }
418 return nil, errors.New("Not found")
419}
420
421func (aMgr *Manager) getAdapter(ctx context.Context, adapterID string) (*voltha.Adapter, error) {
422 aMgr.lockAdapterAgentsMap.RLock()
423 defer aMgr.lockAdapterAgentsMap.RUnlock()
424 if adapterAgent, ok := aMgr.adapterAgents[adapterID]; ok {
425 return adapterAgent.getAdapter(ctx), nil
426 }
427 return nil, errors.New("Not found")
428}
429
430// mutedAdapterRestartedHandler will be invoked by the grpc client on an adapter restart.
431// Since the Adapter will re-register itself and that will trigger the reconcile process,
432// therefore this handler does nothing, other than logging the event.
433func (aMgr *Manager) mutedAdapterRestartedHandler(ctx context.Context, endpoint string) error {
434 logger.Infow(ctx, "muted-adapter-restarted", log.Fields{"endpoint": endpoint})
435 return nil
436}
437
438func (aMgr *Manager) WaitUntilConnectionsToAdaptersAreUp(ctx context.Context, connectionRetryInterval time.Duration) error {
439 logger.Infow(ctx, "waiting-for-adapters-to-be-up", log.Fields{"retry-interval": connectionRetryInterval})
440 for {
441 aMgr.lockAdapterAgentsMap.Lock()
442 numAdapters := len(aMgr.adapterAgents)
443 if numAdapters == 0 {
444 // No adapter registered yet
445 aMgr.lockAdapterAgentsMap.Unlock()
446 logger.Info(ctx, "no-adapter-registered")
447 return nil
448 }
449 // A case of Core restart
450 agentsUp := true
451 adapterloop:
452 for _, agt := range aMgr.adapterAgents {
453 agentsUp = agentsUp && agt.IsConnectionUp()
454 if !agentsUp {
455 break adapterloop
456 }
457 }
458 aMgr.lockAdapterAgentsMap.Unlock()
459 if agentsUp {
460 logger.Infow(ctx, "adapter-connections-ready", log.Fields{"adapter-count": numAdapters})
461 return nil
462 }
463 logger.Warnw(ctx, "adapter-connections-not-ready", log.Fields{"adapter-count": numAdapters})
464 select {
465 case <-time.After(connectionRetryInterval):
466 logger.Infow(ctx, "retrying-adapter-connections", log.Fields{"adapter-count": numAdapters})
467 continue
468 case <-ctx.Done():
469 logger.Errorw(ctx, "context-timeout", log.Fields{"adapter-count": numAdapters, "err": ctx.Err()})
470 return ctx.Err()
471 }
472 }
473}