RIC-547 - E2M publish SDL event - Automation
[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         "encoding/json"
24         "fmt"
25         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
26         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
27         "github.com/golang/protobuf/proto"
28 )
29
30 const E2TAddressesKey = "E2TAddresses"
31
32 type rNibWriterInstance struct {
33         sdl common.ISdlInstance
34 }
35
36 /*
37 RNibWriter interface allows saving data to the redis DB
38 */
39 type RNibWriter interface {
40         SaveNodeb(nbIdentity *entities.NbIdentity, nb *entities.NodebInfo) error
41         UpdateNodebInfo(nodebInfo *entities.NodebInfo) error
42         SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error
43         SaveE2TInstance(e2tInstance *entities.E2TInstance) error
44         SaveE2TAddresses(addresses []string) error
45         RemoveE2TInstance(e2tAddress string) error
46         UpdateGnbCells(nodebInfo *entities.NodebInfo, servedNrCells []*entities.ServedNRCell) error
47         RemoveServedNrCells(inventoryName string, servedNrCells []*entities.ServedNRCell) error
48         UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, stateChangeMessageChannel string, event string) error
49         SaveGeneralConfiguration(config *entities.GeneralConfiguration) error
50 }
51
52 /*
53 GetRNibWriter returns reference to RNibWriter
54 */
55
56 func GetRNibWriter(sdl common.ISdlInstance) RNibWriter {
57         return &rNibWriterInstance{sdl: sdl}
58 }
59
60
61 func (w *rNibWriterInstance) RemoveServedNrCells(inventoryName string, servedNrCells []*entities.ServedNRCell) error {
62         cellKeysToRemove := buildCellKeysToRemove(inventoryName, servedNrCells)
63         err := w.sdl.Remove(cellKeysToRemove)
64
65         if err != nil {
66                 return common.NewInternalError(err)
67         }
68
69         return nil
70 }
71
72 func (w *rNibWriterInstance) SaveGeneralConfiguration(config *entities.GeneralConfiguration) error {
73
74         err := w.SaveWithKeyAndMarshal(common.BuildGeneralConfigurationKey(), config)
75
76         if err != nil {
77                 return common.NewInternalError(err)
78         }
79
80         return nil
81 }
82
83 /*
84 SaveNodeb saves nodeB entity data in the redis DB according to the specified data model
85 */
86 func (w *rNibWriterInstance) SaveNodeb(nbIdentity *entities.NbIdentity, entity *entities.NodebInfo) error {
87         isNotEmptyIdentity := isNotEmpty(nbIdentity)
88
89         if isNotEmptyIdentity && entity.GetNodeType() == entities.Node_UNKNOWN {
90                 return common.NewValidationError(fmt.Sprintf("#rNibWriter.saveNodeB - Unknown responding node type, entity: %v", entity))
91         }
92         data, err := proto.Marshal(entity)
93         if err != nil {
94                 return common.NewInternalError(err)
95         }
96         var pairs []interface{}
97         key, rNibErr := common.ValidateAndBuildNodeBNameKey(nbIdentity.InventoryName)
98         if rNibErr != nil {
99                 return rNibErr
100         }
101         pairs = append(pairs, key, data)
102
103         if isNotEmptyIdentity {
104                 key, rNibErr = common.ValidateAndBuildNodeBIdKey(entity.GetNodeType().String(), nbIdentity.GlobalNbId.GetPlmnId(), nbIdentity.GlobalNbId.GetNbId())
105                 if rNibErr != nil {
106                         return rNibErr
107                 }
108                 pairs = append(pairs, key, data)
109         }
110
111         if entity.GetEnb() != nil {
112                 pairs, rNibErr = appendEnbCells(nbIdentity.InventoryName, entity.GetEnb().GetServedCells(), pairs)
113                 if rNibErr != nil {
114                         return rNibErr
115                 }
116         }
117         if entity.GetGnb() != nil {
118                 pairs, rNibErr = appendGnbCells(nbIdentity.InventoryName, entity.GetGnb().GetServedNrCells(), pairs)
119                 if rNibErr != nil {
120                         return rNibErr
121                 }
122         }
123         err = w.sdl.Set(pairs)
124         if err != nil {
125                 return common.NewInternalError(err)
126         }
127
128         ranNameIdentity := &entities.NbIdentity{InventoryName: nbIdentity.InventoryName}
129
130         if isNotEmptyIdentity {
131                 nbIdData, err := proto.Marshal(ranNameIdentity)
132                 if err != nil {
133                         return common.NewInternalError(err)
134                 }
135                 err = w.sdl.RemoveMember(entities.Node_UNKNOWN.String(), nbIdData)
136                 if err != nil {
137                         return common.NewInternalError(err)
138                 }
139         } else {
140                 nbIdentity = ranNameIdentity
141         }
142
143         nbIdData, err := proto.Marshal(nbIdentity)
144         if err != nil {
145                 return common.NewInternalError(err)
146         }
147         err = w.sdl.AddMember(entity.GetNodeType().String(), nbIdData)
148         if err != nil {
149                 return common.NewInternalError(err)
150         }
151         return nil
152 }
153
154 func (w *rNibWriterInstance) UpdateGnbCells(nodebInfo *entities.NodebInfo, servedNrCells []*entities.ServedNRCell) error {
155
156         pairs, err := buildUpdateNodebInfoPairs(nodebInfo)
157
158         if err != nil {
159                 return err
160         }
161
162         pairs, err = appendGnbCells(nodebInfo.RanName, servedNrCells, pairs)
163
164         if err != nil {
165                 return err
166         }
167
168         err = w.sdl.Set(pairs)
169
170         if err != nil {
171                 return common.NewInternalError(err)
172         }
173
174         return nil
175 }
176
177 func buildCellKeysToRemove(inventoryName string, servedNrCellsToRemove []*entities.ServedNRCell) []string {
178
179         cellKeysToRemove := []string{}
180
181         for _, cell := range servedNrCellsToRemove {
182
183                 key, _ := common.ValidateAndBuildNrCellIdKey(cell.GetServedNrCellInformation().GetCellId())
184
185                 if len(key) != 0 {
186                         cellKeysToRemove = append(cellKeysToRemove, key)
187                 }
188
189                 key, _ = common.ValidateAndBuildCellNamePciKey(inventoryName, cell.GetServedNrCellInformation().GetNrPci())
190
191                 if len(key) != 0 {
192                         cellKeysToRemove = append(cellKeysToRemove, key)
193                 }
194         }
195
196         return cellKeysToRemove
197 }
198
199 func buildUpdateNodebInfoPairs(nodebInfo *entities.NodebInfo) ([]interface{}, error) {
200         nodebNameKey, rNibErr := common.ValidateAndBuildNodeBNameKey(nodebInfo.GetRanName())
201
202         if rNibErr != nil {
203                 return []interface{}{}, rNibErr
204         }
205
206         nodebIdKey, buildNodebIdKeyError := common.ValidateAndBuildNodeBIdKey(nodebInfo.GetNodeType().String(), nodebInfo.GlobalNbId.GetPlmnId(), nodebInfo.GlobalNbId.GetNbId())
207
208         data, err := proto.Marshal(nodebInfo)
209
210         if err != nil {
211                 return []interface{}{}, common.NewInternalError(err)
212         }
213
214         pairs := []interface{}{nodebNameKey, data}
215
216         if buildNodebIdKeyError == nil {
217                 pairs = append(pairs, nodebIdKey, data)
218         }
219
220         return pairs, nil
221 }
222
223 /*
224 UpdateNodebInfo...
225 */
226 func (w *rNibWriterInstance) UpdateNodebInfo(nodebInfo *entities.NodebInfo) error {
227
228         pairs, err := buildUpdateNodebInfoPairs(nodebInfo)
229
230         if err != nil {
231                 return err
232         }
233
234         err = w.sdl.Set(pairs)
235
236         if err != nil {
237                 return common.NewInternalError(err)
238         }
239
240         return nil
241 }
242
243 /*
244 SaveRanLoadInformation stores ran load information for the provided ran
245 */
246 func (w *rNibWriterInstance) SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error {
247
248         key, rnibErr := common.ValidateAndBuildRanLoadInformationKey(inventoryName)
249
250         if rnibErr != nil {
251                 return rnibErr
252         }
253
254         data, err := proto.Marshal(ranLoadInformation)
255
256         if err != nil {
257                 return common.NewInternalError(err)
258         }
259
260         var pairs []interface{}
261         pairs = append(pairs, key, data)
262
263         err = w.sdl.Set(pairs)
264
265         if err != nil {
266                 return common.NewInternalError(err)
267         }
268
269         return nil
270 }
271
272 func (w *rNibWriterInstance) SaveE2TInstance(e2tInstance *entities.E2TInstance) error {
273
274         key, rnibErr := common.ValidateAndBuildE2TInstanceKey(e2tInstance.Address)
275
276         if rnibErr != nil {
277                 return rnibErr
278         }
279
280         data, err := json.Marshal(e2tInstance)
281
282         if err != nil {
283                 return common.NewInternalError(err)
284         }
285
286         var pairs []interface{}
287         pairs = append(pairs, key, data)
288
289         err = w.sdl.Set(pairs)
290
291         if err != nil {
292                 return common.NewInternalError(err)
293         }
294
295         return nil
296 }
297
298 func (w *rNibWriterInstance) SaveE2TAddresses(addresses []string) error {
299
300         data, err := json.Marshal(addresses)
301
302         if err != nil {
303                 return common.NewInternalError(err)
304         }
305
306         var pairs []interface{}
307         pairs = append(pairs, E2TAddressesKey, data)
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 func (w *rNibWriterInstance) RemoveE2TInstance(address string) error {
319         key, rNibErr := common.ValidateAndBuildE2TInstanceKey(address)
320         if rNibErr != nil {
321                 return rNibErr
322         }
323         err := w.sdl.Remove([]string{key})
324
325         if err != nil {
326                 return common.NewInternalError(err)
327         }
328         return nil
329 }
330
331 func (w *rNibWriterInstance) SaveWithKeyAndMarshal(key string, entity interface{}) error {
332
333         data, err := json.Marshal(entity)
334
335         if err != nil {
336                 return common.NewInternalError(err)
337         }
338
339         var pairs []interface{}
340         pairs = append(pairs, key, data)
341
342         err = w.sdl.Set(pairs)
343
344         if err != nil {
345                 return common.NewInternalError(err)
346         }
347
348         return nil
349 }
350
351 /*
352 UpdateNodebInfoOnConnectionStatusInversion...
353 */
354 func (w *rNibWriterInstance) UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, stateChangeMessageChannel string, event string) error {
355
356         pairs, err := buildUpdateNodebInfoPairs(nodebInfo)
357
358         if err != nil {
359                 return err
360         }
361
362         err = w.sdl.SetAndPublish([]string{stateChangeMessageChannel, event}, pairs)
363
364         if err != nil {
365                 return common.NewInternalError(err)
366         }
367
368         return nil
369 }
370
371 /*
372 Close the writer
373 */
374 func Close() {
375         //Nothing to do
376 }
377
378 func appendEnbCells(inventoryName string, cells []*entities.ServedCellInfo, pairs []interface{}) ([]interface{}, error) {
379         for _, cell := range cells {
380                 cellEntity := entities.Cell{Type: entities.Cell_LTE_CELL, Cell: &entities.Cell_ServedCellInfo{ServedCellInfo: cell}}
381                 cellData, err := proto.Marshal(&cellEntity)
382                 if err != nil {
383                         return pairs, common.NewInternalError(err)
384                 }
385                 key, rNibErr := common.ValidateAndBuildCellIdKey(cell.GetCellId())
386                 if rNibErr != nil {
387                         return pairs, rNibErr
388                 }
389                 pairs = append(pairs, key, cellData)
390                 key, rNibErr = common.ValidateAndBuildCellNamePciKey(inventoryName, cell.GetPci())
391                 if rNibErr != nil {
392                         return pairs, rNibErr
393                 }
394                 pairs = append(pairs, key, cellData)
395         }
396         return pairs, nil
397 }
398
399 func appendGnbCells(inventoryName string, cells []*entities.ServedNRCell, pairs []interface{}) ([]interface{}, error) {
400         for _, cell := range cells {
401                 cellEntity := entities.Cell{Type: entities.Cell_NR_CELL, Cell: &entities.Cell_ServedNrCell{ServedNrCell: cell}}
402                 cellData, err := proto.Marshal(&cellEntity)
403                 if err != nil {
404                         return pairs, common.NewInternalError(err)
405                 }
406                 key, rNibErr := common.ValidateAndBuildNrCellIdKey(cell.GetServedNrCellInformation().GetCellId())
407                 if rNibErr != nil {
408                         return pairs, rNibErr
409                 }
410                 pairs = append(pairs, key, cellData)
411                 key, rNibErr = common.ValidateAndBuildCellNamePciKey(inventoryName, cell.GetServedNrCellInformation().GetNrPci())
412                 if rNibErr != nil {
413                         return pairs, rNibErr
414                 }
415                 pairs = append(pairs, key, cellData)
416         }
417         return pairs, nil
418 }
419
420 func isNotEmpty(nbIdentity *entities.NbIdentity) bool {
421         return nbIdentity.GlobalNbId != nil && nbIdentity.GlobalNbId.PlmnId != "" && nbIdentity.GlobalNbId.NbId != ""
422 }