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