[RIC-431] Add Enb | Configuration changes | Some refactoring | K8S yamls
[ric-plt/e2mgr.git] / E2Manager / rNibWriter / rNibWriter.go
1 //
2 // Copyright 2019 AT&T Intellectual Property
3 // Copyright 2019 Nokia
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //      http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
18 //  platform project (RICP).
19
20 package rNibWriter
21
22 import (
23         "e2mgr/configuration"
24         "encoding/json"
25         "fmt"
26         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
27         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
28         "github.com/golang/protobuf/proto"
29 )
30
31 const (
32         E2TAddressesKey = "E2TAddresses"
33         RanAddedEvent   = "ADDED"
34         RanUpdatedEvent = "UPDATED"
35         RanDeletedEvent = "DELETED"
36 )
37
38 type rNibWriterInstance struct {
39         sdl              common.ISdlInstance
40         rnibWriterConfig configuration.RnibWriterConfig
41 }
42
43 /*
44 RNibWriter interface allows saving data to the redis DB
45 */
46 type RNibWriter interface {
47         SaveNodeb(nbIdentity *entities.NbIdentity, nb *entities.NodebInfo) error
48         UpdateNodebInfo(nodebInfo *entities.NodebInfo) error
49         SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error
50         SaveE2TInstance(e2tInstance *entities.E2TInstance) error
51         SaveE2TAddresses(addresses []string) error
52         RemoveE2TInstance(e2tAddress string) error
53         UpdateGnbCells(nodebInfo *entities.NodebInfo, servedNrCells []*entities.ServedNRCell) error
54         RemoveServedNrCells(inventoryName string, servedNrCells []*entities.ServedNRCell) error
55         UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, stateChangeMessageChannel string, event string) error
56         SaveGeneralConfiguration(config *entities.GeneralConfiguration) error
57 }
58
59 /*
60 GetRNibWriter returns reference to RNibWriter
61 */
62
63 func GetRNibWriter(sdl common.ISdlInstance, rnibWriterConfig configuration.RnibWriterConfig) RNibWriter {
64         return &rNibWriterInstance{sdl: sdl, rnibWriterConfig: rnibWriterConfig}
65 }
66
67 func (w *rNibWriterInstance) RemoveServedNrCells(inventoryName string, servedNrCells []*entities.ServedNRCell) error {
68         cellKeysToRemove := buildCellKeysToRemove(inventoryName, servedNrCells)
69         err := w.sdl.Remove(cellKeysToRemove)
70
71         if err != nil {
72                 return common.NewInternalError(err)
73         }
74
75         return nil
76 }
77
78 func (w *rNibWriterInstance) SaveGeneralConfiguration(config *entities.GeneralConfiguration) error {
79
80         err := w.SaveWithKeyAndMarshal(common.BuildGeneralConfigurationKey(), config)
81
82         if err != nil {
83                 return common.NewInternalError(err)
84         }
85
86         return nil
87 }
88
89 /*
90 SaveNodeb saves nodeB entity data in the redis DB according to the specified data model
91 */
92 func (w *rNibWriterInstance) SaveNodeb(nbIdentity *entities.NbIdentity, entity *entities.NodebInfo) error {
93         isNotEmptyIdentity := isNotEmpty(nbIdentity)
94
95         nodeType := entity.GetNodeType()
96
97         if isNotEmptyIdentity && nodeType == entities.Node_UNKNOWN {
98                 return common.NewValidationError(fmt.Sprintf("#rNibWriter.saveNodeB - Unknown responding node type, entity: %v", entity))
99         }
100
101         data, err := proto.Marshal(entity)
102
103         if err != nil {
104                 return common.NewInternalError(err)
105         }
106
107         var pairs []interface{}
108         key, rNibErr := common.ValidateAndBuildNodeBNameKey(nbIdentity.InventoryName)
109
110         if rNibErr != nil {
111                 return rNibErr
112         }
113
114         pairs = append(pairs, key, data)
115
116         if isNotEmptyIdentity {
117
118                 key, rNibErr = common.ValidateAndBuildNodeBIdKey(nodeType.String(), nbIdentity.GlobalNbId.GetPlmnId(), nbIdentity.GlobalNbId.GetNbId())
119                 if rNibErr != nil {
120                         return rNibErr
121                 }
122                 pairs = append(pairs, key, data)
123         }
124
125         if entity.GetEnb() != nil {
126                 pairs, rNibErr = appendEnbCells(nbIdentity.InventoryName, entity.GetEnb().GetServedCells(), pairs)
127                 if rNibErr != nil {
128                         return rNibErr
129                 }
130         }
131
132         if entity.GetGnb() != nil {
133                 pairs, rNibErr = appendGnbCells(nbIdentity.InventoryName, entity.GetGnb().GetServedNrCells(), pairs)
134                 if rNibErr != nil {
135                         return rNibErr
136                 }
137         }
138
139         if nodeType == entities.Node_ENB {
140                 err = w.sdl.SetAndPublish([]string{w.rnibWriterConfig.RanManipulationMessageChannel, fmt.Sprintf("%s_%s", entity.RanName, RanAddedEvent)}, pairs)
141         } else {
142                 err = w.sdl.Set(pairs)
143         }
144
145         if err != nil {
146                 return common.NewInternalError(err)
147         }
148
149         ranNameIdentity := &entities.NbIdentity{InventoryName: nbIdentity.InventoryName}
150
151         if isNotEmptyIdentity {
152                 nbIdData, err := proto.Marshal(ranNameIdentity)
153                 if err != nil {
154                         return common.NewInternalError(err)
155                 }
156                 err = w.sdl.RemoveMember(entities.Node_UNKNOWN.String(), nbIdData)
157                 if err != nil {
158                         return common.NewInternalError(err)
159                 }
160         } else {
161                 nbIdentity = ranNameIdentity
162         }
163
164         nbIdData, err := proto.Marshal(nbIdentity)
165
166         if err != nil {
167                 return common.NewInternalError(err)
168         }
169
170         err = w.sdl.AddMember(nodeType.String(), nbIdData)
171
172         if err != nil {
173                 return common.NewInternalError(err)
174         }
175         return nil
176 }
177
178 func (w *rNibWriterInstance) UpdateGnbCells(nodebInfo *entities.NodebInfo, servedNrCells []*entities.ServedNRCell) error {
179
180         pairs, err := buildUpdateNodebInfoPairs(nodebInfo)
181
182         if err != nil {
183                 return err
184         }
185
186         pairs, err = appendGnbCells(nodebInfo.RanName, servedNrCells, pairs)
187
188         if err != nil {
189                 return err
190         }
191
192         err = w.sdl.Set(pairs)
193
194         if err != nil {
195                 return common.NewInternalError(err)
196         }
197
198         return nil
199 }
200
201 func buildCellKeysToRemove(inventoryName string, servedNrCellsToRemove []*entities.ServedNRCell) []string {
202
203         cellKeysToRemove := []string{}
204
205         for _, cell := range servedNrCellsToRemove {
206
207                 key, _ := common.ValidateAndBuildNrCellIdKey(cell.GetServedNrCellInformation().GetCellId())
208
209                 if len(key) != 0 {
210                         cellKeysToRemove = append(cellKeysToRemove, key)
211                 }
212
213                 key, _ = common.ValidateAndBuildCellNamePciKey(inventoryName, cell.GetServedNrCellInformation().GetNrPci())
214
215                 if len(key) != 0 {
216                         cellKeysToRemove = append(cellKeysToRemove, key)
217                 }
218         }
219
220         return cellKeysToRemove
221 }
222
223 func buildUpdateNodebInfoPairs(nodebInfo *entities.NodebInfo) ([]interface{}, error) {
224         nodebNameKey, rNibErr := common.ValidateAndBuildNodeBNameKey(nodebInfo.GetRanName())
225
226         if rNibErr != nil {
227                 return []interface{}{}, rNibErr
228         }
229
230         nodebIdKey, buildNodebIdKeyError := common.ValidateAndBuildNodeBIdKey(nodebInfo.GetNodeType().String(), nodebInfo.GlobalNbId.GetPlmnId(), nodebInfo.GlobalNbId.GetNbId())
231
232         data, err := proto.Marshal(nodebInfo)
233
234         if err != nil {
235                 return []interface{}{}, common.NewInternalError(err)
236         }
237
238         pairs := []interface{}{nodebNameKey, data}
239
240         if buildNodebIdKeyError == nil {
241                 pairs = append(pairs, nodebIdKey, data)
242         }
243
244         return pairs, nil
245 }
246
247 /*
248 UpdateNodebInfo...
249 */
250 func (w *rNibWriterInstance) UpdateNodebInfo(nodebInfo *entities.NodebInfo) error {
251
252         pairs, err := buildUpdateNodebInfoPairs(nodebInfo)
253
254         if err != nil {
255                 return err
256         }
257
258         err = w.sdl.Set(pairs)
259
260         if err != nil {
261                 return common.NewInternalError(err)
262         }
263
264         return nil
265 }
266
267 /*
268 SaveRanLoadInformation stores ran load information for the provided ran
269 */
270 func (w *rNibWriterInstance) SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error {
271
272         key, rnibErr := common.ValidateAndBuildRanLoadInformationKey(inventoryName)
273
274         if rnibErr != nil {
275                 return rnibErr
276         }
277
278         data, err := proto.Marshal(ranLoadInformation)
279
280         if err != nil {
281                 return common.NewInternalError(err)
282         }
283
284         var pairs []interface{}
285         pairs = append(pairs, key, data)
286
287         err = w.sdl.Set(pairs)
288
289         if err != nil {
290                 return common.NewInternalError(err)
291         }
292
293         return nil
294 }
295
296 func (w *rNibWriterInstance) SaveE2TInstance(e2tInstance *entities.E2TInstance) error {
297
298         key, rnibErr := common.ValidateAndBuildE2TInstanceKey(e2tInstance.Address)
299
300         if rnibErr != nil {
301                 return rnibErr
302         }
303
304         data, err := json.Marshal(e2tInstance)
305
306         if err != nil {
307                 return common.NewInternalError(err)
308         }
309
310         var pairs []interface{}
311         pairs = append(pairs, key, data)
312
313         err = w.sdl.Set(pairs)
314
315         if err != nil {
316                 return common.NewInternalError(err)
317         }
318
319         return nil
320 }
321
322 func (w *rNibWriterInstance) SaveE2TAddresses(addresses []string) error {
323
324         data, err := json.Marshal(addresses)
325
326         if err != nil {
327                 return common.NewInternalError(err)
328         }
329
330         var pairs []interface{}
331         pairs = append(pairs, E2TAddressesKey, data)
332
333         err = w.sdl.Set(pairs)
334
335         if err != nil {
336                 return common.NewInternalError(err)
337         }
338
339         return nil
340 }
341
342 func (w *rNibWriterInstance) RemoveE2TInstance(address string) error {
343         key, rNibErr := common.ValidateAndBuildE2TInstanceKey(address)
344         if rNibErr != nil {
345                 return rNibErr
346         }
347         err := w.sdl.Remove([]string{key})
348
349         if err != nil {
350                 return common.NewInternalError(err)
351         }
352         return nil
353 }
354
355 func (w *rNibWriterInstance) SaveWithKeyAndMarshal(key string, entity interface{}) error {
356
357         data, err := json.Marshal(entity)
358
359         if err != nil {
360                 return common.NewInternalError(err)
361         }
362
363         var pairs []interface{}
364         pairs = append(pairs, key, data)
365
366         err = w.sdl.Set(pairs)
367
368         if err != nil {
369                 return common.NewInternalError(err)
370         }
371
372         return nil
373 }
374
375 /*
376 UpdateNodebInfoOnConnectionStatusInversion...
377 */
378 func (w *rNibWriterInstance) UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, stateChangeMessageChannel string, event string) error {
379
380         pairs, err := buildUpdateNodebInfoPairs(nodebInfo)
381
382         if err != nil {
383                 return err
384         }
385
386         err = w.sdl.SetAndPublish([]string{stateChangeMessageChannel, event}, pairs)
387
388         if err != nil {
389                 return common.NewInternalError(err)
390         }
391
392         return nil
393 }
394
395 /*
396 Close the writer
397 */
398 func Close() {
399         //Nothing to do
400 }
401
402 func appendEnbCells(inventoryName string, cells []*entities.ServedCellInfo, pairs []interface{}) ([]interface{}, error) {
403         for _, cell := range cells {
404                 cellEntity := entities.Cell{Type: entities.Cell_LTE_CELL, Cell: &entities.Cell_ServedCellInfo{ServedCellInfo: cell}}
405                 cellData, err := proto.Marshal(&cellEntity)
406                 if err != nil {
407                         return pairs, common.NewInternalError(err)
408                 }
409                 key, rNibErr := common.ValidateAndBuildCellIdKey(cell.GetCellId())
410                 if rNibErr != nil {
411                         return pairs, rNibErr
412                 }
413                 pairs = append(pairs, key, cellData)
414                 key, rNibErr = common.ValidateAndBuildCellNamePciKey(inventoryName, cell.GetPci())
415                 if rNibErr != nil {
416                         return pairs, rNibErr
417                 }
418                 pairs = append(pairs, key, cellData)
419         }
420         return pairs, nil
421 }
422
423 func appendGnbCells(inventoryName string, cells []*entities.ServedNRCell, pairs []interface{}) ([]interface{}, error) {
424         for _, cell := range cells {
425                 cellEntity := entities.Cell{Type: entities.Cell_NR_CELL, Cell: &entities.Cell_ServedNrCell{ServedNrCell: cell}}
426                 cellData, err := proto.Marshal(&cellEntity)
427                 if err != nil {
428                         return pairs, common.NewInternalError(err)
429                 }
430                 key, rNibErr := common.ValidateAndBuildNrCellIdKey(cell.GetServedNrCellInformation().GetCellId())
431                 if rNibErr != nil {
432                         return pairs, rNibErr
433                 }
434                 pairs = append(pairs, key, cellData)
435                 key, rNibErr = common.ValidateAndBuildCellNamePciKey(inventoryName, cell.GetServedNrCellInformation().GetNrPci())
436                 if rNibErr != nil {
437                         return pairs, rNibErr
438                 }
439                 pairs = append(pairs, key, cellData)
440         }
441         return pairs, nil
442 }
443
444 func isNotEmpty(nbIdentity *entities.NbIdentity) bool {
445         return nbIdentity.GlobalNbId != nil && nbIdentity.GlobalNbId.PlmnId != "" && nbIdentity.GlobalNbId.NbId != ""
446 }