[RIC-298] Added handling for orphan cells and updated Swagger
[ric-plt/e2mgr.git] / E2Manager / handlers / rmrmsghandlers / e2_setup_request_notification_handler.go
index f40636b..b71129f 100644 (file)
@@ -22,6 +22,7 @@ package rmrmsghandlers
 import (
        "bytes"
        "e2mgr/configuration"
+       "e2mgr/e2managererrors"
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/models"
@@ -34,6 +35,8 @@ import (
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "strconv"
+       "strings"
 )
 
 type E2SetupRequestNotificationHandler struct {
@@ -58,7 +61,7 @@ func NewE2SetupRequestNotificationHandler(logger *logger.Logger, config *configu
 
 func (h E2SetupRequestNotificationHandler) Handle(request *models.NotificationRequest){
        ranName := request.RanName
-       h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - received E2 Setup Request. Payload: %x", ranName, request.Payload)
+       h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - received E2_SETUP_REQUEST. Payload: %x", ranName, request.Payload)
 
        setupRequest, e2tIpAddress, err := h.parseSetupRequest(request.Payload)
        if err != nil {
@@ -67,6 +70,7 @@ func (h E2SetupRequestNotificationHandler) Handle(request *models.NotificationRe
        }
 
        h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - E2T Address: %s - handling E2_SETUP_REQUEST", e2tIpAddress)
+       h.logger.Debugf("#E2SetupRequestNotificationHandler.Handle - E2_SETUP_REQUEST has been parsed successfully %+v", setupRequest)
 
        _, err = h.e2tInstancesManager.GetE2TInstance(e2tIpAddress)
 
@@ -109,39 +113,88 @@ func (h E2SetupRequestNotificationHandler) Handle(request *models.NotificationRe
        err = h.e2tAssociationManager.AssociateRan(e2tIpAddress, nodebInfo)
        if err != nil{
                h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to associate E2T to nodeB entity. Error: %s", ranName, err)
+               if _, ok := err.(*e2managererrors.RoutingManagerError); ok{
+                       h.handleUnsuccessfulResponse(nodebInfo, request)
+               }
                return
        }
-       successResponse := models.NewE2SetupSuccessResponseMessage()
-       successResponse.SetPlmnId(h.config.GlobalRicId.PlmnId)
-       successResponse.SetRicId(h.config.GlobalRicId.RicNearRtId)
-       successResponse.SetExtractRanFunctionsIDList(setupRequest)
-       responsePayload, err := xml.Marshal(&successResponse.E2APPDU)
+       h.handleSuccessfulResponse(ranName, request, setupRequest)
+}
+
+func (h E2SetupRequestNotificationHandler) handleUnsuccessfulResponse(nodebInfo *entities.NodebInfo, req *models.NotificationRequest){
+       failureResponse := models.NewE2SetupFailureResponseMessage(models.TimeToWaitEnum.V60s)
+       h.logger.Debugf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", failureResponse)
 
+       responsePayload, err := xml.Marshal(&failureResponse.E2APPDU)
        if err != nil{
-               h.logger.Warnf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - Error marshalling E2 Setup Response. Response: %x", ranName, responsePayload)
+               h.logger.Warnf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", nodebInfo.RanName, responsePayload)
        }
-       msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_RESP, ranName, responsePayload, request.TransactionId)
-       h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - E2 Setup Request has been built. Message: %x", ranName, msg)
-       _ = h.rmrSender.Send(msg)
+
+       responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload)
+
+       msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_FAILURE, nodebInfo.RanName, responsePayload, req.TransactionId, req.GetMsgSrc())
+       h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", nodebInfo.RanName, msg)
+       _ = h.rmrSender.WhSend(msg)
+
 }
 
-func (h E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte)(*models.E2SetupRequestMessage, string, error){
+func (h E2SetupRequestNotificationHandler) handleSuccessfulResponse(ranName string, req *models.NotificationRequest, setupRequest *models.E2SetupRequestMessage){
 
-       colonInd := bytes.IndexByte(payload, ':')
-       if colonInd < 0 {
-               return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Error parsing E2 Setup Request, failed extract E2T IP Address: no ':' separator found")
+       ricNearRtId, err := convertTo20BitString(h.config.GlobalRicId.RicNearRtId)
+       if err != nil{
+               h.logger.Errorf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - failed to convert RicNearRtId value %s to 20 bit string . Error: %s", ranName, h.config.GlobalRicId.RicNearRtId, err)
+               return
        }
+       successResponse := models.NewE2SetupSuccessResponseMessage(h.config.GlobalRicId.PlmnId, ricNearRtId,setupRequest)
+       h.logger.Debugf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", successResponse)
 
-       e2tIpAddress := string(payload[:colonInd])
-       if len(e2tIpAddress) == 0 {
-               return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Empty E2T Address received")
+       responsePayload, err := xml.Marshal(&successResponse.E2APPDU)
+       if err != nil{
+               h.logger.Warnf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload)
+       }
+
+       responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload)
+
+       msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_RESP, ranName, responsePayload, req.TransactionId, req.GetMsgSrc())
+       h.logger.Infof("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", ranName, msg)
+       _ = h.rmrSender.Send(msg)
+}
+
+
+func replaceEmptyTagsWithSelfClosing(responsePayload []byte) []byte {
+       responseString := strings.NewReplacer(
+               "<reject></reject>", "<reject/>",
+               "<ignore></ignore>", "<ignore/>",
+               "<transport-resource-unavailable></transport-resource-unavailable>", "<transport-resource-unavailable/>",
+               "<v60s></v60s>", "<v60s/>",
+               "<v20s></v20s>", "<v20s/>",
+               "<v10s></v10s>", "<v10s/>",
+               "<v5s></v5s>", "<v5s/>",
+               "<v2s></v2s>", "<v2s/>",
+               "<v1s></v1s>", "<v1s/>",
+               ).Replace(string(responsePayload))
+       return []byte(responseString)
+}
+
+func convertTo20BitString(ricNearRtId string) (string, error){
+       r, err := strconv.ParseUint(ricNearRtId, 16, 32)
+       if err != nil{
+               return "", err
        }
+       return fmt.Sprintf("%020b", r)[:20], nil
+}
+
+func (h E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte)(*models.E2SetupRequestMessage, string, error){
 
        pipInd := bytes.IndexByte(payload, '|')
        if pipInd < 0 {
                return nil, "", errors.New( "#E2SetupRequestNotificationHandler.parseSetupRequest - Error parsing E2 Setup Request failed extract Payload: no | separator found")
        }
 
+       e2tIpAddress := string(payload[:pipInd])
+       if len(e2tIpAddress) == 0 {
+               return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Empty E2T Address received")
+       }
        setupRequest := &models.E2SetupRequestMessage{}
        err := xml.Unmarshal(payload[pipInd + 1:], &setupRequest.E2APPDU)
        if err != nil {
@@ -159,6 +212,10 @@ func (h E2SetupRequestNotificationHandler) buildNodebInfo(ranName string, e2tAdd
                RanName: ranName,
                NodeType: entities.Node_GNB,
                Configuration: &entities.NodebInfo_Gnb{Gnb: &entities.Gnb{}},
+               GlobalNbId:  &entities.GlobalNbId{
+                       PlmnId: request.GetPlmnId(),
+                       NbId:   request.GetNbId(),
+               },
        }
        nodebInfo.GetGnb().RanFunctions, err = request.GetExtractRanFunctionsList()
        return nodebInfo, err