blob: 712f51df25e34f4073e37c1310ab1c812bc0efb8 [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"
Kent Hagerman16ce36a2019-12-17 13:40:53 -050024 "time"
npujar1d86a522019-11-14 17:11:16 +053025
David Bainbridged1afd662020-03-26 18:27:41 -070026 "github.com/golang/protobuf/ptypes"
27 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
28
khenaidoo21d51152019-02-01 13:48:37 -050029 "github.com/gogo/protobuf/proto"
sbarbari17d7e222019-11-05 10:02:29 -050030 "github.com/opencord/voltha-go/db/model"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080031 "github.com/opencord/voltha-lib-go/v3/pkg/log"
32 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
33 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoo21d51152019-02-01 13:48:37 -050034)
35
npujar1d86a522019-11-14 17:11:16 +053036// sentinel constants
khenaidoo21d51152019-02-01 13:48:37 -050037const (
npujar1d86a522019-11-14 17:11:16 +053038 SentinelAdapterID = "adapter_sentinel"
39 SentinelDevicetypeID = "device_type_sentinel"
khenaidoo21d51152019-02-01 13:48:37 -050040)
41
npujar1d86a522019-11-14 17:11:16 +053042// AdapterAgent represents adapter agent
khenaidoo21d51152019-02-01 13:48:37 -050043type AdapterAgent struct {
khenaidoo1ce37ad2019-03-24 22:07:24 -040044 adapter *voltha.Adapter
khenaidoo21d51152019-02-01 13:48:37 -050045 deviceTypes map[string]*voltha.DeviceType
khenaidoo1ce37ad2019-03-24 22:07:24 -040046 lock sync.RWMutex
khenaidoo21d51152019-02-01 13:48:37 -050047}
48
49func newAdapterAgent(adapter *voltha.Adapter, deviceTypes *voltha.DeviceTypes) *AdapterAgent {
50 var adapterAgent AdapterAgent
51 adapterAgent.adapter = adapter
52 adapterAgent.lock = sync.RWMutex{}
53 adapterAgent.deviceTypes = make(map[string]*voltha.DeviceType)
54 if deviceTypes != nil {
55 for _, dType := range deviceTypes.Items {
56 adapterAgent.deviceTypes[dType.Id] = dType
57 }
58 }
59 return &adapterAgent
60}
61
khenaidoo21d51152019-02-01 13:48:37 -050062func (aa *AdapterAgent) getDeviceType(deviceType string) *voltha.DeviceType {
63 aa.lock.RLock()
64 defer aa.lock.RUnlock()
65 if _, exist := aa.deviceTypes[deviceType]; exist {
66 return aa.deviceTypes[deviceType]
67 }
68 return nil
69}
70
71func (aa *AdapterAgent) getAdapter() *voltha.Adapter {
72 aa.lock.RLock()
73 defer aa.lock.RUnlock()
Girish Kumarf56a4682020-03-20 20:07:46 +000074 logger.Debugw("getAdapter", log.Fields{"adapter": aa.adapter})
khenaidoo21d51152019-02-01 13:48:37 -050075 return aa.adapter
76}
77
78func (aa *AdapterAgent) updateAdapter(adapter *voltha.Adapter) {
khenaidoo1ce37ad2019-03-24 22:07:24 -040079 aa.lock.Lock()
80 defer aa.lock.Unlock()
khenaidoo21d51152019-02-01 13:48:37 -050081 aa.adapter = adapter
82}
83
khenaidoo1ce37ad2019-03-24 22:07:24 -040084func (aa *AdapterAgent) updateDeviceType(deviceType *voltha.DeviceType) {
85 aa.lock.Lock()
86 defer aa.lock.Unlock()
khenaidoo21d51152019-02-01 13:48:37 -050087 aa.deviceTypes[deviceType.Id] = deviceType
88}
89
Kent Hagerman16ce36a2019-12-17 13:40:53 -050090// updateCommunicationTime updates the message to the specified time.
91// No attempt is made to save the time to the db, so only recent times are guaranteed to be accurate.
92func (aa *AdapterAgent) updateCommunicationTime(new time.Time) {
93 // only update if new time is not in the future, and either the old time is invalid or new time > old time
94 if last, err := ptypes.Timestamp(aa.adapter.LastCommunication); !new.After(time.Now()) && (err != nil || new.After(last)) {
95 timestamp, err := ptypes.TimestampProto(new)
96 if err != nil {
97 return // if the new time cannot be encoded, just ignore it
98 }
99
100 aa.lock.Lock()
101 defer aa.lock.Unlock()
102 aa.adapter.LastCommunication = timestamp
103 }
104}
105
npujar1d86a522019-11-14 17:11:16 +0530106// AdapterManager represents adapter manager attributes
khenaidoo21d51152019-02-01 13:48:37 -0500107type AdapterManager struct {
108 adapterAgents map[string]*AdapterAgent
109 deviceTypeToAdapterMap map[string]string
110 clusterDataProxy *model.Proxy
111 adapterProxy *model.Proxy
112 deviceTypeProxy *model.Proxy
khenaidooba6b6c42019-08-02 09:11:56 -0400113 deviceMgr *DeviceManager
npujar1d86a522019-11-14 17:11:16 +0530114 coreInstanceID string
khenaidoo21d51152019-02-01 13:48:37 -0500115 exitChannel chan int
116 lockAdaptersMap sync.RWMutex
117 lockdDeviceTypeToAdapterMap sync.RWMutex
118}
119
Kent Hagerman16ce36a2019-12-17 13:40:53 -0500120func newAdapterManager(cdProxy *model.Proxy, coreInstanceID string, kafkaClient kafka.Client, deviceMgr *DeviceManager) *AdapterManager {
121 aMgr := &AdapterManager{
122 exitChannel: make(chan int, 1),
123 coreInstanceID: coreInstanceID,
124 clusterDataProxy: cdProxy,
125 adapterAgents: make(map[string]*AdapterAgent),
126 deviceTypeToAdapterMap: make(map[string]string),
127 deviceMgr: deviceMgr,
128 }
129 kafkaClient.SubscribeForMetadata(aMgr.updateLastAdapterCommunication)
130 return aMgr
khenaidoo21d51152019-02-01 13:48:37 -0500131}
132
Thomas Lee Se5a44012019-11-07 20:32:24 +0530133func (aMgr *AdapterManager) start(ctx context.Context) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000134 logger.Info("starting-adapter-manager")
khenaidoo21d51152019-02-01 13:48:37 -0500135
136 // Load the existing adapterAgents and device types - this will also ensure the correct paths have been
137 // created if there are no data in the dB to start
Thomas Lee Se5a44012019-11-07 20:32:24 +0530138 err := aMgr.loadAdaptersAndDevicetypesInMemory()
139 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000140 logger.Errorw("Failed-to-load-adapters-and-device-types-in-memeory", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530141 return err
142 }
khenaidoo21d51152019-02-01 13:48:37 -0500143
144 //// Create the proxies
npujar467fe752020-01-16 20:17:45 +0530145 aMgr.adapterProxy, err = aMgr.clusterDataProxy.CreateProxy(ctx, "/adapters", false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530146 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000147 logger.Errorw("Failed-to-create-adapter-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530148 return err
149 }
npujar467fe752020-01-16 20:17:45 +0530150 aMgr.deviceTypeProxy, err = aMgr.clusterDataProxy.CreateProxy(ctx, "/device_types", false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530151 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000152 logger.Errorw("Failed-to-create-device-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530153 return err
154 }
khenaidoo21d51152019-02-01 13:48:37 -0500155
156 // Register the callbacks
npujar9a30c702019-11-14 17:06:39 +0530157 aMgr.adapterProxy.RegisterCallback(model.PostUpdate, aMgr.adapterUpdated)
158 aMgr.deviceTypeProxy.RegisterCallback(model.PostUpdate, aMgr.deviceTypesUpdated)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -0700159 probe.UpdateStatusFromContext(ctx, "adapter-manager", probe.ServiceStatusRunning)
Girish Kumarf56a4682020-03-20 20:07:46 +0000160 logger.Info("adapter-manager-started")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530161 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500162}
163
khenaidoo21d51152019-02-01 13:48:37 -0500164//loadAdaptersAndDevicetypesInMemory loads the existing set of adapters and device types in memory
Thomas Lee Se5a44012019-11-07 20:32:24 +0530165func (aMgr *AdapterManager) loadAdaptersAndDevicetypesInMemory() error {
khenaidoo21d51152019-02-01 13:48:37 -0500166 // Load the adapters
Thomas Lee Se5a44012019-11-07 20:32:24 +0530167 adaptersIf, err := aMgr.clusterDataProxy.List(context.Background(), "/adapters", 0, false, "")
168 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000169 logger.Errorw("Failed-to-list-adapters-from-cluster-data-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530170 return err
171 }
172 if adaptersIf != nil {
khenaidoo21d51152019-02-01 13:48:37 -0500173 for _, adapterIf := range adaptersIf.([]interface{}) {
174 if adapter, ok := adapterIf.(*voltha.Adapter); ok {
khenaidooe7be1332020-01-24 18:58:33 -0500175 if err := aMgr.addAdapter(adapter, false); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000176 logger.Errorw("failed to add adapter", log.Fields{"adapterId": adapter.Id})
khenaidooe7be1332020-01-24 18:58:33 -0500177 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000178 logger.Debugw("adapter added successfully", log.Fields{"adapterId": adapter.Id})
khenaidooe7be1332020-01-24 18:58:33 -0500179 }
khenaidoo21d51152019-02-01 13:48:37 -0500180 }
181 }
182 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000183 logger.Debug("no-existing-adapter-found")
khenaidoo21d51152019-02-01 13:48:37 -0500184 // 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 +0530185 return aMgr.addAdapter(&voltha.Adapter{Id: SentinelAdapterID}, true)
khenaidoo21d51152019-02-01 13:48:37 -0500186 }
187
188 // Load the device types
Thomas Lee Se5a44012019-11-07 20:32:24 +0530189 deviceTypesIf, err := aMgr.clusterDataProxy.List(context.Background(), "/device_types", 0, false, "")
190 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000191 logger.Errorw("Failed-to-list-device-types-from-cluster-data-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530192 return err
193 }
194 if deviceTypesIf != nil {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400195 dTypes := &voltha.DeviceTypes{Items: []*voltha.DeviceType{}}
khenaidoo21d51152019-02-01 13:48:37 -0500196 for _, deviceTypeIf := range deviceTypesIf.([]interface{}) {
197 if dType, ok := deviceTypeIf.(*voltha.DeviceType); ok {
Girish Kumarf56a4682020-03-20 20:07:46 +0000198 logger.Debugw("found-existing-device-types", log.Fields{"deviceTypes": dTypes})
khenaidoo21d51152019-02-01 13:48:37 -0500199 dTypes.Items = append(dTypes.Items, dType)
khenaidooe7be1332020-01-24 18:58:33 -0500200 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000201 logger.Errorw("not an voltha device type", log.Fields{"interface": deviceTypeIf})
khenaidoo21d51152019-02-01 13:48:37 -0500202 }
203 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530204 return aMgr.addDeviceTypes(dTypes, false)
khenaidoo21d51152019-02-01 13:48:37 -0500205 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530206
Girish Kumarf56a4682020-03-20 20:07:46 +0000207 logger.Debug("no-existing-device-type-found")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530208 // No device types data. In order to have a proxy setup for that path let's create a fake device type
209 return aMgr.addDeviceTypes(&voltha.DeviceTypes{Items: []*voltha.DeviceType{{Id: SentinelDevicetypeID, Adapter: SentinelAdapterID}}}, true)
khenaidoo21d51152019-02-01 13:48:37 -0500210}
211
Kent Hagerman16ce36a2019-12-17 13:40:53 -0500212func (aMgr *AdapterManager) updateLastAdapterCommunication(adapterID string, timestamp int64) {
213 aMgr.lockAdaptersMap.RLock()
214 adapterAgent, have := aMgr.adapterAgents[adapterID]
215 aMgr.lockAdaptersMap.RUnlock()
216
217 if have {
218 adapterAgent.updateCommunicationTime(time.Unix(timestamp/1000, timestamp%1000*1000))
219 }
220}
221
Thomas Lee Se5a44012019-11-07 20:32:24 +0530222func (aMgr *AdapterManager) addAdapter(adapter *voltha.Adapter, saveToDb bool) error {
khenaidoo21d51152019-02-01 13:48:37 -0500223 aMgr.lockAdaptersMap.Lock()
224 defer aMgr.lockAdaptersMap.Unlock()
Girish Kumarf56a4682020-03-20 20:07:46 +0000225 logger.Debugw("adding-adapter", log.Fields{"adapter": adapter})
khenaidoo21d51152019-02-01 13:48:37 -0500226 if _, exist := aMgr.adapterAgents[adapter.Id]; !exist {
227 clonedAdapter := (proto.Clone(adapter)).(*voltha.Adapter)
228 aMgr.adapterAgents[adapter.Id] = newAdapterAgent(clonedAdapter, nil)
229 if saveToDb {
230 // Save the adapter to the KV store - first check if it already exist
Thomas Lee Se5a44012019-11-07 20:32:24 +0530231 kvAdapter, err := aMgr.clusterDataProxy.Get(context.Background(), "/adapters/"+adapter.Id, 0, false, "")
232 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000233 logger.Errorw("failed-to-get-adapters-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530234 return err
235 }
236 if kvAdapter == nil {
237 added, err := aMgr.clusterDataProxy.AddWithID(context.Background(), "/adapters", adapter.Id, clonedAdapter, "")
238 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000239 logger.Errorw("failed-to-save-adapter-to-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530240 return err
241 }
242 if added == nil {
khenaidoo21d51152019-02-01 13:48:37 -0500243 //TODO: Errors when saving to KV would require a separate go routine to be launched and try the saving again
Girish Kumarf56a4682020-03-20 20:07:46 +0000244 logger.Errorw("failed-to-save-adapter", log.Fields{"adapter": adapter})
khenaidoo21d51152019-02-01 13:48:37 -0500245 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000246 logger.Debugw("adapter-saved-to-KV-Store", log.Fields{"adapter": adapter})
khenaidoo21d51152019-02-01 13:48:37 -0500247 }
248 }
249 }
250 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530251 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500252}
253
Thomas Lee Se5a44012019-11-07 20:32:24 +0530254func (aMgr *AdapterManager) addDeviceTypes(deviceTypes *voltha.DeviceTypes, saveToDb bool) error {
khenaidoo21d51152019-02-01 13:48:37 -0500255 if deviceTypes == nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530256 return fmt.Errorf("no-device-type")
khenaidoo21d51152019-02-01 13:48:37 -0500257 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000258 logger.Debugw("adding-device-types", log.Fields{"deviceTypes": deviceTypes})
khenaidoo21d51152019-02-01 13:48:37 -0500259 aMgr.lockAdaptersMap.Lock()
260 defer aMgr.lockAdaptersMap.Unlock()
261 aMgr.lockdDeviceTypeToAdapterMap.Lock()
262 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
263 for _, deviceType := range deviceTypes.Items {
264 clonedDType := (proto.Clone(deviceType)).(*voltha.DeviceType)
265 if adapterAgent, exist := aMgr.adapterAgents[clonedDType.Adapter]; exist {
266 adapterAgent.updateDeviceType(clonedDType)
267 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000268 logger.Debugw("adapter-not-exist", log.Fields{"deviceTypes": deviceTypes, "adapterId": clonedDType.Adapter})
khenaidoo1ce37ad2019-03-24 22:07:24 -0400269 aMgr.adapterAgents[clonedDType.Adapter] = newAdapterAgent(&voltha.Adapter{Id: clonedDType.Adapter}, deviceTypes)
khenaidoo21d51152019-02-01 13:48:37 -0500270 }
271 aMgr.deviceTypeToAdapterMap[clonedDType.Id] = clonedDType.Adapter
272 }
273 if saveToDb {
274 // Save the device types to the KV store as well
275 for _, deviceType := range deviceTypes.Items {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530276 dType, err := aMgr.clusterDataProxy.Get(context.Background(), "/device_types/"+deviceType.Id, 0, false, "")
277 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000278 logger.Errorw("Failed-to--device-types-from-cluster-data-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530279 return err
280 }
281 if dType == nil {
khenaidoo21d51152019-02-01 13:48:37 -0500282 // Does not exist - save it
283 clonedDType := (proto.Clone(deviceType)).(*voltha.DeviceType)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530284 added, err := aMgr.clusterDataProxy.AddWithID(context.Background(), "/device_types", deviceType.Id, clonedDType, "")
285 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000286 logger.Errorw("Failed-to-add-device-types-to-cluster-data-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530287 return err
288 }
289 if added == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000290 logger.Errorw("failed-to-save-deviceType", log.Fields{"deviceType": deviceType})
khenaidoo21d51152019-02-01 13:48:37 -0500291 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000292 logger.Debugw("device-type-saved-to-KV-Store", log.Fields{"deviceType": deviceType})
khenaidoo21d51152019-02-01 13:48:37 -0500293 }
294 }
295 }
296 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530297 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500298}
299
300func (aMgr *AdapterManager) listAdapters(ctx context.Context) (*voltha.Adapters, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400301 result := &voltha.Adapters{Items: []*voltha.Adapter{}}
302 aMgr.lockAdaptersMap.RLock()
303 defer aMgr.lockAdaptersMap.RUnlock()
khenaidoo21d51152019-02-01 13:48:37 -0500304 for _, adapterAgent := range aMgr.adapterAgents {
305 if a := adapterAgent.getAdapter(); a != nil {
npujar1d86a522019-11-14 17:11:16 +0530306 if a.Id != SentinelAdapterID { // don't report the sentinel
khenaidoo297cd252019-02-07 22:10:23 -0500307 result.Items = append(result.Items, (proto.Clone(a)).(*voltha.Adapter))
308 }
khenaidoo21d51152019-02-01 13:48:37 -0500309 }
310 }
311 return result, nil
312}
313
npujar1d86a522019-11-14 17:11:16 +0530314func (aMgr *AdapterManager) getAdapter(adapterID string) *voltha.Adapter {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400315 aMgr.lockAdaptersMap.RLock()
316 defer aMgr.lockAdaptersMap.RUnlock()
npujar1d86a522019-11-14 17:11:16 +0530317 if adapterAgent, ok := aMgr.adapterAgents[adapterID]; ok {
khenaidoo21d51152019-02-01 13:48:37 -0500318 return adapterAgent.getAdapter()
319 }
320 return nil
321}
322
323//updateAdapter updates an adapter if it exist. Otherwise, it creates it.
khenaidoo1ce37ad2019-03-24 22:07:24 -0400324func (aMgr *AdapterManager) updateAdapter(adapter *voltha.Adapter) {
khenaidoo21d51152019-02-01 13:48:37 -0500325 aMgr.lockAdaptersMap.Lock()
326 defer aMgr.lockAdaptersMap.Unlock()
A R Karthicked2a77b2019-10-08 01:40:51 +0000327 aMgr.updateAdapterWithoutLock(adapter)
328}
329
330func (aMgr *AdapterManager) updateAdapterWithoutLock(adapter *voltha.Adapter) {
khenaidoo21d51152019-02-01 13:48:37 -0500331 if adapterAgent, ok := aMgr.adapterAgents[adapter.Id]; ok {
332 adapterAgent.updateAdapter(adapter)
333 } else {
334 aMgr.adapterAgents[adapter.Id] = newAdapterAgent(adapter, nil)
335 }
336}
337
338//updateDeviceType updates an adapter if it exist. Otherwise, it creates it.
khenaidoo1ce37ad2019-03-24 22:07:24 -0400339func (aMgr *AdapterManager) updateDeviceType(deviceType *voltha.DeviceType) {
khenaidoo21d51152019-02-01 13:48:37 -0500340 aMgr.lockAdaptersMap.Lock()
341 defer aMgr.lockAdaptersMap.Unlock()
342 aMgr.lockdDeviceTypeToAdapterMap.Lock()
343 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
A R Karthicked2a77b2019-10-08 01:40:51 +0000344 aMgr.updateDeviceTypeWithoutLock(deviceType)
345}
346
347func (aMgr *AdapterManager) updateDeviceTypeWithoutLock(deviceType *voltha.DeviceType) {
khenaidoo297cd252019-02-07 22:10:23 -0500348 if adapterAgent, exist := aMgr.adapterAgents[deviceType.Adapter]; exist {
khenaidoo21d51152019-02-01 13:48:37 -0500349 adapterAgent.updateDeviceType(deviceType)
350 } else {
351 aMgr.adapterAgents[deviceType.Adapter] = newAdapterAgent(&voltha.Adapter{Id: deviceType.Adapter},
khenaidoo1ce37ad2019-03-24 22:07:24 -0400352 &voltha.DeviceTypes{Items: []*voltha.DeviceType{deviceType}})
khenaidoo21d51152019-02-01 13:48:37 -0500353 }
354 aMgr.deviceTypeToAdapterMap[deviceType.Id] = deviceType.Adapter
355}
356
Thomas Lee Se5a44012019-11-07 20:32:24 +0530357func (aMgr *AdapterManager) registerAdapter(adapter *voltha.Adapter, deviceTypes *voltha.DeviceTypes) (*voltha.CoreInstance, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000358 logger.Debugw("registerAdapter", log.Fields{"adapter": adapter, "deviceTypes": deviceTypes.Items})
khenaidoo21d51152019-02-01 13:48:37 -0500359
360 if aMgr.getAdapter(adapter.Id) != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400361 // Already registered - Adapter may have restarted. Trigger the reconcile process for that adapter
npujar1d86a522019-11-14 17:11:16 +0530362 go func() {
npujar467fe752020-01-16 20:17:45 +0530363 err := aMgr.deviceMgr.adapterRestarted(context.Background(), adapter)
npujar1d86a522019-11-14 17:11:16 +0530364 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000365 logger.Errorw("unable-to-restart-adapter", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530366 }
367 }()
Thomas Lee Se5a44012019-11-07 20:32:24 +0530368 return &voltha.CoreInstance{InstanceId: aMgr.coreInstanceID}, nil
khenaidoo21d51152019-02-01 13:48:37 -0500369 }
370 // Save the adapter and the device types
Thomas Lee Se5a44012019-11-07 20:32:24 +0530371 if err := aMgr.addAdapter(adapter, true); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000372 logger.Errorw("failed-to-add-adapter", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530373 return nil, err
374 }
375 if err := aMgr.addDeviceTypes(deviceTypes, true); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000376 logger.Errorw("failed-to-add-device-types", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530377 return nil, err
378 }
khenaidoo21d51152019-02-01 13:48:37 -0500379
Girish Kumarf56a4682020-03-20 20:07:46 +0000380 logger.Debugw("adapter-registered", log.Fields{"adapter": adapter.Id})
khenaidoo21d51152019-02-01 13:48:37 -0500381
Thomas Lee Se5a44012019-11-07 20:32:24 +0530382 return &voltha.CoreInstance{InstanceId: aMgr.coreInstanceID}, nil
khenaidoo21d51152019-02-01 13:48:37 -0500383}
384
385//getAdapterName returns the name of the device adapter that service this device type
386func (aMgr *AdapterManager) getAdapterName(deviceType string) (string, error) {
387 aMgr.lockdDeviceTypeToAdapterMap.Lock()
388 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530389 if adapterID, exist := aMgr.deviceTypeToAdapterMap[deviceType]; exist {
390 return adapterID, nil
khenaidoo21d51152019-02-01 13:48:37 -0500391 }
npujar1d86a522019-11-14 17:11:16 +0530392 return "", fmt.Errorf("Adapter-not-registered-for-device-type %s", deviceType)
khenaidoo21d51152019-02-01 13:48:37 -0500393}
394
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500395func (aMgr *AdapterManager) listDeviceTypes() []*voltha.DeviceType {
396 aMgr.lockdDeviceTypeToAdapterMap.Lock()
397 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
398
399 deviceTypes := make([]*voltha.DeviceType, 0, len(aMgr.deviceTypeToAdapterMap))
npujar1d86a522019-11-14 17:11:16 +0530400 for deviceTypeID, adapterID := range aMgr.deviceTypeToAdapterMap {
401 if adapterAgent, have := aMgr.adapterAgents[adapterID]; have {
402 if deviceType := adapterAgent.getDeviceType(deviceTypeID); deviceType != nil {
khenaidoob64fc8a2019-11-27 15:08:19 -0500403 if deviceType.Id != SentinelDevicetypeID { // don't report the sentinel
404 deviceTypes = append(deviceTypes, deviceType)
405 }
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500406 }
407 }
408 }
409 return deviceTypes
410}
411
khenaidoo21d51152019-02-01 13:48:37 -0500412// getDeviceType returns the device type proto definition given the name of the device type
khenaidoo1ce37ad2019-03-24 22:07:24 -0400413func (aMgr *AdapterManager) getDeviceType(deviceType string) *voltha.DeviceType {
khenaidoo21d51152019-02-01 13:48:37 -0500414 aMgr.lockdDeviceTypeToAdapterMap.Lock()
415 defer aMgr.lockdDeviceTypeToAdapterMap.Unlock()
Kent Hagermanc2c73ff2019-11-20 16:22:32 -0500416
npujar1d86a522019-11-14 17:11:16 +0530417 if adapterID, exist := aMgr.deviceTypeToAdapterMap[deviceType]; exist {
418 if adapterAgent := aMgr.adapterAgents[adapterID]; adapterAgent != nil {
khenaidoo21d51152019-02-01 13:48:37 -0500419 return adapterAgent.getDeviceType(deviceType)
420 }
421 }
422 return nil
423}
424
425//adapterUpdated is a callback invoked when an adapter change has been noticed
npujar467fe752020-01-16 20:17:45 +0530426func (aMgr *AdapterManager) adapterUpdated(ctx context.Context, args ...interface{}) interface{} {
Girish Kumarf56a4682020-03-20 20:07:46 +0000427 logger.Debugw("updateAdapter-callback", log.Fields{"argsLen": len(args)})
khenaidoo21d51152019-02-01 13:48:37 -0500428
429 var previousData *voltha.Adapters
430 var latestData *voltha.Adapters
431
432 var ok bool
433 if previousData, ok = args[0].(*voltha.Adapters); !ok {
Girish Kumarf56a4682020-03-20 20:07:46 +0000434 logger.Errorw("invalid-args", log.Fields{"args0": args[0]})
khenaidoo433f54a2019-02-05 14:02:57 -0500435 return nil
khenaidoo21d51152019-02-01 13:48:37 -0500436 }
437 if latestData, ok = args[1].(*voltha.Adapters); !ok {
Girish Kumarf56a4682020-03-20 20:07:46 +0000438 logger.Errorw("invalid-args", log.Fields{"args1": args[1]})
khenaidoo21d51152019-02-01 13:48:37 -0500439 return nil
440 }
441
khenaidoo433f54a2019-02-05 14:02:57 -0500442 if previousData != nil && latestData != nil {
443 if reflect.DeepEqual(previousData.Items, latestData.Items) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000444 logger.Debug("update-not-required")
khenaidoo433f54a2019-02-05 14:02:57 -0500445 return nil
446 }
khenaidoo21d51152019-02-01 13:48:37 -0500447 }
khenaidoo433f54a2019-02-05 14:02:57 -0500448
449 if latestData != nil {
450 for _, adapter := range latestData.Items {
451 aMgr.updateAdapter(adapter)
452 }
453 }
454
khenaidoo21d51152019-02-01 13:48:37 -0500455 return nil
456}
457
458//deviceTypesUpdated is a callback invoked when a device type change has been noticed
npujar467fe752020-01-16 20:17:45 +0530459func (aMgr *AdapterManager) deviceTypesUpdated(ctx context.Context, args ...interface{}) interface{} {
Girish Kumarf56a4682020-03-20 20:07:46 +0000460 logger.Debugw("deviceTypesUpdated-callback", log.Fields{"argsLen": len(args)})
khenaidoo21d51152019-02-01 13:48:37 -0500461
462 var previousData *voltha.DeviceTypes
463 var latestData *voltha.DeviceTypes
464
465 var ok bool
466 if previousData, ok = args[0].(*voltha.DeviceTypes); !ok {
Girish Kumarf56a4682020-03-20 20:07:46 +0000467 logger.Errorw("invalid-args", log.Fields{"args0": args[0]})
khenaidoo21d51152019-02-01 13:48:37 -0500468 return nil
469 }
470
khenaidoo433f54a2019-02-05 14:02:57 -0500471 if latestData, ok = args[1].(*voltha.DeviceTypes); !ok {
Girish Kumarf56a4682020-03-20 20:07:46 +0000472 logger.Errorw("invalid-args", log.Fields{"args1": args[1]})
khenaidoo433f54a2019-02-05 14:02:57 -0500473 return nil
474 }
475
476 if previousData != nil && latestData != nil {
477 if reflect.DeepEqual(previousData.Items, latestData.Items) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000478 logger.Debug("update-not-required")
khenaidoo433f54a2019-02-05 14:02:57 -0500479 return nil
480 }
481 }
482
483 if latestData != nil {
484 for _, dType := range latestData.Items {
485 aMgr.updateDeviceType(dType)
486 }
khenaidoo21d51152019-02-01 13:48:37 -0500487 }
488 return nil
khenaidoo1ce37ad2019-03-24 22:07:24 -0400489}