b86ef81fc90594c9d41f7e7ce7808ef0326048b8
[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         err := e.SubscribeChannels()
61         if err != nil {
62                 xapp.Logger.Error("Init(): SubscribeChannels() failed: %v", err)
63         }
64 }
65
66 func (e *E2IfState) GetE2NodesJson() []byte {
67
68         e.mutex.Lock()
69         defer e.mutex.Unlock()
70
71         // Map contains something like this{"RAN_NAME_1":"RAN_NAME_1","RAN_NAME_11":"RAN_NAME_11","RAN_NAME_2":"RAN_NAME_2"}
72         var ranNameList []string
73         for _, ranName := range e.NbIdMap {
74                 ranNameList = append(ranNameList, ranName)
75         }
76
77         e2NodesJson, err := json.Marshal(ranNameList)
78         if err != nil {
79                 xapp.Logger.Error("GetE2Node() json.Marshal error: %v", err)
80         }
81         return e2NodesJson
82 }
83
84 func (e *E2IfState) GetAllE2Nodes() map[string]string {
85
86         e.mutex.Lock()
87         defer e.mutex.Unlock()
88         return e.NbIdMap
89 }
90
91 func (e *E2IfState) NotificationCb(ch string, events ...string) {
92
93         xapp.Logger.Debug("SDL notification received from channel=%s, event=%v", ch, events[0])
94         if len(events) == 0 {
95                 xapp.Logger.Error("Invalid SDL notification received: %d", len(events))
96                 return
97         }
98
99         if strings.Contains(events[0], "_CONNECTED") && !strings.Contains(events[0], "_CONNECTED_SETUP_FAILED") {
100                 e.control.UpdateCounter(cE2StateChangedToUp)
101                 nbId, err := ExtractNbiIdFromString(events[0])
102                 if err != nil {
103                         xapp.Logger.Error("NotificationCb CONNECTED len(nbId) == 0 ")
104                         return
105                 }
106                 xapp.Logger.Debug("E2 CONNECTED. NbId=%s", nbId)
107                 e.NbIdMap[nbId] = nbId
108         } else if strings.Contains(events[0], "_DISCONNECTED") {
109                 e.control.UpdateCounter(cE2StateChangedToDown)
110                 nbId, err := ExtractNbiIdFromString(events[0])
111                 if err != nil {
112                         xapp.Logger.Error("NotificationCb DISCONNECTED len(nbId) == 0 ")
113                         return
114                 }
115                 xapp.Logger.Debug("E2 DISCONNECTED. NbId=%s", nbId)
116                 if _, ok := e.NbIdMap[nbId]; ok {
117                         delete(e.NbIdMap, nbId)
118                         e.control.registry.DeleteAllE2Subscriptions(nbId, e.control)
119                 }
120         }
121 }
122
123 func (e *E2IfState) SubscribeChannels() error {
124
125         if err := e.control.e2IfStateDb.XappRnibSubscribe(e.NotificationCb, "RAN_CONNECTION_STATUS_CHANGE"); err != nil {
126                 xapp.Logger.Error("Sdl.SubscribeChannel failed: %v", err)
127                 return err
128         }
129         xapp.Logger.Debug("Subscription to RAN state changes done!")
130         return nil
131 }
132
133 func (e *E2IfState) ReadE2ConfigurationFromRnib() {
134
135         xapp.Logger.Debug("ReadE2ConfigurationFromRnib()")
136         nbIdentities, err := e.control.e2IfStateDb.XappRnibGetListGnbIds()
137         if err != nil || len(nbIdentities) == 0 {
138                 xapp.Logger.Debug("There are no active NodeBs available: %v", err)
139                 e.NbIdMap = make(map[string]string, 0)
140                 return
141         }
142
143         for _, nbIdentity := range nbIdentities {
144                 if e.isNodeBActive(nbIdentity.InventoryName) == false {
145                         if _, ok := e.NbIdMap[nbIdentity.InventoryName]; ok {
146                                 delete(e.NbIdMap, nbIdentity.InventoryName)
147                                 xapp.Logger.Debug("E2 connection DISCONNETED: %v", nbIdentity.InventoryName)
148
149                                 // Delete all subscriptions related to InventoryName/nbId
150                                 e.control.registry.DeleteAllE2Subscriptions(nbIdentity.InventoryName, e.control)
151                         }
152                         continue
153                 }
154
155                 if _, ok := e.NbIdMap[nbIdentity.InventoryName]; !ok {
156                         e.NbIdMap[nbIdentity.InventoryName] = nbIdentity.InventoryName
157                         xapp.Logger.Debug("E2 connection CONNECTED: %v", nbIdentity.InventoryName)
158                 }
159         }
160 }
161
162 func (e *E2IfState) isNodeBActive(inventoryName string) bool {
163         nodeInfo, err := e.control.e2IfStateDb.XappRnibGetNodeb(inventoryName)
164         if err != nil {
165                 xapp.Logger.Error("GetNodeb() failed for inventoryName=%s: %v", inventoryName, err)
166                 return false
167         }
168         xapp.Logger.Debug("NodeB['%s'] connection status = %d", inventoryName, nodeInfo.ConnectionStatus)
169         return nodeInfo.ConnectionStatus == 1
170 }
171
172 func (e *E2IfState) IsE2ConnectionUp(nbId *string) bool {
173
174         if checkE2State == "false" {
175                 return true
176         }
177
178         if _, ok := e.NbIdMap[*nbId]; ok {
179                 return true
180         } else {
181                 return false
182         }
183 }
184
185 func ExtractNbiIdFromString(s string) (string, error) {
186
187         // Expected string formats are below
188         // gnb_208_092_303030_CONNECTED
189         // gnb_208_092_303030_DISCONNECTED
190         // ...
191
192         var nbId string
193         var err error
194         if strings.Contains(s, "_CONNECTED") {
195                 splitStringTbl := strings.Split(s, "_CONNECTED")
196                 nbId = splitStringTbl[0]
197         } else if strings.Contains(s, "_DISCONNECTED") {
198                 splitStringTbl := strings.Split(s, "_DISCONNECTED")
199                 nbId = splitStringTbl[0]
200         }
201         if len(nbId) == 0 {
202                 return "", fmt.Errorf("ExtractNbiIdFromString(): len(nbId) == 0 ")
203         }
204         return nbId, err
205 }