Delete all subscriptions when Ran is under reset.
[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         "strings"
26         "sync"
27
28         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
29 )
30
31 type XappRnibIf struct {
32         XappRnibInterface
33 }
34
35 func (x *XappRnibIf) XappRnibSubscribe(NotificationCb func(string, ...string), channel string) error {
36         return xapp.Rnib.Subscribe(NotificationCb, channel)
37 }
38
39 func (x *XappRnibIf) XappRnibGetListGnbIds() ([]*xapp.RNIBNbIdentity, xapp.RNIBIRNibError) {
40         return xapp.Rnib.GetListGnbIds()
41 }
42 func (x *XappRnibIf) XappRnibGetNodeb(inventoryName string) (*xapp.RNIBNodebInfo, xapp.RNIBIRNibError) {
43         nodeInfo, err := xapp.Rnib.GetNodeb(inventoryName)
44         return nodeInfo, err
45 }
46
47 func CreateXappRnibIfInstance() XappRnibInterface {
48         return new(XappRnibIf)
49 }
50
51 type E2IfState struct {
52         mutex   sync.Mutex
53         control *Control
54         NbIdMap map[string]string
55 }
56
57 func (e *E2IfState) Init(c *Control) {
58         e.control = c
59         e.NbIdMap = make(map[string]string, 0)
60         e.ReadE2ConfigurationFromRnib()
61         err := e.SubscribeChannels()
62         if err != nil {
63                 xapp.Logger.Error("Init(): SubscribeChannels() failed: %v", err)
64         }
65 }
66
67 func (e *E2IfState) GetE2NodesJson() []byte {
68
69         e.mutex.Lock()
70         defer e.mutex.Unlock()
71
72         // Map contains something like this{"RAN_NAME_1":"RAN_NAME_1","RAN_NAME_11":"RAN_NAME_11","RAN_NAME_2":"RAN_NAME_2"}
73         var ranNameList []string
74         for _, ranName := range e.NbIdMap {
75                 ranNameList = append(ranNameList, ranName)
76         }
77
78         e2NodesJson, err := json.Marshal(ranNameList)
79         if err != nil {
80                 xapp.Logger.Error("GetE2Node() json.Marshal error: %v", err)
81         }
82         return e2NodesJson
83 }
84
85 func (e *E2IfState) GetAllE2Nodes() map[string]string {
86
87         e.mutex.Lock()
88         defer e.mutex.Unlock()
89         return e.NbIdMap
90 }
91
92 func (e *E2IfState) NotificationCb(ch string, events ...string) {
93
94         xapp.Logger.Debug("SDL notification received from channel=%s, event=%v", ch, events[0])
95         if len(events) == 0 {
96                 xapp.Logger.Error("Invalid SDL notification received: %d", len(events))
97                 return
98         }
99
100         if strings.Contains(events[0], "_CONNECTED") && !strings.Contains(events[0], "_CONNECTED_SETUP_FAILED") {
101                 e.control.UpdateCounter(cE2StateChangedToUp)
102                 nbId, err := ExtractNbiIdFromString(events[0])
103                 if err != nil {
104                         xapp.Logger.Error("NotificationCb CONNECTED len(nbId) == 0 ")
105                         return
106                 }
107                 xapp.Logger.Debug("E2 CONNECTED. NbId=%s", nbId)
108                 e.NbIdMap[nbId] = nbId
109         } else if strings.Contains(events[0], "_DISCONNECTED") {
110                 e.control.UpdateCounter(cE2StateChangedToDown)
111                 nbId, err := ExtractNbiIdFromString(events[0])
112                 if err != nil {
113                         xapp.Logger.Error("NotificationCb DISCONNECTED len(nbId) == 0 ")
114                         return
115                 }
116                 xapp.Logger.Debug("E2 DISCONNECTED. NbId=%s", nbId)
117                 if _, ok := e.NbIdMap[nbId]; ok {
118                         delete(e.NbIdMap, nbId)
119                         e.control.registry.DeleteAllE2Subscriptions(nbId, e.control)
120                 }
121         } else if strings.Contains(events[0], "_UNDER_RESET") {
122                 xapp.Logger.Debug("NotificationCb UNDER_RESET len(nbId) == 0 ")
123                 e.control.UpdateCounter(cE2StateUnderReset)
124                 nbId, err := ExtractNbiIdFromString(events[0])
125                 if err != nil {
126                         xapp.Logger.Error("NotificationCb _UNDER_RESET %v ", err)
127                         return
128                 }
129                 xapp.Logger.Debug("E2 Under Reset. NbId=%s", nbId)
130                 if _, ok := e.NbIdMap[nbId]; ok {
131                         e.control.registry.DeleteAllE2Subscriptions(nbId, e.control)
132                 }
133         }
134 }
135
136 func (e *E2IfState) SubscribeChannels() error {
137
138         if err := e.control.e2IfStateDb.XappRnibSubscribe(e.NotificationCb, "RAN_CONNECTION_STATUS_CHANGE"); err != nil {
139                 xapp.Logger.Error("Sdl.SubscribeChannel failed: %v", err)
140                 return err
141         }
142         xapp.Logger.Debug("Subscription to RAN state changes done!")
143         return nil
144 }
145
146 func (e *E2IfState) ReadE2ConfigurationFromRnib() {
147
148         xapp.Logger.Debug("ReadE2ConfigurationFromRnib()")
149         nbIdentities, err := e.control.e2IfStateDb.XappRnibGetListGnbIds()
150         if err != nil || len(nbIdentities) == 0 {
151                 xapp.Logger.Debug("There are no active NodeBs available: %v", err)
152                 e.NbIdMap = make(map[string]string, 0)
153                 return
154         }
155
156         for _, nbIdentity := range nbIdentities {
157                 if e.isNodeBActive(nbIdentity.InventoryName) == false {
158                         if _, ok := e.NbIdMap[nbIdentity.InventoryName]; ok {
159                                 delete(e.NbIdMap, nbIdentity.InventoryName)
160                                 xapp.Logger.Debug("E2 connection DISCONNETED: %v", nbIdentity.InventoryName)
161
162                                 // Delete all subscriptions related to InventoryName/nbId
163                                 e.control.registry.DeleteAllE2Subscriptions(nbIdentity.InventoryName, e.control)
164                         }
165                         continue
166                 }
167
168                 if _, ok := e.NbIdMap[nbIdentity.InventoryName]; !ok {
169                         e.NbIdMap[nbIdentity.InventoryName] = nbIdentity.InventoryName
170                         xapp.Logger.Debug("E2 connection CONNECTED: %v", nbIdentity.InventoryName)
171                 }
172         }
173 }
174
175 func (e *E2IfState) isNodeBActive(inventoryName string) bool {
176         nodeInfo, err := e.control.e2IfStateDb.XappRnibGetNodeb(inventoryName)
177         if err != nil {
178                 xapp.Logger.Error("GetNodeb() failed for inventoryName=%s: %v", inventoryName, err)
179                 return false
180         }
181         xapp.Logger.Debug("NodeB['%s'] connection status = %d", inventoryName, nodeInfo.ConnectionStatus)
182         return nodeInfo.ConnectionStatus == 1
183 }
184
185 func (e *E2IfState) IsE2ConnectionUp(nbId *string) bool {
186
187         if checkE2State == "false" {
188                 return true
189         }
190
191         if _, ok := e.NbIdMap[*nbId]; ok {
192                 return true
193         } else {
194                 return false
195         }
196 }
197
198 func ExtractNbiIdFromString(s string) (string, error) {
199
200         // Expected string formats are below
201         // gnb_208_092_303030_CONNECTED
202         // gnb_208_092_303030_DISCONNECTED
203         // ...
204
205         var nbId string
206         var err error
207         if strings.Contains(s, "_CONNECTED") {
208                 splitStringTbl := strings.Split(s, "_CONNECTED")
209                 nbId = splitStringTbl[0]
210         } else if strings.Contains(s, "_DISCONNECTED") {
211                 splitStringTbl := strings.Split(s, "_DISCONNECTED")
212                 nbId = splitStringTbl[0]
213         } else if strings.Contains(s, "_UNDER_RESET") {
214                 splitStringTbl := strings.Split(s, "_UNDER_RESET")
215                 nbId = splitStringTbl[0]
216         }
217         if len(nbId) == 0 {
218                 return "", fmt.Errorf("ExtractNbiIdFromString(): len(nbId) == 0 ")
219         }
220         return nbId, err
221 }