Test and debug interface improvements
[ric-plt/submgr.git] / pkg / control / e2if_state.go
1 /*
2 ==================================================================================
3   Copyright (c) 2019 AT&T Intellectual Property.
4   Copyright (c) 2019 Nokia
5
6    Licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8    You may obtain a copy of the License at
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17 ==================================================================================
18 */
19
20 package control
21
22 import (
23         "encoding/json"
24         "fmt"
25         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
26         "strings"
27         "sync"
28 )
29
30 type XappRnibIf struct {
31         XappRnibInterface
32 }
33
34 func (x *XappRnibIf) XappRnibSubscribe(NotificationCb func(string, ...string), channel string) error {
35         return xapp.Rnib.Subscribe(NotificationCb, channel)
36 }
37
38 func (x *XappRnibIf) XappRnibGetListGnbIds() ([]*xapp.RNIBNbIdentity, xapp.RNIBIRNibError) {
39         return xapp.Rnib.GetListGnbIds()
40 }
41 func (x *XappRnibIf) XappRnibGetNodeb(inventoryName string) (*xapp.RNIBNodebInfo, xapp.RNIBIRNibError) {
42         nodeInfo, err := xapp.Rnib.GetNodeb(inventoryName)
43         return nodeInfo, err
44 }
45
46 func CreateXappRnibIfInstance() XappRnibInterface {
47         return new(XappRnibIf)
48 }
49
50 type E2IfState struct {
51         mutex   sync.Mutex
52         control *Control
53         NbIdMap map[string]string
54 }
55
56 func (e *E2IfState) Init(c *Control) {
57         e.control = c
58         e.NbIdMap = make(map[string]string, 0)
59         e.ReadE2ConfigurationFromRnib()
60         e.SubscribeChannels()
61 }
62
63 func (e *E2IfState) GetE2NodesJson() []byte {
64
65         e.mutex.Lock()
66         defer e.mutex.Unlock()
67
68         // Map contains something like this{"RAN_NAME_1":"RAN_NAME_1","RAN_NAME_11":"RAN_NAME_11","RAN_NAME_2":"RAN_NAME_2"}
69         var ranNameList []string
70         for _, ranName := range e.NbIdMap {
71                 ranNameList = append(ranNameList, ranName)
72         }
73
74         e2NodesJson, err := json.Marshal(ranNameList)
75         if err != nil {
76                 xapp.Logger.Error("GetE2Node() json.Marshal error: %v", err)
77         }
78         return e2NodesJson
79 }
80
81 func (e *E2IfState) GetAllE2Nodes() map[string]string {
82
83         e.mutex.Lock()
84         defer e.mutex.Unlock()
85         return e.NbIdMap
86 }
87
88 func (e *E2IfState) NotificationCb(ch string, events ...string) {
89
90         xapp.Logger.Debug("SDL notification received from channel=%s, event=%v", ch, events[0])
91         if len(events) == 0 {
92                 xapp.Logger.Error("Invalid SDL notification received: %d", len(events))
93                 return
94         }
95
96         if strings.Contains(events[0], "_CONNECTED") && !strings.Contains(events[0], "_CONNECTED_SETUP_FAILED") {
97                 e.control.UpdateCounter(cE2StateChangedToUp)
98                 nbId, err := ExtractNbiIdFromString(events[0])
99                 if err != nil {
100                         xapp.Logger.Error("NotificationCb CONNECTED len(nbId) == 0 ")
101                         return
102                 }
103                 xapp.Logger.Debug("E2 CONNECTED. NbId=%s", nbId)
104                 e.NbIdMap[nbId] = nbId
105         } else if strings.Contains(events[0], "_DISCONNECTED") {
106                 e.control.UpdateCounter(cE2StateChangedToDown)
107                 nbId, err := ExtractNbiIdFromString(events[0])
108                 if err != nil {
109                         xapp.Logger.Error("NotificationCb DISCONNECTED len(nbId) == 0 ")
110                         return
111                 }
112                 xapp.Logger.Debug("E2 DISCONNECTED. NbId=%s", nbId)
113                 if _, ok := e.NbIdMap[nbId]; ok {
114                         delete(e.NbIdMap, nbId)
115                         e.control.registry.DeleteAllE2Subscriptions(nbId, e.control)
116                 }
117         }
118 }
119
120 func (e *E2IfState) SubscribeChannels() error {
121
122         if err := e.control.e2IfStateDb.XappRnibSubscribe(e.NotificationCb, "RAN_CONNECTION_STATUS_CHANGE"); err != nil {
123                 xapp.Logger.Error("Sdl.SubscribeChannel failed: %v", err)
124                 return err
125         }
126         xapp.Logger.Debug("Subscription to RAN state changes done!")
127         return nil
128 }
129
130 func (e *E2IfState) ReadE2ConfigurationFromRnib() {
131
132         xapp.Logger.Debug("ReadE2ConfigurationFromRnib()")
133         nbIdentities, err := e.control.e2IfStateDb.XappRnibGetListGnbIds()
134         if err != nil || len(nbIdentities) == 0 {
135                 xapp.Logger.Debug("There are no active NodeBs available: %v", err)
136                 e.NbIdMap = make(map[string]string, 0)
137                 return
138         }
139
140         for _, nbIdentity := range nbIdentities {
141                 if e.isNodeBActive(nbIdentity.InventoryName) == false {
142                         if _, ok := e.NbIdMap[nbIdentity.InventoryName]; ok {
143                                 delete(e.NbIdMap, nbIdentity.InventoryName)
144                                 xapp.Logger.Debug("E2 connection DISCONNETED: %v", nbIdentity.InventoryName)
145
146                                 // Delete all subscriptions related to InventoryName/nbId
147                                 e.control.registry.DeleteAllE2Subscriptions(nbIdentity.InventoryName, e.control)
148                         }
149                         continue
150                 }
151
152                 if _, ok := e.NbIdMap[nbIdentity.InventoryName]; !ok {
153                         e.NbIdMap[nbIdentity.InventoryName] = nbIdentity.InventoryName
154                         xapp.Logger.Debug("E2 connection CONNECTED: %v", nbIdentity.InventoryName)
155                 }
156         }
157 }
158
159 func (e *E2IfState) isNodeBActive(inventoryName string) bool {
160         nodeInfo, err := e.control.e2IfStateDb.XappRnibGetNodeb(inventoryName)
161         if err != nil {
162                 xapp.Logger.Error("GetNodeb() failed for inventoryName=%s: %v", inventoryName, err)
163                 return false
164         }
165         xapp.Logger.Debug("NodeB['%s'] connection status = %d", inventoryName, nodeInfo.ConnectionStatus)
166         return nodeInfo.ConnectionStatus == 1
167 }
168
169 func (e *E2IfState) IsE2ConnectionUp(nbId *string) bool {
170
171         if checkE2State == "false" {
172                 return true
173         }
174
175         if _, ok := e.NbIdMap[*nbId]; ok {
176                 return true
177         } else {
178                 return false
179         }
180 }
181
182 func ExtractNbiIdFromString(s string) (string, error) {
183
184         // Expected string formats are below
185         // gnb_208_092_303030_CONNECTED
186         // gnb_208_092_303030_DISCONNECTED
187         // ...
188
189         var nbId string
190         var err error
191         if strings.Contains(s, "_CONNECTED") {
192                 splitStringTbl := strings.Split(s, "_CONNECTED")
193                 nbId = splitStringTbl[0]
194         } else if strings.Contains(s, "_DISCONNECTED") {
195                 splitStringTbl := strings.Split(s, "_DISCONNECTED")
196                 nbId = splitStringTbl[0]
197         }
198         if len(nbId) == 0 {
199                 return "", fmt.Errorf("ExtractNbiIdFromString(): len(nbId) == 0 ")
200         }
201         return nbId, err
202 }