blob: 02d0b7a17c50d59339a584ff3cf0f2f6927f8305 [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"
npujar1d86a522019-11-14 17:11:16 +053022 "reflect"
23 "sync"
24
khenaidoo21d51152019-02-01 13:48:37 -050025 "github.com/gogo/protobuf/proto"
sbarbari17d7e222019-11-05 10:02:29 -050026 "github.com/opencord/voltha-go/db/model"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080027 "github.com/opencord/voltha-lib-go/v3/pkg/log"
28 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
29 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoo21d51152019-02-01 13:48:37 -050030)
31
npujar1d86a522019-11-14 17:11:16 +053032// sentinel constants
khenaidoo21d51152019-02-01 13:48:37 -050033const (
npujar1d86a522019-11-14 17:11:16 +053034 SentinelAdapterID = "adapter_sentinel"
35 SentinelDevicetypeID = "device_type_sentinel"
khenaidoo21d51152019-02-01 13:48:37 -050036)
37
npujar1d86a522019-11-14 17:11:16 +053038// AdapterAgent represents adapter agent
khenaidoo21d51152019-02-01 13:48:37 -050039type AdapterAgent struct {
khenaidoo1ce37ad2019-03-24 22:07:24 -040040 adapter *voltha.Adapter
khenaidoo21d51152019-02-01 13:48:37 -050041 deviceTypes map[string]*voltha.DeviceType
khenaidoo1ce37ad2019-03-24 22:07:24 -040042 lock sync.RWMutex
khenaidoo21d51152019-02-01 13:48:37 -050043}
44
45func newAdapterAgent(adapter *voltha.Adapter, deviceTypes *voltha.DeviceTypes) *AdapterAgent {
46 var adapterAgent AdapterAgent
47 adapterAgent.adapter = adapter
48 adapterAgent.lock = sync.RWMutex{}
49 adapterAgent.deviceTypes = make(map[string]*voltha.DeviceType)
50 if deviceTypes != nil {
51 for _, dType := range deviceTypes.Items {
52 adapterAgent.deviceTypes[dType.Id] = dType
53 }
54 }
55 return &adapterAgent
56}
57
khenaidoo21d51152019-02-01 13:48:37 -050058func (aa *AdapterAgent) getDeviceType(deviceType string) *voltha.DeviceType {
59 aa.lock.RLock()
60 defer aa.lock.RUnlock()
61 if _, exist := aa.deviceTypes[deviceType]; exist {
62 return aa.deviceTypes[deviceType]
63 }
64 return nil
65}
66
67func (aa *AdapterAgent) getAdapter() *voltha.Adapter {
68 aa.lock.RLock()
69 defer aa.lock.RUnlock()
70 log.Debugw("getAdapter", log.Fields{"adapter": aa.adapter})
71 return aa.adapter
72}
73
74func (aa *AdapterAgent) updateAdapter(adapter *voltha.Adapter) {
khenaidoo1ce37ad2019-03-24 22:07:24 -040075 aa.lock.Lock()
76 defer aa.lock.Unlock()
khenaidoo21d51152019-02-01 13:48:37 -050077 aa.adapter = adapter
78}
79
khenaidoo1ce37ad2019-03-24 22:07:24 -040080func (aa *AdapterAgent) updateDeviceType(deviceType *voltha.DeviceType) {
81 aa.lock.Lock()
82 defer aa.lock.Unlock()
khenaidoo21d51152019-02-01 13:48:37 -050083 aa.deviceTypes[deviceType.Id] = deviceType
84}
85
npujar1d86a522019-11-14 17:11:16 +053086// AdapterManager represents adapter manager attributes
khenaidoo21d51152019-02-01 13:48:37 -050087type AdapterManager struct {
88 adapterAgents map[string]*AdapterAgent
89 deviceTypeToAdapterMap map[string]string
90 clusterDataProxy *model.Proxy
91 adapterProxy *model.Proxy
92 deviceTypeProxy *model.Proxy
khenaidooba6b6c42019-08-02 09:11:56 -040093 deviceMgr *DeviceManager
npujar1d86a522019-11-14 17:11:16 +053094 coreInstanceID string
khenaidoo21d51152019-02-01 13:48:37 -050095 exitChannel chan int
96 lockAdaptersMap sync.RWMutex
97 lockdDeviceTypeToAdapterMap sync.RWMutex
98}
99
npujar1d86a522019-11-14 17:11:16 +0530100func newAdapterManager(cdProxy *model.Proxy, coreInstanceID string, deviceMgr *DeviceManager) *AdapterManager {
khenaidoo21d51152019-02-01 13:48:37 -0500101 var adapterMgr AdapterManager
102 adapterMgr.exitChannel = make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530103 adapterMgr.coreInstanceID = coreInstanceID
khenaidoo21d51152019-02-01 13:48:37 -0500104 adapterMgr.clusterDataProxy = cdProxy
105 adapterMgr.adapterAgents = make(map[string]*AdapterAgent)
106 adapterMgr.deviceTypeToAdapterMap = make(map[string]string)
107 adapterMgr.lockAdaptersMap = sync.RWMutex{}
108 adapterMgr.lockdDeviceTypeToAdapterMap = sync.RWMutex{}
khenaidooba6b6c42019-08-02 09:11:56 -0400109 adapterMgr.deviceMgr = deviceMgr
khenaidoo21d51152019-02-01 13:48:37 -0500110 return &adapterMgr
111}
112
Thomas Lee Se5a44012019-11-07 20:32:24 +0530113func (aMgr *AdapterManager) start(ctx context.Context) error {
khenaidoo21d51152019-02-01 13:48:37 -0500114 log.Info("starting-adapter-manager")
115
116 // Load the existing adapterAgents and device types - this will also ensure the correct paths have been
117 // created if there are no data in the dB to start
Thomas Lee Se5a44012019-11-07 20:32:24 +0530118 err := aMgr.loadAdaptersAndDevicetypesInMemory()
119 if err != nil {
120 log.Errorw("Failed-to-load-adapters-and-device-types-in-memeory", log.Fields{"error": err})
121 return err
122 }
khenaidoo21d51152019-02-01 13:48:37 -0500123
124 //// Create the proxies
npujar467fe752020-01-16 20:17:45 +0530125 aMgr.adapterProxy, err = aMgr.clusterDataProxy.CreateProxy(ctx, "/adapters", false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530126 if err != nil {
127 log.Errorw("Failed-to-create-adapter-proxy", log.Fields{"error": err})
128 return err
129 }
npujar467fe752020-01-16 20:17:45 +0530130 aMgr.deviceTypeProxy, err = aMgr.clusterDataProxy.CreateProxy(ctx, "/device_types", false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530131 if err != nil {
132 log.Errorw("Failed-to-create-device-proxy", log.Fields{"error": err})
133 return err
134 }
khenaidoo21d51152019-02-01 13:48:37 -0500135
136 // Register the callbacks
npujar9a30c702019-11-14 17:06:39 +0530137 aMgr.adapterProxy.RegisterCallback(model.PostUpdate, aMgr.adapterUpdated)
138 aMgr.deviceTypeProxy.RegisterCallback(model.PostUpdate, aMgr.deviceTypesUpdated)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -0700139 probe.UpdateStatusFromContext(ctx, "adapter-manager", probe.ServiceStatusRunning)
khenaidoo21d51152019-02-01 13:48:37 -0500140 log.Info("adapter-manager-started")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530141 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500142}
143
khenaidoo21d51152019-02-01 13:48:37 -0500144//loadAdaptersAndDevicetypesInMemory loads the existing set of adapters and device types in memory
Thomas Lee Se5a44012019-11-07 20:32:24 +0530145func (aMgr *AdapterManager) loadAdaptersAndDevicetypesInMemory() error {
khenaidoo21d51152019-02-01 13:48:37 -0500146 // Load the adapters
Thomas Lee Se5a44012019-11-07 20:32:24 +0530147 adaptersIf, err := aMgr.clusterDataProxy.List(context.Background(), "/adapters", 0, false, "")
148 if err != nil {
149 log.Errorw("Failed-to-list-adapters-from-cluster-data-proxy", log.Fields{"error": err})
150 return err
151 }
152 if adaptersIf != nil {
khenaidoo21d51152019-02-01 13:48:37 -0500153 for _, adapterIf := range adaptersIf.([]interface{}) {
154 if adapter, ok := adapterIf.(*voltha.Adapter); ok {
khenaidooe7be1332020-01-24 18:58:33 -0500155 if err := aMgr.addAdapter(adapter, false); err != nil {
156 log.Errorw("failed to add adapter", log.Fields{"adapterId": adapter.Id})
157 } else {
158 log.Debugw("adapter added successfully", log.Fields{"adapterId": adapter.Id})
159 }
khenaidoo21d51152019-02-01 13:48:37 -0500160 }
161 }
162 } else {
163 log.Debug("no-existing-adapter-found")
164 // 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 +0530165 return aMgr.addAdapter(&voltha.Adapter{Id: SentinelAdapterID}, true)
khenaidoo21d51152019-02-01 13:48:37 -0500166 }
167
168 // Load the device types
Thomas Lee Se5a44012019-11-07 20:32:24 +0530169 deviceTypesIf, err := aMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, "")
170 if err != nil {
171 log.Errorw("Failed-to-list-device-types-from-cluster-data-proxy", log.Fields{"error": err})
172 return err
173 }
174 if deviceTypesIf != nil {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400175 dTypes := &voltha.DeviceTypes{Items: []*voltha.DeviceType{}}
khenaidoo21d51152019-02-01 13:48:37 -0500176 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
177 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
178 log.Debugw("found-existing-device-types", log.Fields{"deviceTypes": dTypes})
179 dTypes.Items = append(dTypes.Items, dType)
khenaidooe7be1332020-01-24 18:58:33 -0500180 } else {
181 log.Errorw("not an voltha device type", log.Fields{"interface": deviceTypeIf})
khenaidoo21d51152019-02-01 13:48:37 -0500182 }
183 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530184 return aMgr.addDeviceTypes(dTypes, false)
khenaidoo21d51152019-02-01 13:48:37 -0500185 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530186
187 log.Debug("no-existing-device-type-found")
188 // No device types data. In order to have a proxy setup for that path let's create a fake device type
189 return aMgr.addDeviceTypes(&voltha.DeviceTypes{Items: []*voltha.DeviceType{{Id: SentinelDevicetypeID, Adapter: SentinelAdapterID}}}, true)
khenaidoo21d51152019-02-01 13:48:37 -0500190}
191
khenaidoo297cd252019-02-07 22:10:23 -0500192//updateAdaptersAndDevicetypesInMemory loads the existing set of adapters and device types in memory
npujar467fe752020-01-16 20:17:45 +0530193func (aMgr *AdapterManager) updateAdaptersAndDevicetypesInMemory(ctx context.Context, adapter *voltha.Adapter) {
A R Karthicked2a77b2019-10-08 01:40:51 +0000194 aMgr.lockAdaptersMap.Lock()
195 defer aMgr.lockAdaptersMap.Unlock()
196
197 if adapterAgent, ok := aMgr.adapterAgents[adapter.Id]; ok {
198 if adapterAgent.getAdapter() != nil {
199 // Already registered - Adapter may have restarted. Trigger the reconcile process for that adapter
npujar1d86a522019-11-14 17:11:16 +0530200 go func() {
npujar467fe752020-01-16 20:17:45 +0530201 err := aMgr.deviceMgr.adapterRestarted(ctx, adapter)
npujar1d86a522019-11-14 17:11:16 +0530202 if err != nil {
203 log.Errorw("unable-to-restart-adapter", log.Fields{"error": err})
204 }
205 }()
A R Karthicked2a77b2019-10-08 01:40:51 +0000206 return
207 }
khenaidooba6b6c42019-08-02 09:11:56 -0400208 }
209
khenaidoo297cd252019-02-07 22:10:23 -0500210 // Update the adapters
npujar467fe752020-01-16 20:17:45 +0530211 adaptersIf, err := aMgr.clusterDataProxy.List(ctx, "/adapters", 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530212 if err != nil {
213 log.Errorw("failed-to-list-adapters-from-cluster-proxy", log.Fields{"error": err})
214 return
215 }
216 if adaptersIf != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500217 for _, adapterIf := range adaptersIf.([]interface{}) {
218 if adapter, ok := adapterIf.(*voltha.Adapter); ok {
219 log.Debugw("found-existing-adapter", log.Fields{"adapterId": adapter.Id})
A R Karthicked2a77b2019-10-08 01:40:51 +0000220 aMgr.updateAdapterWithoutLock(adapter)
khenaidoo297cd252019-02-07 22:10:23 -0500221 }
222 }
223 }
A R Karthicked2a77b2019-10-08 01:40:51 +0000224 aMgr.lockdDeviceTypeToAdapterMap.Lock()
225 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500226 // Update the device types
Thomas Lee Se5a44012019-11-07 20:32:24 +0530227 deviceTypesIf, err := aMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, "")
228 if err != nil {
229 log.Errorw("Failed-to-list-device-types-in-cluster-data-proxy", log.Fields{"error": err})
230 return
231 }
232 if deviceTypesIf != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500233 dTypes := &voltha.DeviceTypes{Items: []*voltha.DeviceType{}}
234 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
235 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
236 log.Debugw("found-existing-device-types", log.Fields{"deviceTypes": dTypes})
A R Karthicked2a77b2019-10-08 01:40:51 +0000237 aMgr.updateDeviceTypeWithoutLock(dType)
khenaidoo297cd252019-02-07 22:10:23 -0500238 }
239 }
240 }
241}
242
Thomas Lee Se5a44012019-11-07 20:32:24 +0530243func (aMgr *AdapterManager) addAdapter(adapter *voltha.Adapter, saveToDb bool) error {
khenaidoo21d51152019-02-01 13:48:37 -0500244 aMgr.lockAdaptersMap.Lock()
245 defer aMgr.lockAdaptersMap.Unlock()
246 log.Debugw("adding-adapter", log.Fields{"adapter": adapter})
247 if _, exist := aMgr.adapterAgents[adapter.Id]; !exist {
248 clonedAdapter := (proto.Clone(adapter)).(*voltha.Adapter)
249 aMgr.adapterAgents[adapter.Id] = newAdapterAgent(clonedAdapter, nil)
250 if saveToDb {
251 // Save the adapter to the KV store - first check if it already exist
Thomas Lee Se5a44012019-11-07 20:32:24 +0530252 kvAdapter, err := aMgr.clusterDataProxy.Get(context.Background(), "/adapters/"+adapter.Id, 0, false, "")
253 if err != nil {
254 log.Errorw("failed-to-get-adapters-from-cluster-proxy", log.Fields{"error": err})
255 return err
256 }
257 if kvAdapter == nil {
258 added, err := aMgr.clusterDataProxy.AddWithID(context.Background(), "/adapters", adapter.Id, clonedAdapter, "")
259 if err != nil {
260 log.Errorw("failed-to-save-adapter-to-cluster-proxy", log.Fields{"error": err})
261 return err
262 }
263 if added == nil {
khenaidoo21d51152019-02-01 13:48:37 -0500264 //TODO: Errors when saving to KV would require a separate go routine to be launched and try the saving again
265 log.Errorw("failed-to-save-adapter", log.Fields{"adapter": adapter})
266 } else {
267 log.Debugw("adapter-saved-to-KV-Store", log.Fields{"adapter": adapter})
268 }
269 }
270 }
271 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530272 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500273}
274
Thomas Lee Se5a44012019-11-07 20:32:24 +0530275func (aMgr *AdapterManager) addDeviceTypes(deviceTypes *voltha.DeviceTypes, saveToDb bool) error {
khenaidoo21d51152019-02-01 13:48:37 -0500276 if deviceTypes == nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530277 return fmt.Errorf("no-device-type")
khenaidoo21d51152019-02-01 13:48:37 -0500278 }
279 log.Debugw("adding-device-types", log.Fields{"deviceTypes": deviceTypes})
280 aMgr.lockAdaptersMap.Lock()
281 defer aMgr.lockAdaptersMap.Unlock()
282 aMgr.lockdDeviceTypeToAdapterMap.Lock()
283 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
284 for _, deviceType := range deviceTypes.Items {
285 clonedDType := (proto.Clone(deviceType)).(*voltha.DeviceType)
286 if adapterAgent, exist := aMgr.adapterAgents[clonedDType.Adapter]; exist {
287 adapterAgent.updateDeviceType(clonedDType)
288 } else {
289 log.Debugw("adapter-not-exist", log.Fields{"deviceTypes": deviceTypes, "adapterId": clonedDType.Adapter})
khenaidoo1ce37ad2019-03-24 22:07:24 -0400290 aMgr.adapterAgents[clonedDType.Adapter] = newAdapterAgent(&voltha.Adapter{Id: clonedDType.Adapter}, deviceTypes)
khenaidoo21d51152019-02-01 13:48:37 -0500291 }
292 aMgr.deviceTypeToAdapterMap[clonedDType.Id] = clonedDType.Adapter
293 }
294 if saveToDb {
295 // Save the device types to the KV store as well
296 for _, deviceType := range deviceTypes.Items {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530297 dType, err := aMgr.clusterDataProxy.Get(context.Background(), "/device_types/"+deviceType.Id, 0, false, "")
298 if err != nil {
299 log.Errorw("Failed-to--device-types-from-cluster-data-proxy", log.Fields{"error": err})
300 return err
301 }
302 if dType == nil {
khenaidoo21d51152019-02-01 13:48:37 -0500303 // Does not exist - save it
304 clonedDType := (proto.Clone(deviceType)).(*voltha.DeviceType)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530305 added, err := aMgr.clusterDataProxy.AddWithID(context.Background(), "/device_types", deviceType.Id, clonedDType, "")
306 if err != nil {
307 log.Errorw("Failed-to-add-device-types-to-cluster-data-proxy", log.Fields{"error": err})
308 return err
309 }
310 if added == nil {
khenaidoo21d51152019-02-01 13:48:37 -0500311 log.Errorw("failed-to-save-deviceType", log.Fields{"deviceType": deviceType})
312 } else {
313 log.Debugw("device-type-saved-to-KV-Store", log.Fields{"deviceType": deviceType})
314 }
315 }
316 }
317 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530318 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500319}
320
321func (aMgr *AdapterManager) listAdapters(ctx context.Context) (*voltha.Adapters, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400322 result := &voltha.Adapters{Items: []*voltha.Adapter{}}
323 aMgr.lockAdaptersMap.RLock()
324 defer aMgr.lockAdaptersMap.RUnlock()
khenaidoo21d51152019-02-01 13:48:37 -0500325 for _, adapterAgent := range aMgr.adapterAgents {
326 if a := adapterAgent.getAdapter(); a != nil {
npujar1d86a522019-11-14 17:11:16 +0530327 if a.Id != SentinelAdapterID { // don't report the sentinel
khenaidoo297cd252019-02-07 22:10:23 -0500328 result.Items = append(result.Items, (proto.Clone(a)).(*voltha.Adapter))
329 }
khenaidoo21d51152019-02-01 13:48:37 -0500330 }
331 }
332 return result, nil
333}
334
npujar1d86a522019-11-14 17:11:16 +0530335func (aMgr *AdapterManager) getAdapter(adapterID string) *voltha.Adapter {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400336 aMgr.lockAdaptersMap.RLock()
337 defer aMgr.lockAdaptersMap.RUnlock()
npujar1d86a522019-11-14 17:11:16 +0530338 if adapterAgent, ok := aMgr.adapterAgents[adapterID]; ok {
khenaidoo21d51152019-02-01 13:48:37 -0500339 return adapterAgent.getAdapter()
340 }
341 return nil
342}
343
344//updateAdapter updates an adapter if it exist. Otherwise, it creates it.
khenaidoo1ce37ad2019-03-24 22:07:24 -0400345func (aMgr *AdapterManager) updateAdapter(adapter *voltha.Adapter) {
khenaidoo21d51152019-02-01 13:48:37 -0500346 aMgr.lockAdaptersMap.Lock()
347 defer aMgr.lockAdaptersMap.Unlock()
A R Karthicked2a77b2019-10-08 01:40:51 +0000348 aMgr.updateAdapterWithoutLock(adapter)
349}
350
351func (aMgr *AdapterManager) updateAdapterWithoutLock(adapter *voltha.Adapter) {
khenaidoo21d51152019-02-01 13:48:37 -0500352 if adapterAgent, ok := aMgr.adapterAgents[adapter.Id]; ok {
353 adapterAgent.updateAdapter(adapter)
354 } else {
355 aMgr.adapterAgents[adapter.Id] = newAdapterAgent(adapter, nil)
356 }
357}
358
359//updateDeviceType updates an adapter if it exist. Otherwise, it creates it.
khenaidoo1ce37ad2019-03-24 22:07:24 -0400360func (aMgr *AdapterManager) updateDeviceType(deviceType *voltha.DeviceType) {
khenaidoo21d51152019-02-01 13:48:37 -0500361 aMgr.lockAdaptersMap.Lock()
362 defer aMgr.lockAdaptersMap.Unlock()
363 aMgr.lockdDeviceTypeToAdapterMap.Lock()
364 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
A R Karthicked2a77b2019-10-08 01:40:51 +0000365 aMgr.updateDeviceTypeWithoutLock(deviceType)
366}
367
368func (aMgr *AdapterManager) updateDeviceTypeWithoutLock(deviceType *voltha.DeviceType) {
khenaidoo297cd252019-02-07 22:10:23 -0500369 if adapterAgent, exist := aMgr.adapterAgents[deviceType.Adapter]; exist {
khenaidoo21d51152019-02-01 13:48:37 -0500370 adapterAgent.updateDeviceType(deviceType)
371 } else {
372 aMgr.adapterAgents[deviceType.Adapter] = newAdapterAgent(&voltha.Adapter{Id: deviceType.Adapter},
khenaidoo1ce37ad2019-03-24 22:07:24 -0400373 &voltha.DeviceTypes{Items: []*voltha.DeviceType{deviceType}})
khenaidoo21d51152019-02-01 13:48:37 -0500374 }
375 aMgr.deviceTypeToAdapterMap[deviceType.Id] = deviceType.Adapter
376}
377
Thomas Lee Se5a44012019-11-07 20:32:24 +0530378func (aMgr *AdapterManager) registerAdapter(adapter *voltha.Adapter, deviceTypes *voltha.DeviceTypes) (*voltha.CoreInstance, error) {
khenaidoo21d51152019-02-01 13:48:37 -0500379 log.Debugw("registerAdapter", log.Fields{"adapter": adapter, "deviceTypes": deviceTypes.Items})
380
381 if aMgr.getAdapter(adapter.Id) != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400382 // Already registered - Adapter may have restarted. Trigger the reconcile process for that adapter
npujar1d86a522019-11-14 17:11:16 +0530383 go func() {
npujar467fe752020-01-16 20:17:45 +0530384 err := aMgr.deviceMgr.adapterRestarted(context.Background(), adapter)
npujar1d86a522019-11-14 17:11:16 +0530385 if err != nil {
386 log.Errorw("unable-to-restart-adapter", log.Fields{"error": err})
387 }
388 }()
Thomas Lee Se5a44012019-11-07 20:32:24 +0530389 return &voltha.CoreInstance{InstanceId: aMgr.coreInstanceID}, nil
khenaidoo21d51152019-02-01 13:48:37 -0500390 }
391 // Save the adapter and the device types
Thomas Lee Se5a44012019-11-07 20:32:24 +0530392 if err := aMgr.addAdapter(adapter, true); err != nil {
393 log.Errorw("failed-to-add-adapter", log.Fields{"error": err})
394 return nil, err
395 }
396 if err := aMgr.addDeviceTypes(deviceTypes, true); err != nil {
397 log.Errorw("failed-to-add-device-types", log.Fields{"error": err})
398 return nil, err
399 }
khenaidoo21d51152019-02-01 13:48:37 -0500400
401 log.Debugw("adapter-registered", log.Fields{"adapter": adapter.Id})
402
Thomas Lee Se5a44012019-11-07 20:32:24 +0530403 return &voltha.CoreInstance{InstanceId: aMgr.coreInstanceID}, nil
khenaidoo21d51152019-02-01 13:48:37 -0500404}
405
406//getAdapterName returns the name of the device adapter that service this device type
407func (aMgr *AdapterManager) getAdapterName(deviceType string) (string, error) {
408 aMgr.lockdDeviceTypeToAdapterMap.Lock()
409 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530410 if adapterID, exist := aMgr.deviceTypeToAdapterMap[deviceType]; exist {
411 return adapterID, nil
khenaidoo21d51152019-02-01 13:48:37 -0500412 }
npujar1d86a522019-11-14 17:11:16 +0530413 return "", fmt.Errorf("Adapter-not-registered-for-device-type %s", deviceType)
khenaidoo21d51152019-02-01 13:48:37 -0500414}
415
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500416func (aMgr *AdapterManager) listDeviceTypes() []*voltha.DeviceType {
417 aMgr.lockdDeviceTypeToAdapterMap.Lock()
418 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
419
420 deviceTypes := make([]*voltha.DeviceType, 0, len(aMgr.deviceTypeToAdapterMap))
npujar1d86a522019-11-14 17:11:16 +0530421 for deviceTypeID, adapterID := range aMgr.deviceTypeToAdapterMap {
422 if adapterAgent, have := aMgr.adapterAgents[adapterID]; have {
423 if deviceType := adapterAgent.getDeviceType(deviceTypeID); deviceType != nil {
khenaidoob64fc8a2019-11-27 15:08:19 -0500424 if deviceType.Id != SentinelDevicetypeID { // don't report the sentinel
425 deviceTypes = append(deviceTypes, deviceType)
426 }
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500427 }
428 }
429 }
430 return deviceTypes
431}
432
khenaidoo21d51152019-02-01 13:48:37 -0500433// getDeviceType returns the device type proto definition given the name of the device type
khenaidoo1ce37ad2019-03-24 22:07:24 -0400434func (aMgr *AdapterManager) getDeviceType(deviceType string) *voltha.DeviceType {
khenaidoo21d51152019-02-01 13:48:37 -0500435 aMgr.lockdDeviceTypeToAdapterMap.Lock()
436 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500437
npujar1d86a522019-11-14 17:11:16 +0530438 if adapterID, exist := aMgr.deviceTypeToAdapterMap[deviceType]; exist {
439 if adapterAgent := aMgr.adapterAgents[adapterID]; adapterAgent != nil {
khenaidoo21d51152019-02-01 13:48:37 -0500440 return adapterAgent.getDeviceType(deviceType)
441 }
442 }
443 return nil
444}
445
446//adapterUpdated is a callback invoked when an adapter change has been noticed
npujar467fe752020-01-16 20:17:45 +0530447func (aMgr *AdapterManager) adapterUpdated(ctx context.Context, args ...interface{}) interface{} {
khenaidoo21d51152019-02-01 13:48:37 -0500448 log.Debugw("updateAdapter-callback", log.Fields{"argsLen": len(args)})
449
450 var previousData *voltha.Adapters
451 var latestData *voltha.Adapters
452
453 var ok bool
454 if previousData, ok = args[0].(*voltha.Adapters); !ok {
455 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
khenaidoo433f54a2019-02-05 14:02:57 -0500456 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500457 }
458 if latestData, ok = args[1].(*voltha.Adapters); !ok {
459 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
khenaidoo21d51152019-02-01 13:48:37 -0500460 return nil
461 }
462
khenaidoo433f54a2019-02-05 14:02:57 -0500463 if previousData != nil && latestData != nil {
464 if reflect.DeepEqual(previousData.Items, latestData.Items) {
465 log.Debug("update-not-required")
466 return nil
467 }
khenaidoo21d51152019-02-01 13:48:37 -0500468 }
khenaidoo433f54a2019-02-05 14:02:57 -0500469
470 if latestData != nil {
471 for _, adapter := range latestData.Items {
472 aMgr.updateAdapter(adapter)
473 }
474 }
475
khenaidoo21d51152019-02-01 13:48:37 -0500476 return nil
477}
478
479//deviceTypesUpdated is a callback invoked when a device type change has been noticed
npujar467fe752020-01-16 20:17:45 +0530480func (aMgr *AdapterManager) deviceTypesUpdated(ctx context.Context, args ...interface{}) interface{} {
khenaidoo21d51152019-02-01 13:48:37 -0500481 log.Debugw("deviceTypesUpdated-callback", log.Fields{"argsLen": len(args)})
482
483 var previousData *voltha.DeviceTypes
484 var latestData *voltha.DeviceTypes
485
486 var ok bool
487 if previousData, ok = args[0].(*voltha.DeviceTypes); !ok {
488 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
khenaidoo21d51152019-02-01 13:48:37 -0500489 return nil
490 }
491
khenaidoo433f54a2019-02-05 14:02:57 -0500492 if latestData, ok = args[1].(*voltha.DeviceTypes); !ok {
493 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
494 return nil
495 }
496
497 if previousData != nil && latestData != nil {
498 if reflect.DeepEqual(previousData.Items, latestData.Items) {
499 log.Debug("update-not-required")
500 return nil
501 }
502 }
503
504 if latestData != nil {
505 for _, dType := range latestData.Items {
506 aMgr.updateDeviceType(dType)
507 }
khenaidoo21d51152019-02-01 13:48:37 -0500508 }
509 return nil
khenaidoo1ce37ad2019-03-24 22:07:24 -0400510}