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