[RIC-433] Add DeleteEnb implementation
[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, ent string) error
56         SaveGeneralConfiguration(config *entities.GeneralConfiguration) error
57         RemoveEnb(nodebInfo *entities.NodebInfo) error
58 }
59
60 /*
61 GetRNibWriter returns reference to RNibWriter
62 */
63
64 func GetRNibWriter(sdl common.ISdlInstance, rnibWriterConfig configuration.RnibWriterConfig) RNibWriter {
65         return &rNibWriterInstance{sdl: sdl, rnibWriterConfig: rnibWriterConfig}
66 }
67
68 func (w *rNibWriterInstance) RemoveServedNrCells(inventoryName string, servedNrCells []*entities.ServedNRCell) error {
69         cellKeysToRemove := buildServedNRCellKeysToRemove(inventoryName, servedNrCells)
70         err := w.sdl.Remove(cellKeysToRemove)
71
72         if err != nil {
73                 return common.NewInternalError(err)
74         }
75
76         return nil
77 }
78
79 func (w *rNibWriterInstance) SaveGeneralConfiguration(config *entities.GeneralConfiguration) error {
80
81         err := w.SaveWithKeyAndMarshal(common.BuildGeneralConfigurationKey(), config)
82
83         if err != nil {
84                 return common.NewInternalError(err)
85         }
86
87         return nil
88 }
89
90 /*
91 SaveNodeb saves nodeB entity data in the redis DB according to the specified data model
92 */
93 func (w *rNibWriterInstance) SaveNodeb(nbIdentity *entities.NbIdentity, entity *entities.NodebInfo) error {
94         isNotEmptyIdentity := isNotEmpty(nbIdentity)
95
96         nodeType := entity.GetNodeType()
97
98         if isNotEmptyIdentity && nodeType == entities.Node_UNKNOWN {
99                 return common.NewValidationError(fmt.Sprintf("#rNibWriter.saveNodeB - Unknown responding node type, entity: %v", entity))
100         }
101
102         data, err := proto.Marshal(entity)
103
104         if err != nil {
105                 return common.NewInternalError(err)
106         }
107
108         var pairs []interface{}
109         key, rNibErr := common.ValidateAndBuildNodeBNameKey(nbIdentity.InventoryName)
110
111         if rNibErr != nil {
112                 return rNibErr
113         }
114
115         pairs = append(pairs, key, data)
116
117         if isNotEmptyIdentity {
118
119                 key, rNibErr = common.ValidateAndBuildNodeBIdKey(nodeType.String(), nbIdentity.GlobalNbId.GetPlmnId(), nbIdentity.GlobalNbId.GetNbId())
120                 if rNibErr != nil {
121                         return rNibErr
122                 }
123                 pairs = append(pairs, key, data)
124         }
125
126         if entity.GetEnb() != nil {
127                 pairs, rNibErr = appendEnbCells(nbIdentity.InventoryName, entity.GetEnb().GetServedCells(), pairs)
128                 if rNibErr != nil {
129                         return rNibErr
130                 }
131         }
132
133         if entity.GetGnb() != nil {
134                 pairs, rNibErr = appendGnbCells(nbIdentity.InventoryName, entity.GetGnb().GetServedNrCells(), pairs)
135                 if rNibErr != nil {
136                         return rNibErr
137                 }
138         }
139
140         if nodeType == entities.Node_ENB {
141                 err = w.sdl.SetAndPublish([]string{w.rnibWriterConfig.RanManipulationMessageChannel, fmt.Sprintf("%s_%s", entity.RanName, RanAddedEvent)}, pairs)
142         } else {
143                 err = w.sdl.Set(pairs)
144         }
145
146         if err != nil {
147                 return common.NewInternalError(err)
148         }
149
150         ranNameIdentity := &entities.NbIdentity{InventoryName: nbIdentity.InventoryName}
151
152         if isNotEmptyIdentity {
153                 err := w.removeNbIdentity(entities.Node_UNKNOWN, ranNameIdentity)
154                 if err != nil {
155                         return common.NewInternalError(err)
156                 }
157         } else {
158                 nbIdentity = ranNameIdentity
159         }
160
161         nbIdData, err := proto.Marshal(nbIdentity)
162
163         if err != nil {
164                 return common.NewInternalError(err)
165         }
166
167         err = w.sdl.AddMember(nodeType.String(), nbIdData)
168
169         if err != nil {
170                 return common.NewInternalError(err)
171         }
172         return nil
173 }
174
175 func (w *rNibWriterInstance) UpdateGnbCells(nodebInfo *entities.NodebInfo, servedNrCells []*entities.ServedNRCell) error {
176
177         pairs, err := buildUpdateNodebInfoPairs(nodebInfo)
178
179         if err != nil {
180                 return err
181         }
182
183         pairs, err = appendGnbCells(nodebInfo.RanName, servedNrCells, pairs)
184
185         if err != nil {
186                 return err
187         }
188
189         err = w.sdl.Set(pairs)
190
191         if err != nil {
192                 return common.NewInternalError(err)
193         }
194
195         return nil
196 }
197
198 func buildServedNRCellKeysToRemove(inventoryName string, servedNrCellsToRemove []*entities.ServedNRCell) []string {
199
200         cellKeysToRemove := []string{}
201
202         for _, cell := range servedNrCellsToRemove {
203
204                 key, _ := common.ValidateAndBuildNrCellIdKey(cell.GetServedNrCellInformation().GetCellId())
205
206                 if len(key) != 0 {
207                         cellKeysToRemove = append(cellKeysToRemove, key)
208                 }
209
210                 key, _ = common.ValidateAndBuildCellNamePciKey(inventoryName, cell.GetServedNrCellInformation().GetNrPci())
211
212                 if len(key) != 0 {
213                         cellKeysToRemove = append(cellKeysToRemove, key)
214                 }
215         }
216
217         return cellKeysToRemove
218 }
219
220 func buildServedCellInfoKeysToRemove(inventoryName string, servedCellsToRemove []*entities.ServedCellInfo) []string {
221
222         cellKeysToRemove := []string{}
223
224         for _, cell := range servedCellsToRemove {
225
226                 key, _ := common.ValidateAndBuildCellIdKey(cell.GetCellId())
227
228                 if len(key) != 0 {
229                         cellKeysToRemove = append(cellKeysToRemove, key)
230                 }
231
232                 key, _ = common.ValidateAndBuildCellNamePciKey(inventoryName, cell.GetPci())
233
234                 if len(key) != 0 {
235                         cellKeysToRemove = append(cellKeysToRemove, key)
236                 }
237         }
238
239         return cellKeysToRemove
240 }
241
242 func buildUpdateNodebInfoPairs(nodebInfo *entities.NodebInfo) ([]interface{}, error) {
243         nodebNameKey, rNibErr := common.ValidateAndBuildNodeBNameKey(nodebInfo.GetRanName())
244
245         if rNibErr != nil {
246                 return []interface{}{}, rNibErr
247         }
248
249         nodebIdKey, buildNodebIdKeyError := common.ValidateAndBuildNodeBIdKey(nodebInfo.GetNodeType().String(), nodebInfo.GlobalNbId.GetPlmnId(), nodebInfo.GlobalNbId.GetNbId())
250
251         data, err := proto.Marshal(nodebInfo)
252
253         if err != nil {
254                 return []interface{}{}, common.NewInternalError(err)
255         }
256
257         pairs := []interface{}{nodebNameKey, data}
258
259         if buildNodebIdKeyError == nil {
260                 pairs = append(pairs, nodebIdKey, data)
261         }
262
263         return pairs, nil
264 }
265
266 func (w *rNibWriterInstance) buildRemoveEnbKeys(nodebInfo *entities.NodebInfo) ([]string, error) {
267         keys := buildServedCellInfoKeysToRemove(nodebInfo.GetRanName(), nodebInfo.GetEnb().GetServedCells())
268
269         nodebNameKey, rNibErr := common.ValidateAndBuildNodeBNameKey(nodebInfo.GetRanName())
270
271         if rNibErr != nil {
272                 return []string{}, rNibErr
273         }
274
275         keys = append(keys, nodebNameKey)
276
277         nodebIdKey, buildNodebIdKeyError := common.ValidateAndBuildNodeBIdKey(nodebInfo.GetNodeType().String(), nodebInfo.GlobalNbId.GetPlmnId(), nodebInfo.GlobalNbId.GetNbId())
278
279         if buildNodebIdKeyError == nil {
280                 keys = append(keys, nodebIdKey)
281         }
282
283         return keys, nil
284 }
285
286 func (w *rNibWriterInstance) removeNbIdentity(nodeType entities.Node_Type ,nbIdentity *entities.NbIdentity) error {
287         nbIdData, err := proto.Marshal(nbIdentity)
288         if err != nil {
289                 return common.NewInternalError(err)
290         }
291         err = w.sdl.RemoveMember(nodeType.String(), nbIdData)
292         if err != nil {
293                 return common.NewInternalError(err)
294         }
295         return nil
296 }
297
298 /*
299 UpdateNodebInfo...
300 */
301 func (w *rNibWriterInstance) UpdateNodebInfo(nodebInfo *entities.NodebInfo) error {
302
303         pairs, err := buildUpdateNodebInfoPairs(nodebInfo)
304
305         if err != nil {
306                 return err
307         }
308
309         err = w.sdl.Set(pairs)
310
311         if err != nil {
312                 return common.NewInternalError(err)
313         }
314
315         return nil
316 }
317
318 /*
319 SaveRanLoadInformation stores ran load information for the provided ran
320 */
321 func (w *rNibWriterInstance) SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error {
322
323         key, rnibErr := common.ValidateAndBuildRanLoadInformationKey(inventoryName)
324
325         if rnibErr != nil {
326                 return rnibErr
327         }
328
329         data, err := proto.Marshal(ranLoadInformation)
330
331         if err != nil {
332                 return common.NewInternalError(err)
333         }
334
335         var pairs []interface{}
336         pairs = append(pairs, key, data)
337
338         err = w.sdl.Set(pairs)
339
340         if err != nil {
341                 return common.NewInternalError(err)
342         }
343
344         return nil
345 }
346
347 func (w *rNibWriterInstance) SaveE2TInstance(e2tInstance *entities.E2TInstance) error {
348
349         key, rnibErr := common.ValidateAndBuildE2TInstanceKey(e2tInstance.Address)
350
351         if rnibErr != nil {
352                 return rnibErr
353         }
354
355         data, err := json.Marshal(e2tInstance)
356
357         if err != nil {
358                 return common.NewInternalError(err)
359         }
360
361         var pairs []interface{}
362         pairs = append(pairs, key, data)
363
364         err = w.sdl.Set(pairs)
365
366         if err != nil {
367                 return common.NewInternalError(err)
368         }
369
370         return nil
371 }
372
373 func (w *rNibWriterInstance) SaveE2TAddresses(addresses []string) error {
374
375         data, err := json.Marshal(addresses)
376
377         if err != nil {
378                 return common.NewInternalError(err)
379         }
380
381         var pairs []interface{}
382         pairs = append(pairs, E2TAddressesKey, data)
383
384         err = w.sdl.Set(pairs)
385
386         if err != nil {
387                 return common.NewInternalError(err)
388         }
389
390         return nil
391 }
392
393 func (w *rNibWriterInstance) RemoveE2TInstance(address string) error {
394         key, rNibErr := common.ValidateAndBuildE2TInstanceKey(address)
395         if rNibErr != nil {
396                 return rNibErr
397         }
398         err := w.sdl.Remove([]string{key})
399
400         if err != nil {
401                 return common.NewInternalError(err)
402         }
403         return nil
404 }
405
406 func (w *rNibWriterInstance) SaveWithKeyAndMarshal(key string, entity interface{}) error {
407
408         data, err := json.Marshal(entity)
409
410         if err != nil {
411                 return common.NewInternalError(err)
412         }
413
414         var pairs []interface{}
415         pairs = append(pairs, key, data)
416
417         err = w.sdl.Set(pairs)
418
419         if err != nil {
420                 return common.NewInternalError(err)
421         }
422
423         return nil
424 }
425
426 /*
427 UpdateNodebInfoOnConnectionStatusInversion...
428 */
429 func (w *rNibWriterInstance) UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, event string) error {
430
431         pairs, err := buildUpdateNodebInfoPairs(nodebInfo)
432
433         if err != nil {
434                 return err
435         }
436
437         err = w.sdl.SetAndPublish([]string{w.rnibWriterConfig.StateChangeMessageChannel, event}, pairs)
438
439         if err != nil {
440                 return common.NewInternalError(err)
441         }
442
443         return nil
444 }
445
446 func (w *rNibWriterInstance) RemoveEnb(nodebInfo *entities.NodebInfo) error {
447         ranNameIdentity := &entities.NbIdentity{InventoryName: nodebInfo.RanName, GlobalNbId: nodebInfo.GetGlobalNbId()}
448         err := w.removeNbIdentity(entities.Node_ENB, ranNameIdentity)
449         if err != nil {
450                 return err
451         }
452
453         keysToRemove, err := w.buildRemoveEnbKeys(nodebInfo)
454         if err != nil {
455                 return err
456         }
457
458         err = w.sdl.RemoveAndPublish([]string{w.rnibWriterConfig.RanManipulationMessageChannel, fmt.Sprintf("%s_%s", nodebInfo.RanName, RanDeletedEvent)}, keysToRemove)
459
460         if err != nil {
461                 return common.NewInternalError(err)
462         }
463
464         return nil
465 }
466
467 /*
468 Close the writer
469 */
470 func Close() {
471         //Nothing to do
472 }
473
474 func appendEnbCells(inventoryName string, cells []*entities.ServedCellInfo, pairs []interface{}) ([]interface{}, error) {
475         for _, cell := range cells {
476                 cellEntity := entities.Cell{Type: entities.Cell_LTE_CELL, Cell: &entities.Cell_ServedCellInfo{ServedCellInfo: cell}}
477                 cellData, err := proto.Marshal(&cellEntity)
478                 if err != nil {
479                         return pairs, common.NewInternalError(err)
480                 }
481                 key, rNibErr := common.ValidateAndBuildCellIdKey(cell.GetCellId())
482                 if rNibErr != nil {
483                         return pairs, rNibErr
484                 }
485                 pairs = append(pairs, key, cellData)
486                 key, rNibErr = common.ValidateAndBuildCellNamePciKey(inventoryName, cell.GetPci())
487                 if rNibErr != nil {
488                         return pairs, rNibErr
489                 }
490                 pairs = append(pairs, key, cellData)
491         }
492         return pairs, nil
493 }
494
495 func appendGnbCells(inventoryName string, cells []*entities.ServedNRCell, pairs []interface{}) ([]interface{}, error) {
496         for _, cell := range cells {
497                 cellEntity := entities.Cell{Type: entities.Cell_NR_CELL, Cell: &entities.Cell_ServedNrCell{ServedNrCell: cell}}
498                 cellData, err := proto.Marshal(&cellEntity)
499                 if err != nil {
500                         return pairs, common.NewInternalError(err)
501                 }
502                 key, rNibErr := common.ValidateAndBuildNrCellIdKey(cell.GetServedNrCellInformation().GetCellId())
503                 if rNibErr != nil {
504                         return pairs, rNibErr
505                 }
506                 pairs = append(pairs, key, cellData)
507                 key, rNibErr = common.ValidateAndBuildCellNamePciKey(inventoryName, cell.GetServedNrCellInformation().GetNrPci())
508                 if rNibErr != nil {
509                         return pairs, rNibErr
510                 }
511                 pairs = append(pairs, key, cellData)
512         }
513         return pairs, nil
514 }
515
516 func isNotEmpty(nbIdentity *entities.NbIdentity) bool {
517         return nbIdentity.GlobalNbId != nil && nbIdentity.GlobalNbId.PlmnId != "" && nbIdentity.GlobalNbId.NbId != ""
518 }