Automation of nodeb health check
[ric-plt/e2mgr.git] / E2Manager / handlers / httpmsghandlers / health_check_handler.go
1 //
2 // Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
17 //  platform project (RICP).
18
19 package httpmsghandlers
20
21 import (
22         "e2mgr/e2managererrors"
23         "e2mgr/logger"
24         "e2mgr/managers"
25         "e2mgr/models"
26         "e2mgr/rmrCgo"
27         "e2mgr/services"
28         "e2mgr/services/rmrsender"
29         "encoding/xml"
30         "fmt"
31         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
32         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
33         "strings"
34         "unsafe"
35 )
36
37 var(
38         emptyTagsToReplaceToSelfClosingTags = []string{"reject", "ignore", "protocolIEs"}
39 )
40
41 type HealthCheckRequestHandler struct {
42         logger          *logger.Logger
43         rNibDataService services.RNibDataService
44         ranListManager  managers.RanListManager
45         rmrsender       *rmrsender.RmrSender
46 }
47
48 func NewHealthCheckRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService, ranListManager managers.RanListManager, rmrsender *rmrsender.RmrSender) *HealthCheckRequestHandler {
49         return &HealthCheckRequestHandler{
50                 logger:          logger,
51                 rNibDataService: rNibDataService,
52                 ranListManager:  ranListManager,
53                 rmrsender:       rmrsender,
54         }
55 }
56
57 func (h *HealthCheckRequestHandler) Handle(request models.Request) (models.IResponse, error) {
58         ranNameList := h.getRanNameList(request)
59         isAtleastOneRanConnected := false
60
61         nodetypeToNbIdentityMapOld := make(map[entities.Node_Type][]*entities.NbIdentity)
62         nodetypeToNbIdentityMapNew := make(map[entities.Node_Type][]*entities.NbIdentity)
63
64         for _, ranName := range ranNameList {
65                 nodebInfo, err := h.rNibDataService.GetNodeb(ranName)
66                 if err != nil {
67                         _, ok := err.(*common.ResourceNotFoundError)
68                         if !ok {
69                                 h.logger.Errorf("#HealthCheckRequest.Handle - failed to get nodeBInfo entity for ran name: %v from RNIB. Error: %s", ranName, err)
70                                 return nil, e2managererrors.NewRnibDbError()
71                         }
72                         continue
73                 }
74
75                 if nodebInfo.ConnectionStatus == entities.ConnectionStatus_CONNECTED {
76                         isAtleastOneRanConnected = true
77
78                         err := h.sendRICServiceQuery(nodebInfo)
79                         if err != nil {
80                                 return nil,err
81                         }
82
83                         oldnbIdentity, newnbIdentity := h.ranListManager.UpdateHealthcheckTimeStampSent(ranName)
84                         nodetypeToNbIdentityMapOld[nodebInfo.NodeType] = append(nodetypeToNbIdentityMapOld[nodebInfo.NodeType], oldnbIdentity)
85                         nodetypeToNbIdentityMapNew[nodebInfo.NodeType] = append(nodetypeToNbIdentityMapNew[nodebInfo.NodeType], newnbIdentity)
86                 }
87         }
88
89         for k, _ := range nodetypeToNbIdentityMapOld {
90                 err := h.ranListManager.UpdateNbIdentities(k, nodetypeToNbIdentityMapOld[k], nodetypeToNbIdentityMapNew[k])
91                 if err != nil {
92                         return nil,err
93                 }
94         }
95
96         if isAtleastOneRanConnected == false {
97                 return nil, e2managererrors.NewNoConnectedRanError()
98         }
99
100         h.logger.Infof("#HealthcheckRequest.Handle - HealthcheckTimeStampSent Update completed to RedisDB")
101
102         return nil, nil
103 }
104
105 func (h *HealthCheckRequestHandler) sendRICServiceQuery(nodebInfo *entities.NodebInfo) error {
106
107         serviceQuery := models.NewRicServiceQueryMessage(nodebInfo.GetGnb().RanFunctions)
108         payLoad, err := xml.Marshal(serviceQuery.E2APPDU)
109         if err != nil {
110                 h.logger.Errorf("#HealthCHeckRequest.Handle- RAN name: %s - Error marshalling RIC_SERVICE_QUERY. Payload: %s", nodebInfo.RanName, payLoad)
111                 //return nil, e2managererrors.NewInternalError()
112         }
113
114         payLoad = replaceEmptyTagsWithSelfClosing(payLoad)
115
116         var xAction []byte
117         var msgSrc unsafe.Pointer
118         msg := models.NewRmrMessage(rmrCgo.RIC_SERVICE_QUERY, nodebInfo.RanName, payLoad, xAction, msgSrc)
119
120         err = h.rmrsender.Send(msg)
121
122         if err != nil {
123                 h.logger.Errorf("#HealthCHeckRequest.Handle - failed to send RIC_SERVICE_QUERY message to RMR for %s. Error: %s", nodebInfo.RanName, err)
124                 //return nil, e2managererrors.NewRmrError()
125         } else {
126                 h.logger.Infof("#HealthCHeckRequest.Handle - RAN name : %s - Successfully built and sent RIC_SERVICE_QUERY. Message: %x", nodebInfo.RanName, msg)
127         }
128
129         return nil
130 }
131
132 func (h *HealthCheckRequestHandler) getRanNameList(request models.Request) []string {
133         healthCheckRequest := request.(models.HealthCheckRequest)
134         if request != nil && len(healthCheckRequest.RanList) != 0 {
135                 return healthCheckRequest.RanList
136         }
137
138         h.logger.Infof("#HealthcheckRequest.getRanNameList - Empty request sent, fetching all connected NbIdentitylist")
139
140         nodeIds := h.ranListManager.GetNbIdentityList()
141         var ranNameList []string
142
143         for _, nbIdentity := range nodeIds {
144                 if nbIdentity.ConnectionStatus == entities.ConnectionStatus_CONNECTED {
145                         ranNameList = append(ranNameList, nbIdentity.InventoryName)
146                 }
147         }
148
149         return ranNameList
150 }
151
152 func replaceEmptyTagsWithSelfClosing(responsePayload []byte) []byte {
153
154         emptyTagVsSelfClosingTagPairs := make([]string, len(emptyTagsToReplaceToSelfClosingTags)*2)
155
156         j := 0
157
158         for i := 0; i < len(emptyTagsToReplaceToSelfClosingTags); i++ {
159                 emptyTagVsSelfClosingTagPairs[j] = fmt.Sprintf("<%[1]s></%[1]s>", emptyTagsToReplaceToSelfClosingTags[i])
160                 emptyTagVsSelfClosingTagPairs[j+1] = fmt.Sprintf("<%s/>", emptyTagsToReplaceToSelfClosingTags[i])
161                 j += 2
162         }
163
164         responseString := strings.NewReplacer(emptyTagVsSelfClosingTagPairs...).Replace(string(responsePayload))
165         return []byte(responseString)
166 }