blob: 45a0ff5555eba7672062068335d4a50d169d8ee2 [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
khenaidoo21d51152019-02-01 13:48:37 -050017package core
18
19import (
20 "context"
khenaidoo21d51152019-02-01 13:48:37 -050021 "fmt"
Kent Hagerman16ce36a2019-12-17 13:40:53 -050022 "github.com/golang/protobuf/ptypes"
23 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
npujar1d86a522019-11-14 17:11:16 +053024 "reflect"
25 "sync"
Kent Hagerman16ce36a2019-12-17 13:40:53 -050026 "time"
npujar1d86a522019-11-14 17:11:16 +053027
khenaidoo21d51152019-02-01 13:48:37 -050028 "github.com/gogo/protobuf/proto"
sbarbari17d7e222019-11-05 10:02:29 -050029 "github.com/opencord/voltha-go/db/model"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080030 "github.com/opencord/voltha-lib-go/v3/pkg/log"
31 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
32 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoo21d51152019-02-01 13:48:37 -050033)
34
npujar1d86a522019-11-14 17:11:16 +053035// sentinel constants
khenaidoo21d51152019-02-01 13:48:37 -050036const (
npujar1d86a522019-11-14 17:11:16 +053037 SentinelAdapterID = "adapter_sentinel"
38 SentinelDevicetypeID = "device_type_sentinel"
khenaidoo21d51152019-02-01 13:48:37 -050039)
40
npujar1d86a522019-11-14 17:11:16 +053041// AdapterAgent represents adapter agent
khenaidoo21d51152019-02-01 13:48:37 -050042type AdapterAgent struct {
khenaidoo1ce37ad2019-03-24 22:07:24 -040043 adapter *voltha.Adapter
khenaidoo21d51152019-02-01 13:48:37 -050044 deviceTypes map[string]*voltha.DeviceType
khenaidoo1ce37ad2019-03-24 22:07:24 -040045 lock sync.RWMutex
khenaidoo21d51152019-02-01 13:48:37 -050046}
47
48func newAdapterAgent(adapter *voltha.Adapter, deviceTypes *voltha.DeviceTypes) *AdapterAgent {
49 var adapterAgent AdapterAgent
50 adapterAgent.adapter = adapter
51 adapterAgent.lock = sync.RWMutex{}
52 adapterAgent.deviceTypes = make(map[string]*voltha.DeviceType)
53 if deviceTypes != nil {
54 for _, dType := range deviceTypes.Items {
55 adapterAgent.deviceTypes[dType.Id] = dType
56 }
57 }
58 return &adapterAgent
59}
60
khenaidoo21d51152019-02-01 13:48:37 -050061func (aa *AdapterAgent) getDeviceType(deviceType string) *voltha.DeviceType {
62 aa.lock.RLock()
63 defer aa.lock.RUnlock()
64 if _, exist := aa.deviceTypes[deviceType]; exist {
65 return aa.deviceTypes[deviceType]
66 }
67 return nil
68}
69
70func (aa *AdapterAgent) getAdapter() *voltha.Adapter {
71 aa.lock.RLock()
72 defer aa.lock.RUnlock()
73 log.Debugw("getAdapter", log.Fields{"adapter": aa.adapter})
74 return aa.adapter
75}
76
77func (aa *AdapterAgent) updateAdapter(adapter *voltha.Adapter) {
khenaidoo1ce37ad2019-03-24 22:07:24 -040078 aa.lock.Lock()
79 defer aa.lock.Unlock()
khenaidoo21d51152019-02-01 13:48:37 -050080 aa.adapter = adapter
81}
82
khenaidoo1ce37ad2019-03-24 22:07:24 -040083func (aa *AdapterAgent) updateDeviceType(deviceType *voltha.DeviceType) {
84 aa.lock.Lock()
85 defer aa.lock.Unlock()
khenaidoo21d51152019-02-01 13:48:37 -050086 aa.deviceTypes[deviceType.Id] = deviceType
87}
88
Kent Hagerman16ce36a2019-12-17 13:40:53 -050089// updateCommunicationTime updates the message to the specified time.
90// No attempt is made to save the time to the db, so only recent times are guaranteed to be accurate.
91func (aa *AdapterAgent) updateCommunicationTime(new time.Time) {
92 // only update if new time is not in the future, and either the old time is invalid or new time > old time
93 if last, err := ptypes.Timestamp(aa.adapter.LastCommunication); !new.After(time.Now()) && (err != nil || new.After(last)) {
94 timestamp, err := ptypes.TimestampProto(new)
95 if err != nil {
96 return // if the new time cannot be encoded, just ignore it
97 }
98
99 aa.lock.Lock()
100 defer aa.lock.Unlock()
101 aa.adapter.LastCommunication = timestamp
102 }
103}
104
npujar1d86a522019-11-14 17:11:16 +0530105// AdapterManager represents adapter manager attributes
khenaidoo21d51152019-02-01 13:48:37 -0500106type AdapterManager struct {
107 adapterAgents map[string]*AdapterAgent
108 deviceTypeToAdapterMap map[string]string
109 clusterDataProxy *model.Proxy
110 adapterProxy *model.Proxy
111 deviceTypeProxy *model.Proxy
khenaidooba6b6c42019-08-02 09:11:56 -0400112 deviceMgr *DeviceManager
npujar1d86a522019-11-14 17:11:16 +0530113 coreInstanceID string
khenaidoo21d51152019-02-01 13:48:37 -0500114 exitChannel chan int
115 lockAdaptersMap sync.RWMutex
116 lockdDeviceTypeToAdapterMap sync.RWMutex
117}
118
Kent Hagerman16ce36a2019-12-17 13:40:53 -0500119func newAdapterManager(cdProxy *model.Proxy, coreInstanceID string, kafkaClient kafka.Client, deviceMgr *DeviceManager) *AdapterManager {
120 aMgr := &AdapterManager{
121 exitChannel: make(chan int, 1),
122 coreInstanceID: coreInstanceID,
123 clusterDataProxy: cdProxy,
124 adapterAgents: make(map[string]*AdapterAgent),
125 deviceTypeToAdapterMap: make(map[string]string),
126 deviceMgr: deviceMgr,
127 }
128 kafkaClient.SubscribeForMetadata(aMgr.updateLastAdapterCommunication)
129 return aMgr
khenaidoo21d51152019-02-01 13:48:37 -0500130}
131
Thomas Lee Se5a44012019-11-07 20:32:24 +0530132func (aMgr *AdapterManager) start(ctx context.Context) error {
khenaidoo21d51152019-02-01 13:48:37 -0500133 log.Info("starting-adapter-manager")
134
135 // Load the existing adapterAgents and device types - this will also ensure the correct paths have been
136 // created if there are no data in the dB to start
Thomas Lee Se5a44012019-11-07 20:32:24 +0530137 err := aMgr.loadAdaptersAndDevicetypesInMemory()
138 if err != nil {
139 log.Errorw("Failed-to-load-adapters-and-device-types-in-memeory", log.Fields{"error": err})
140 return err
141 }
khenaidoo21d51152019-02-01 13:48:37 -0500142
143 //// Create the proxies
npujar467fe752020-01-16 20:17:45 +0530144 aMgr.adapterProxy, err = aMgr.clusterDataProxy.CreateProxy(ctx, "/adapters", false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530145 if err != nil {
146 log.Errorw("Failed-to-create-adapter-proxy", log.Fields{"error": err})
147 return err
148 }
npujar467fe752020-01-16 20:17:45 +0530149 aMgr.deviceTypeProxy, err = aMgr.clusterDataProxy.CreateProxy(ctx, "/device_types", false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530150 if err != nil {
151 log.Errorw("Failed-to-create-device-proxy", log.Fields{"error": err})
152 return err
153 }
khenaidoo21d51152019-02-01 13:48:37 -0500154
155 // Register the callbacks
npujar9a30c702019-11-14 17:06:39 +0530156 aMgr.adapterProxy.RegisterCallback(model.PostUpdate, aMgr.adapterUpdated)
157 aMgr.deviceTypeProxy.RegisterCallback(model.PostUpdate, aMgr.deviceTypesUpdated)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -0700158 probe.UpdateStatusFromContext(ctx, "adapter-manager", probe.ServiceStatusRunning)
khenaidoo21d51152019-02-01 13:48:37 -0500159 log.Info("adapter-manager-started")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530160 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500161}
162
khenaidoo21d51152019-02-01 13:48:37 -0500163//loadAdaptersAndDevicetypesInMemory loads the existing set of adapters and device types in memory
Thomas Lee Se5a44012019-11-07 20:32:24 +0530164func (aMgr *AdapterManager) loadAdaptersAndDevicetypesInMemory() error {
khenaidoo21d51152019-02-01 13:48:37 -0500165 // Load the adapters
Thomas Lee Se5a44012019-11-07 20:32:24 +0530166 adaptersIf, err := aMgr.clusterDataProxy.List(context.Background(), "/adapters", 0, false, "")
167 if err != nil {
168 log.Errorw("Failed-to-list-adapters-from-cluster-data-proxy", log.Fields{"error": err})
169 return err
170 }
171 if adaptersIf != nil {
khenaidoo21d51152019-02-01 13:48:37 -0500172 for _, adapterIf := range adaptersIf.([]interface{}) {
173 if adapter, ok := adapterIf.(*voltha.Adapter); ok {
khenaidooe7be1332020-01-24 18:58:33 -0500174 if err := aMgr.addAdapter(adapter, false); err != nil {
175 log.Errorw("failed to add adapter", log.Fields{"adapterId": adapter.Id})
176 } else {
177 log.Debugw("adapter added successfully", log.Fields{"adapterId": adapter.Id})
178 }
khenaidoo21d51152019-02-01 13:48:37 -0500179 }
180 }
181 } else {
182 log.Debug("no-existing-adapter-found")
183 // No adapter data. In order to have a proxy setup for that path let's create a fake adapter
Thomas Lee Se5a44012019-11-07 20:32:24 +0530184 return aMgr.addAdapter(&voltha.Adapter{Id: SentinelAdapterID}, true)
khenaidoo21d51152019-02-01 13:48:37 -0500185 }
186
187 // Load the device types
Thomas Lee Se5a44012019-11-07 20:32:24 +0530188 deviceTypesIf, err := aMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, "")
189 if err != nil {
190 log.Errorw("Failed-to-list-device-types-from-cluster-data-proxy", log.Fields{"error": err})
191 return err
192 }
193 if deviceTypesIf != nil {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400194 dTypes := &voltha.DeviceTypes{Items: []*voltha.DeviceType{}}
khenaidoo21d51152019-02-01 13:48:37 -0500195 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
196 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
197 log.Debugw("found-existing-device-types", log.Fields{"deviceTypes": dTypes})
198 dTypes.Items = append(dTypes.Items, dType)
khenaidooe7be1332020-01-24 18:58:33 -0500199 } else {
200 log.Errorw("not an voltha device type", log.Fields{"interface": deviceTypeIf})
khenaidoo21d51152019-02-01 13:48:37 -0500201 }
202 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530203 return aMgr.addDeviceTypes(dTypes, false)
khenaidoo21d51152019-02-01 13:48:37 -0500204 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530205
206 log.Debug("no-existing-device-type-found")
207 // No device types data. In order to have a proxy setup for that path let's create a fake device type
208 return aMgr.addDeviceTypes(&voltha.DeviceTypes{Items: []*voltha.DeviceType{{Id: SentinelDevicetypeID, Adapter: SentinelAdapterID}}}, true)
khenaidoo21d51152019-02-01 13:48:37 -0500209}
210
Kent Hagerman16ce36a2019-12-17 13:40:53 -0500211func (aMgr *AdapterManager) updateLastAdapterCommunication(adapterID string, timestamp int64) {
212 aMgr.lockAdaptersMap.RLock()
213 adapterAgent, have := aMgr.adapterAgents[adapterID]
214 aMgr.lockAdaptersMap.RUnlock()
215
216 if have {
217 adapterAgent.updateCommunicationTime(time.Unix(timestamp/1000, timestamp%1000*1000))
218 }
219}
220
khenaidoo297cd252019-02-07 22:10:23 -0500221//updateAdaptersAndDevicetypesInMemory loads the existing set of adapters and device types in memory
npujar467fe752020-01-16 20:17:45 +0530222func (aMgr *AdapterManager) updateAdaptersAndDevicetypesInMemory(ctx context.Context, adapter *voltha.Adapter) {
A R Karthicked2a77b2019-10-08 01:40:51 +0000223 aMgr.lockAdaptersMap.Lock()
224 defer aMgr.lockAdaptersMap.Unlock()
225
226 if adapterAgent, ok := aMgr.adapterAgents[adapter.Id]; ok {
227 if adapterAgent.getAdapter() != nil {
228 // Already registered - Adapter may have restarted. Trigger the reconcile process for that adapter
npujar1d86a522019-11-14 17:11:16 +0530229 go func() {
npujar467fe752020-01-16 20:17:45 +0530230 err := aMgr.deviceMgr.adapterRestarted(ctx, adapter)
npujar1d86a522019-11-14 17:11:16 +0530231 if err != nil {
232 log.Errorw("unable-to-restart-adapter", log.Fields{"error": err})
233 }
234 }()
A R Karthicked2a77b2019-10-08 01:40:51 +0000235 return
236 }
khenaidooba6b6c42019-08-02 09:11:56 -0400237 }
238
khenaidoo297cd252019-02-07 22:10:23 -0500239 // Update the adapters
npujar467fe752020-01-16 20:17:45 +0530240 adaptersIf, err := aMgr.clusterDataProxy.List(ctx, "/adapters", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530241 if err != nil {
242 log.Errorw("failed-to-list-adapters-from-cluster-proxy", log.Fields{"error": err})
243 return
244 }
245 if adaptersIf != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500246 for _, adapterIf := range adaptersIf.([]interface{}) {
247 if adapter, ok := adapterIf.(*voltha.Adapter); ok {
248 log.Debugw("found-existing-adapter", log.Fields{"adapterId": adapter.Id})
A R Karthicked2a77b2019-10-08 01:40:51 +0000249 aMgr.updateAdapterWithoutLock(adapter)
khenaidoo297cd252019-02-07 22:10:23 -0500250 }
251 }
252 }
A R Karthicked2a77b2019-10-08 01:40:51 +0000253 aMgr.lockdDeviceTypeToAdapterMap.Lock()
254 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500255 // Update the device types
Thomas Lee Se5a44012019-11-07 20:32:24 +0530256 deviceTypesIf, err := aMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, "")
257 if err != nil {
258 log.Errorw("Failed-to-list-device-types-in-cluster-data-proxy", log.Fields{"error": err})
259 return
260 }
261 if deviceTypesIf != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500262 dTypes := &voltha.DeviceTypes{Items: []*voltha.DeviceType{}}
263 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
264 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
265 log.Debugw("found-existing-device-types", log.Fields{"deviceTypes": dTypes})
A R Karthicked2a77b2019-10-08 01:40:51 +0000266 aMgr.updateDeviceTypeWithoutLock(dType)
khenaidoo297cd252019-02-07 22:10:23 -0500267 }
268 }
269 }
270}
271
Thomas Lee Se5a44012019-11-07 20:32:24 +0530272func (aMgr *AdapterManager) addAdapter(adapter *voltha.Adapter, saveToDb bool) error {
khenaidoo21d51152019-02-01 13:48:37 -0500273 aMgr.lockAdaptersMap.Lock()
274 defer aMgr.lockAdaptersMap.Unlock()
275 log.Debugw("adding-adapter", log.Fields{"adapter": adapter})
276 if _, exist := aMgr.adapterAgents[adapter.Id]; !exist {
277 clonedAdapter := (proto.Clone(adapter)).(*voltha.Adapter)
278 aMgr.adapterAgents[adapter.Id] = newAdapterAgent(clonedAdapter, nil)
279 if saveToDb {
280 // Save the adapter to the KV store - first check if it already exist
Thomas Lee Se5a44012019-11-07 20:32:24 +0530281 kvAdapter, err := aMgr.clusterDataProxy.Get(context.Background(), "/adapters/"+adapter.Id, 0, false, "")
282 if err != nil {
283 log.Errorw("failed-to-get-adapters-from-cluster-proxy", log.Fields{"error": err})
284 return err
285 }
286 if kvAdapter == nil {
287 added, err := aMgr.clusterDataProxy.AddWithID(context.Background(), "/adapters", adapter.Id, clonedAdapter, "")
288 if err != nil {
289 log.Errorw("failed-to-save-adapter-to-cluster-proxy", log.Fields{"error": err})
290 return err
291 }
292 if added == nil {
khenaidoo21d51152019-02-01 13:48:37 -0500293 //TODO: Errors when saving to KV would require a separate go routine to be launched and try the saving again
294 log.Errorw("failed-to-save-adapter", log.Fields{"adapter": adapter})
295 } else {
296 log.Debugw("adapter-saved-to-KV-Store", log.Fields{"adapter": adapter})
297 }
298 }
299 }
300 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530301 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500302}
303
Thomas Lee Se5a44012019-11-07 20:32:24 +0530304func (aMgr *AdapterManager) addDeviceTypes(deviceTypes *voltha.DeviceTypes, saveToDb bool) error {
khenaidoo21d51152019-02-01 13:48:37 -0500305 if deviceTypes == nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530306 return fmt.Errorf("no-device-type")
khenaidoo21d51152019-02-01 13:48:37 -0500307 }
308 log.Debugw("adding-device-types", log.Fields{"deviceTypes": deviceTypes})
309 aMgr.lockAdaptersMap.Lock()
310 defer aMgr.lockAdaptersMap.Unlock()
311 aMgr.lockdDeviceTypeToAdapterMap.Lock()
312 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
313 for _, deviceType := range deviceTypes.Items {
314 clonedDType := (proto.Clone(deviceType)).(*voltha.DeviceType)
315 if adapterAgent, exist := aMgr.adapterAgents[clonedDType.Adapter]; exist {
316 adapterAgent.updateDeviceType(clonedDType)
317 } else {
318 log.Debugw("adapter-not-exist", log.Fields{"deviceTypes": deviceTypes, "adapterId": clonedDType.Adapter})
khenaidoo1ce37ad2019-03-24 22:07:24 -0400319 aMgr.adapterAgents[clonedDType.Adapter] = newAdapterAgent(&voltha.Adapter{Id: clonedDType.Adapter}, deviceTypes)
khenaidoo21d51152019-02-01 13:48:37 -0500320 }
321 aMgr.deviceTypeToAdapterMap[clonedDType.Id] = clonedDType.Adapter
322 }
323 if saveToDb {
324 // Save the device types to the KV store as well
325 for _, deviceType := range deviceTypes.Items {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530326 dType, err := aMgr.clusterDataProxy.Get(context.Background(), "/device_types/"+deviceType.Id, 0, false, "")
327 if err != nil {
328 log.Errorw("Failed-to--device-types-from-cluster-data-proxy", log.Fields{"error": err})
329 return err
330 }
331 if dType == nil {
khenaidoo21d51152019-02-01 13:48:37 -0500332 // Does not exist - save it
333 clonedDType := (proto.Clone(deviceType)).(*voltha.DeviceType)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530334 added, err := aMgr.clusterDataProxy.AddWithID(context.Background(), "/device_types", deviceType.Id, clonedDType, "")
335 if err != nil {
336 log.Errorw("Failed-to-add-device-types-to-cluster-data-proxy", log.Fields{"error": err})
337 return err
338 }
339 if added == nil {
khenaidoo21d51152019-02-01 13:48:37 -0500340 log.Errorw("failed-to-save-deviceType", log.Fields{"deviceType": deviceType})
341 } else {
342 log.Debugw("device-type-saved-to-KV-Store", log.Fields{"deviceType": deviceType})
343 }
344 }
345 }
346 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530347 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500348}
349
350func (aMgr *AdapterManager) listAdapters(ctx context.Context) (*voltha.Adapters, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400351 result := &voltha.Adapters{Items: []*voltha.Adapter{}}
352 aMgr.lockAdaptersMap.RLock()
353 defer aMgr.lockAdaptersMap.RUnlock()
khenaidoo21d51152019-02-01 13:48:37 -0500354 for _, adapterAgent := range aMgr.adapterAgents {
355 if a := adapterAgent.getAdapter(); a != nil {
npujar1d86a522019-11-14 17:11:16 +0530356 if a.Id != SentinelAdapterID { // don't report the sentinel
khenaidoo297cd252019-02-07 22:10:23 -0500357 result.Items = append(result.Items, (proto.Clone(a)).(*voltha.Adapter))
358 }
khenaidoo21d51152019-02-01 13:48:37 -0500359 }
360 }
361 return result, nil
362}
363
npujar1d86a522019-11-14 17:11:16 +0530364func (aMgr *AdapterManager) getAdapter(adapterID string) *voltha.Adapter {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400365 aMgr.lockAdaptersMap.RLock()
366 defer aMgr.lockAdaptersMap.RUnlock()
npujar1d86a522019-11-14 17:11:16 +0530367 if adapterAgent, ok := aMgr.adapterAgents[adapterID]; ok {
khenaidoo21d51152019-02-01 13:48:37 -0500368 return adapterAgent.getAdapter()
369 }
370 return nil
371}
372
373//updateAdapter updates an adapter if it exist. Otherwise, it creates it.
khenaidoo1ce37ad2019-03-24 22:07:24 -0400374func (aMgr *AdapterManager) updateAdapter(adapter *voltha.Adapter) {
khenaidoo21d51152019-02-01 13:48:37 -0500375 aMgr.lockAdaptersMap.Lock()
376 defer aMgr.lockAdaptersMap.Unlock()
A R Karthicked2a77b2019-10-08 01:40:51 +0000377 aMgr.updateAdapterWithoutLock(adapter)
378}
379
380func (aMgr *AdapterManager) updateAdapterWithoutLock(adapter *voltha.Adapter) {
khenaidoo21d51152019-02-01 13:48:37 -0500381 if adapterAgent, ok := aMgr.adapterAgents[adapter.Id]; ok {
382 adapterAgent.updateAdapter(adapter)
383 } else {
384 aMgr.adapterAgents[adapter.Id] = newAdapterAgent(adapter, nil)
385 }
386}
387
388//updateDeviceType updates an adapter if it exist. Otherwise, it creates it.
khenaidoo1ce37ad2019-03-24 22:07:24 -0400389func (aMgr *AdapterManager) updateDeviceType(deviceType *voltha.DeviceType) {
khenaidoo21d51152019-02-01 13:48:37 -0500390 aMgr.lockAdaptersMap.Lock()
391 defer aMgr.lockAdaptersMap.Unlock()
392 aMgr.lockdDeviceTypeToAdapterMap.Lock()
393 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
A R Karthicked2a77b2019-10-08 01:40:51 +0000394 aMgr.updateDeviceTypeWithoutLock(deviceType)
395}
396
397func (aMgr *AdapterManager) updateDeviceTypeWithoutLock(deviceType *voltha.DeviceType) {
khenaidoo297cd252019-02-07 22:10:23 -0500398 if adapterAgent, exist := aMgr.adapterAgents[deviceType.Adapter]; exist {
khenaidoo21d51152019-02-01 13:48:37 -0500399 adapterAgent.updateDeviceType(deviceType)
400 } else {
401 aMgr.adapterAgents[deviceType.Adapter] = newAdapterAgent(&voltha.Adapter{Id: deviceType.Adapter},
khenaidoo1ce37ad2019-03-24 22:07:24 -0400402 &voltha.DeviceTypes{Items: []*voltha.DeviceType{deviceType}})
khenaidoo21d51152019-02-01 13:48:37 -0500403 }
404 aMgr.deviceTypeToAdapterMap[deviceType.Id] = deviceType.Adapter
405}
406
Thomas Lee Se5a44012019-11-07 20:32:24 +0530407func (aMgr *AdapterManager) registerAdapter(adapter *voltha.Adapter, deviceTypes *voltha.DeviceTypes) (*voltha.CoreInstance, error) {
khenaidoo21d51152019-02-01 13:48:37 -0500408 log.Debugw("registerAdapter", log.Fields{"adapter": adapter, "deviceTypes": deviceTypes.Items})
409
410 if aMgr.getAdapter(adapter.Id) != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400411 // Already registered - Adapter may have restarted. Trigger the reconcile process for that adapter
npujar1d86a522019-11-14 17:11:16 +0530412 go func() {
npujar467fe752020-01-16 20:17:45 +0530413 err := aMgr.deviceMgr.adapterRestarted(context.Background(), adapter)
npujar1d86a522019-11-14 17:11:16 +0530414 if err != nil {
415 log.Errorw("unable-to-restart-adapter", log.Fields{"error": err})
416 }
417 }()
Thomas Lee Se5a44012019-11-07 20:32:24 +0530418 return &voltha.CoreInstance{InstanceId: aMgr.coreInstanceID}, nil
khenaidoo21d51152019-02-01 13:48:37 -0500419 }
420 // Save the adapter and the device types
Thomas Lee Se5a44012019-11-07 20:32:24 +0530421 if err := aMgr.addAdapter(adapter, true); err != nil {
422 log.Errorw("failed-to-add-adapter", log.Fields{"error": err})
423 return nil, err
424 }
425 if err := aMgr.addDeviceTypes(deviceTypes, true); err != nil {
426 log.Errorw("failed-to-add-device-types", log.Fields{"error": err})
427 return nil, err
428 }
khenaidoo21d51152019-02-01 13:48:37 -0500429
430 log.Debugw("adapter-registered", log.Fields{"adapter": adapter.Id})
431
Thomas Lee Se5a44012019-11-07 20:32:24 +0530432 return &voltha.CoreInstance{InstanceId: aMgr.coreInstanceID}, nil
khenaidoo21d51152019-02-01 13:48:37 -0500433}
434
435//getAdapterName returns the name of the device adapter that service this device type
436func (aMgr *AdapterManager) getAdapterName(deviceType string) (string, error) {
437 aMgr.lockdDeviceTypeToAdapterMap.Lock()
438 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530439 if adapterID, exist := aMgr.deviceTypeToAdapterMap[deviceType]; exist {
440 return adapterID, nil
khenaidoo21d51152019-02-01 13:48:37 -0500441 }
npujar1d86a522019-11-14 17:11:16 +0530442 return "", fmt.Errorf("Adapter-not-registered-for-device-type %s", deviceType)
khenaidoo21d51152019-02-01 13:48:37 -0500443}
444
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500445func (aMgr *AdapterManager) listDeviceTypes() []*voltha.DeviceType {
446 aMgr.lockdDeviceTypeToAdapterMap.Lock()
447 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
448
449 deviceTypes := make([]*voltha.DeviceType, 0, len(aMgr.deviceTypeToAdapterMap))
npujar1d86a522019-11-14 17:11:16 +0530450 for deviceTypeID, adapterID := range aMgr.deviceTypeToAdapterMap {
451 if adapterAgent, have := aMgr.adapterAgents[adapterID]; have {
452 if deviceType := adapterAgent.getDeviceType(deviceTypeID); deviceType != nil {
khenaidoob64fc8a2019-11-27 15:08:19 -0500453 if deviceType.Id != SentinelDevicetypeID { // don't report the sentinel
454 deviceTypes = append(deviceTypes, deviceType)
455 }
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500456 }
457 }
458 }
459 return deviceTypes
460}
461
khenaidoo21d51152019-02-01 13:48:37 -0500462// getDeviceType returns the device type proto definition given the name of the device type
khenaidoo1ce37ad2019-03-24 22:07:24 -0400463func (aMgr *AdapterManager) getDeviceType(deviceType string) *voltha.DeviceType {
khenaidoo21d51152019-02-01 13:48:37 -0500464 aMgr.lockdDeviceTypeToAdapterMap.Lock()
465 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500466
npujar1d86a522019-11-14 17:11:16 +0530467 if adapterID, exist := aMgr.deviceTypeToAdapterMap[deviceType]; exist {
468 if adapterAgent := aMgr.adapterAgents[adapterID]; adapterAgent != nil {
khenaidoo21d51152019-02-01 13:48:37 -0500469 return adapterAgent.getDeviceType(deviceType)
470 }
471 }
472 return nil
473}
474
475//adapterUpdated is a callback invoked when an adapter change has been noticed
npujar467fe752020-01-16 20:17:45 +0530476func (aMgr *AdapterManager) adapterUpdated(ctx context.Context, args ...interface{}) interface{} {
khenaidoo21d51152019-02-01 13:48:37 -0500477 log.Debugw("updateAdapter-callback", log.Fields{"argsLen": len(args)})
478
479 var previousData *voltha.Adapters
480 var latestData *voltha.Adapters
481
482 var ok bool
483 if previousData, ok = args[0].(*voltha.Adapters); !ok {
484 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
khenaidoo433f54a2019-02-05 14:02:57 -0500485 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500486 }
487 if latestData, ok = args[1].(*voltha.Adapters); !ok {
488 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
khenaidoo21d51152019-02-01 13:48:37 -0500489 return nil
490 }
491
khenaidoo433f54a2019-02-05 14:02:57 -0500492 if previousData != nil && latestData != nil {
493 if reflect.DeepEqual(previousData.Items, latestData.Items) {
494 log.Debug("update-not-required")
495 return nil
496 }
khenaidoo21d51152019-02-01 13:48:37 -0500497 }
khenaidoo433f54a2019-02-05 14:02:57 -0500498
499 if latestData != nil {
500 for _, adapter := range latestData.Items {
501 aMgr.updateAdapter(adapter)
502 }
503 }
504
khenaidoo21d51152019-02-01 13:48:37 -0500505 return nil
506}
507
508//deviceTypesUpdated is a callback invoked when a device type change has been noticed
npujar467fe752020-01-16 20:17:45 +0530509func (aMgr *AdapterManager) deviceTypesUpdated(ctx context.Context, args ...interface{}) interface{} {
khenaidoo21d51152019-02-01 13:48:37 -0500510 log.Debugw("deviceTypesUpdated-callback", log.Fields{"argsLen": len(args)})
511
512 var previousData *voltha.DeviceTypes
513 var latestData *voltha.DeviceTypes
514
515 var ok bool
516 if previousData, ok = args[0].(*voltha.DeviceTypes); !ok {
517 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
khenaidoo21d51152019-02-01 13:48:37 -0500518 return nil
519 }
520
khenaidoo433f54a2019-02-05 14:02:57 -0500521 if latestData, ok = args[1].(*voltha.DeviceTypes); !ok {
522 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
523 return nil
524 }
525
526 if previousData != nil && latestData != nil {
527 if reflect.DeepEqual(previousData.Items, latestData.Items) {
528 log.Debug("update-not-required")
529 return nil
530 }
531 }
532
533 if latestData != nil {
534 for _, dType := range latestData.Items {
535 aMgr.updateDeviceType(dType)
536 }
khenaidoo21d51152019-02-01 13:48:37 -0500537 }
538 return nil
khenaidoo1ce37ad2019-03-24 22:07:24 -0400539}