[RIC-248] RAN Health Check Request API - Implementation 92/4692/4
authorRahul Banerji <r.banerji@samsung.com>
Fri, 11 Sep 2020 05:55:03 +0000 (11:25 +0530)
committerRahul Banerji <r.banerji@samsung.com>
Fri, 11 Sep 2020 07:24:27 +0000 (12:54 +0530)
Change-Id: I27e3eea34ada7dc001e3deca95079c491ab98c67
Signed-off-by: Rahul Banerji <r.banerji@samsung.com>
E2Manager/container-tag.yaml
E2Manager/handlers/httpmsghandlers/health_check_handler.go
E2Manager/handlers/httpmsghandlers/health_check_handler_test.go
E2Manager/managers/ran_list_manager.go
E2Manager/models/ric_service_query_message.go [new file with mode: 0644]
E2Manager/rmrCgo/rmrCgoTypes.go
tools/cm_e2mgr_ide/rtmgr_config.yaml
tools/cm_e2mgr_k8s/rtmgr_config.yaml

index d4430fd..cfda56b 100644 (file)
@@ -1,4 +1,4 @@
 # The Jenkins job requires a tag to build the Docker image.
 # Global-JJB script assumes this file is in the repo root.
 ---
 # The Jenkins job requires a tag to build the Docker image.
 # Global-JJB script assumes this file is in the repo root.
 ---
-tag: 5.4.9
+tag: 5.4.10
index 70203d8..718a49b 100644 (file)
@@ -23,11 +23,19 @@ import (
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/models"
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/models"
+       "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/services/rmrsender"
        "e2mgr/services"
        "e2mgr/services/rmrsender"
+       "encoding/xml"
+       "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"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       //        "github.com/pkg/errors"
+       "strings"
+       "unsafe"
+)
+
+var(
+       emptyTagsToReplaceToSelfClosingTags = []string{"reject", "ignore", "protocolIEs"}
 )
 
 type HealthCheckRequestHandler struct {
 )
 
 type HealthCheckRequestHandler struct {
@@ -50,8 +58,11 @@ func (h *HealthCheckRequestHandler) Handle(request models.Request) (models.IResp
        ranNameList := h.getRanNameList(request)
        isAtleastOneRanConnected := false
 
        ranNameList := h.getRanNameList(request)
        isAtleastOneRanConnected := false
 
+       nodetypeToNbIdentityMapOld := make(map[entities.Node_Type][]*entities.NbIdentity)
+       nodetypeToNbIdentityMapNew := make(map[entities.Node_Type][]*entities.NbIdentity)
+
        for _, ranName := range ranNameList {
        for _, ranName := range ranNameList {
-               nodebInfo, err := h.rNibDataService.GetNodeb(ranName) //This method is needed for getting RAN functions with later commits
+               nodebInfo, err := h.rNibDataService.GetNodeb(ranName)
                if err != nil {
                        _, ok := err.(*common.ResourceNotFoundError)
                        if !ok {
                if err != nil {
                        _, ok := err.(*common.ResourceNotFoundError)
                        if !ok {
@@ -60,30 +71,96 @@ func (h *HealthCheckRequestHandler) Handle(request models.Request) (models.IResp
                        }
                        continue
                }
                        }
                        continue
                }
+
                if nodebInfo.ConnectionStatus == entities.ConnectionStatus_CONNECTED {
                        isAtleastOneRanConnected = true
 
                if nodebInfo.ConnectionStatus == entities.ConnectionStatus_CONNECTED {
                        isAtleastOneRanConnected = true
 
+                       err := h.sendRICServiceQuery(nodebInfo)
+                       if err != nil {
+                               return nil,err
+                       }
+
+                       oldnbIdentity, newnbIdentity := h.ranListManager.UpdateHealthcheckTimeStampSent(ranName)
+                       nodetypeToNbIdentityMapOld[nodebInfo.NodeType] = append(nodetypeToNbIdentityMapOld[nodebInfo.NodeType], oldnbIdentity)
+                       nodetypeToNbIdentityMapNew[nodebInfo.NodeType] = append(nodetypeToNbIdentityMapNew[nodebInfo.NodeType], newnbIdentity)
                }
        }
                }
        }
+
+       for k, _ := range nodetypeToNbIdentityMapOld {
+               err := h.ranListManager.UpdateNbIdentities(k, nodetypeToNbIdentityMapOld[k], nodetypeToNbIdentityMapNew[k])
+               if err != nil {
+                       return nil,err
+               }
+       }
+
        if isAtleastOneRanConnected == false {
                return nil, e2managererrors.NewNoConnectedRanError()
        }
 
        if isAtleastOneRanConnected == false {
                return nil, e2managererrors.NewNoConnectedRanError()
        }
 
+       h.logger.Infof("#HealthcheckRequest.Handle - HealthcheckTimeStampSent Update completed to RedisDB")
+
        return nil, nil
 }
 
        return nil, nil
 }
 
+func (h *HealthCheckRequestHandler) sendRICServiceQuery(nodebInfo *entities.NodebInfo) error {
+
+       serviceQuery := models.NewRicServiceQueryMessage(nodebInfo.GetGnb().RanFunctions)
+       payLoad, err := xml.Marshal(serviceQuery.E2APPDU)
+       if err != nil {
+               h.logger.Errorf("#HealthCHeckRequest.Handle- RAN name: %s - Error marshalling RIC_SERVICE_QUERY. Payload: %s", nodebInfo.RanName, payLoad)
+               //return nil, e2managererrors.NewInternalError()
+       }
+
+       payLoad = replaceEmptyTagsWithSelfClosing(payLoad)
+
+       var xAction []byte
+       var msgSrc unsafe.Pointer
+       msg := models.NewRmrMessage(rmrCgo.RIC_SERVICE_QUERY, nodebInfo.RanName, payLoad, xAction, msgSrc)
+
+       err = h.rmrsender.Send(msg)
+
+       if err != nil {
+               h.logger.Errorf("#HealthCHeckRequest.Handle - failed to send RIC_SERVICE_QUERY message to RMR for %s. Error: %s", nodebInfo.RanName, err)
+               //return nil, e2managererrors.NewRmrError()
+       } else {
+               h.logger.Infof("#HealthCHeckRequest.Handle - RAN name : %s - Successfully built and sent RIC_SERVICE_QUERY. Message: %x", nodebInfo.RanName, msg)
+       }
+
+       return nil
+}
+
 func (h *HealthCheckRequestHandler) getRanNameList(request models.Request) []string {
        healthCheckRequest := request.(models.HealthCheckRequest)
        if request != nil && len(healthCheckRequest.RanList) != 0 {
                return healthCheckRequest.RanList
        }
 func (h *HealthCheckRequestHandler) getRanNameList(request models.Request) []string {
        healthCheckRequest := request.(models.HealthCheckRequest)
        if request != nil && len(healthCheckRequest.RanList) != 0 {
                return healthCheckRequest.RanList
        }
-       nodeIds := h.ranListManager.GetNbIdentityList()
 
 
+       h.logger.Infof("#HealthcheckRequest.getRanNameList - Empty request sent, fetching all connected NbIdentitylist")
+
+       nodeIds := h.ranListManager.GetNbIdentityList()
        var ranNameList []string
        var ranNameList []string
+
        for _, nbIdentity := range nodeIds {
                if nbIdentity.ConnectionStatus == entities.ConnectionStatus_CONNECTED {
                        ranNameList = append(ranNameList, nbIdentity.InventoryName)
                }
        }
        for _, nbIdentity := range nodeIds {
                if nbIdentity.ConnectionStatus == entities.ConnectionStatus_CONNECTED {
                        ranNameList = append(ranNameList, nbIdentity.InventoryName)
                }
        }
+
        return ranNameList
 }
        return ranNameList
 }
+
+func replaceEmptyTagsWithSelfClosing(responsePayload []byte) []byte {
+
+       emptyTagVsSelfClosingTagPairs := make([]string, len(emptyTagsToReplaceToSelfClosingTags)*2)
+
+       j := 0
+
+       for i := 0; i < len(emptyTagsToReplaceToSelfClosingTags); i++ {
+               emptyTagVsSelfClosingTagPairs[j] = fmt.Sprintf("<%[1]s></%[1]s>", emptyTagsToReplaceToSelfClosingTags[i])
+               emptyTagVsSelfClosingTagPairs[j+1] = fmt.Sprintf("<%s/>", emptyTagsToReplaceToSelfClosingTags[i])
+               j += 2
+       }
+
+       responseString := strings.NewReplacer(emptyTagVsSelfClosingTagPairs...).Replace(string(responsePayload))
+       return []byte(responseString)
+}
index 2c519df..af21f04 100644 (file)
 package httpmsghandlers
 
 import (
 package httpmsghandlers
 
 import (
+       "bytes"
        "e2mgr/configuration"
        "e2mgr/e2managererrors"
        "e2mgr/mocks"
        "e2mgr/models"
        "e2mgr/configuration"
        "e2mgr/e2managererrors"
        "e2mgr/mocks"
        "e2mgr/models"
+       "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/services"
+       "encoding/xml"
+       "errors"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "github.com/pkg/errors"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/mock"
+       "io/ioutil"
+       "path/filepath"
+       "strings"
        "testing"
        "testing"
+       "unsafe"
 )
 
 )
 
-func setupHealthCheckHandlerTest(t *testing.T) (*HealthCheckRequestHandler, services.RNibDataService, *mocks.RnibReaderMock, *mocks.RanListManagerMock) {
+const (
+       e2tInstanceFullAddress                   = "10.0.2.15:9999"
+       e2SetupMsgPrefix                         = e2tInstanceFullAddress + "|"
+       GnbSetupRequestXmlPath                   = "../../tests/resources/setupRequest_gnb.xml"
+)
+
+func setupHealthCheckHandlerTest(t *testing.T) (*HealthCheckRequestHandler, services.RNibDataService, *mocks.RnibReaderMock, *mocks.RanListManagerMock, *mocks.RmrMessengerMock) {
        logger := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
        logger := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
@@ -44,16 +58,23 @@ func setupHealthCheckHandlerTest(t *testing.T) (*HealthCheckRequestHandler, serv
        rmrSender := getRmrSender(rmrMessengerMock, logger)
        handler := NewHealthCheckRequestHandler(logger, rnibDataService, ranListManagerMock, rmrSender)
 
        rmrSender := getRmrSender(rmrMessengerMock, logger)
        handler := NewHealthCheckRequestHandler(logger, rnibDataService, ranListManagerMock, rmrSender)
 
-       return handler, rnibDataService, readerMock, ranListManagerMock
+       return handler, rnibDataService, readerMock, ranListManagerMock, rmrMessengerMock
 }
 
 func TestHealthCheckRequestHandlerArguementHasRanNameSuccess(t *testing.T) {
 }
 
 func TestHealthCheckRequestHandlerArguementHasRanNameSuccess(t *testing.T) {
-       handler, _, readerMock, _ := setupHealthCheckHandlerTest(t)
-
-       nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED}
+       handler, _, readerMock, ranListManagerMock, rmrMessengerMock := setupHealthCheckHandlerTest(t)
        ranNames := []string{"RanName_1"}
 
        ranNames := []string{"RanName_1"}
 
-       readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+       nb1:= createNbIdentity(t,"RanName_1", entities.ConnectionStatus_CONNECTED)
+       oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
+       newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
+
+       readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
+
+       mbuf:= createRMRMbuf(t, nb1)
+       rmrMessengerMock.On("SendMsg",mbuf,true).Return(mbuf,nil)
+       ranListManagerMock.On("UpdateHealthcheckTimeStampSent",nb1.RanName).Return(oldnbIdentity, newnbIdentity)
+       ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(nil)
 
        _, err := handler.Handle(models.HealthCheckRequest{ranNames})
 
 
        _, err := handler.Handle(models.HealthCheckRequest{ranNames})
 
@@ -62,15 +83,23 @@ func TestHealthCheckRequestHandlerArguementHasRanNameSuccess(t *testing.T) {
 }
 
 func TestHealthCheckRequestHandlerArguementHasNoRanNameSuccess(t *testing.T) {
 }
 
 func TestHealthCheckRequestHandlerArguementHasNoRanNameSuccess(t *testing.T) {
-       handler, _, readerMock, ranListManagerMock := setupHealthCheckHandlerTest(t)
+       handler, _, readerMock, ranListManagerMock, rmrMessengerMock := setupHealthCheckHandlerTest(t)
 
        nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED},
                {InventoryName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}}
 
        ranListManagerMock.On("GetNbIdentityList").Return(nbIdentityList)
 
 
        nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED},
                {InventoryName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}}
 
        ranListManagerMock.On("GetNbIdentityList").Return(nbIdentityList)
 
-       nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED}
-       readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+       nb1:= createNbIdentity(t,"RanName_1", entities.ConnectionStatus_CONNECTED)
+       oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
+       newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
+
+       readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
+
+       mbuf:= createRMRMbuf(t, nb1)
+       rmrMessengerMock.On("SendMsg",mbuf,true).Return(mbuf,nil)
+       ranListManagerMock.On("UpdateHealthcheckTimeStampSent",nb1.RanName).Return(oldnbIdentity, newnbIdentity)
+       ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(nil)
 
        nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
        readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
 
        nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
        readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
@@ -82,7 +111,7 @@ func TestHealthCheckRequestHandlerArguementHasNoRanNameSuccess(t *testing.T) {
 }
 
 func TestHealthCheckRequestHandlerArguementHasNoRanConnectedFailure(t *testing.T) {
 }
 
 func TestHealthCheckRequestHandlerArguementHasNoRanConnectedFailure(t *testing.T) {
-       handler, _, readerMock, ranListManagerMock := setupHealthCheckHandlerTest(t)
+       handler, _, readerMock, ranListManagerMock, rmrMessengerMock := setupHealthCheckHandlerTest(t)
 
        nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED},
                {InventoryName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}}
 
        nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED},
                {InventoryName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}}
@@ -91,23 +120,96 @@ func TestHealthCheckRequestHandlerArguementHasNoRanConnectedFailure(t *testing.T
        nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
        readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
 
        nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
        readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
 
-       nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
+       nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN}
        readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
 
        _, err := handler.Handle(models.HealthCheckRequest{[]string{}})
 
        readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
 
        _, err := handler.Handle(models.HealthCheckRequest{[]string{}})
 
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
+       ranListManagerMock.AssertNotCalled(t,"UpdateHealthcheckTimeStampSent",mock.Anything)
+       ranListManagerMock.AssertNotCalled(t,"UpdateNbIdentities",mock.Anything, mock.Anything, mock.Anything)
        assert.IsType(t, &e2managererrors.NoConnectedRanError{}, err)
 
 }
 
 func TestHealthCheckRequestHandlerArguementHasRanNameDBErrorFailure(t *testing.T) {
        assert.IsType(t, &e2managererrors.NoConnectedRanError{}, err)
 
 }
 
 func TestHealthCheckRequestHandlerArguementHasRanNameDBErrorFailure(t *testing.T) {
-       handler, _, readerMock, _ := setupHealthCheckHandlerTest(t)
+       handler, _, readerMock, ranListManagerMock, rmrMessengerMock := setupHealthCheckHandlerTest(t)
 
        ranNames := []string{"RanName_1"}
        readerMock.On("GetNodeb", "RanName_1").Return(&entities.NodebInfo{}, errors.New("error"))
 
        _, err := handler.Handle(models.HealthCheckRequest{ranNames})
 
 
        ranNames := []string{"RanName_1"}
        readerMock.On("GetNodeb", "RanName_1").Return(&entities.NodebInfo{}, errors.New("error"))
 
        _, err := handler.Handle(models.HealthCheckRequest{ranNames})
 
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
+       ranListManagerMock.AssertNotCalled(t,"UpdateHealthcheckTimeStampSent",mock.Anything)
+       ranListManagerMock.AssertNotCalled(t,"UpdateNbIdentities",mock.Anything, mock.Anything, mock.Anything)
        assert.IsType(t, &e2managererrors.RnibDbError{}, err)
        readerMock.AssertExpectations(t)
 }
        assert.IsType(t, &e2managererrors.RnibDbError{}, err)
        readerMock.AssertExpectations(t)
 }
+
+func createRMRMbuf(t *testing.T, nodebInfo *entities.NodebInfo) *rmrCgo.MBuf{
+       serviceQuery := models.NewRicServiceQueryMessage(nodebInfo.GetGnb().RanFunctions)
+       payLoad, err := xml.Marshal(&serviceQuery.E2APPDU)
+       payLoad = normalizeXml(payLoad)
+
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       var xAction []byte
+       var msgSrc unsafe.Pointer
+
+       rmrMessage := models.NewRmrMessage(rmrCgo.RIC_SERVICE_QUERY, nodebInfo.RanName, payLoad, xAction, msgSrc)
+       return rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
+}
+
+func createNbIdentity(t *testing.T, RanName string,  connectionStatus entities.ConnectionStatus) *entities.NodebInfo {
+       xmlgnb := readXmlFile(t, GnbSetupRequestXmlPath)
+       payload := append([]byte(e2SetupMsgPrefix), xmlgnb...)
+       pipInd := bytes.IndexByte(payload, '|')
+       setupRequest := &models.E2SetupRequestMessage{}
+       err := xml.Unmarshal(normalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       nodeb := &entities.NodebInfo{
+               AssociatedE2TInstanceAddress: e2tInstanceFullAddress,
+               RanName:                      RanName,
+               SetupFromNetwork:             true,
+               NodeType:                     entities.Node_GNB,
+               ConnectionStatus:                         connectionStatus,
+               Configuration: &entities.NodebInfo_Gnb{
+                       Gnb: &entities.Gnb{
+                               GnbType:      entities.GnbType_GNB,
+                               RanFunctions: setupRequest.ExtractRanFunctionsList(),
+                       },
+               },
+               GlobalNbId: &entities.GlobalNbId{
+                       PlmnId: setupRequest.GetPlmnId(),
+                       NbId:   setupRequest.GetNbId(),
+               },
+       }
+       return nodeb
+}
+
+func normalizeXml(payload []byte) []byte {
+       xmlStr := string(payload)
+       normalized := strings.NewReplacer("&lt;", "<", "&gt;", ">",
+               "<reject></reject>","<reject/>","<ignore></ignore>","<ignore/>",
+               "<protocolIEs></protocolIEs>","<protocolIEs/>").Replace(xmlStr)
+       return []byte(normalized)
+}
+
+func readXmlFile(t *testing.T, xmlPath string) []byte {
+       path, err := filepath.Abs(xmlPath)
+       if err != nil {
+               t.Fatal(err)
+       }
+       xmlAsBytes, err := ioutil.ReadFile(path)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       return xmlAsBytes
+}
index 8ffa411..060d3ea 100755 (executable)
@@ -190,7 +190,13 @@ func (m *ranListManagerInstance) UpdateNbIdentities(nodeType entities.Node_Type,
        m.mux.Lock()
        defer m.mux.Unlock()
 
        m.mux.Lock()
        defer m.mux.Unlock()
 
-       err:= m.rnibDataService.UpdateNbIdentities(nodeType, oldNbIdentities, newNbIdentities)
+       err := m.rnibDataService.UpdateNbIdentities(nodeType, oldNbIdentities, newNbIdentities)
+
+       if err != nil {
+               m.logger.Errorf("#ranListManagerInstance.UpdateNbIdentities not completed for %d nbIdentities of nodetype - %s", len(newNbIdentities), nodeType.String())
+       } else{
+               m.logger.Infof("#ranListManagerInstance.UpdateNbIdentities completed successfully for %d nbIdentities of nodetype - %s", len(newNbIdentities), nodeType.String())
+       }
 
        return err
 }
 
        return err
 }
diff --git a/E2Manager/models/ric_service_query_message.go b/E2Manager/models/ric_service_query_message.go
new file mode 100644 (file)
index 0000000..dc6d315
--- /dev/null
@@ -0,0 +1,111 @@
+//
+// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package models
+
+import (
+       "encoding/xml"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+)
+
+type RanFunctionIdItem struct {
+       Text                  string `xml:",chardata"`
+       RanFunctionId         uint32 `xml:"ranFunctionID"`
+       RanFunctionRevision   uint32 `xml:"ranFunctionRevision"`
+}
+
+type RicServiceQueryProtocolIESingleContainer struct {
+       Text        string `xml:",chardata"`
+       Id          string `xml:"id"`
+       Criticality struct {
+               Text   string `xml:",chardata"`
+               Reject string `xml:"reject"`
+       } `xml:"criticality"`
+       Value struct {
+               Text               string          `xml:",chardata"`
+               RanFunctionIdItem  RanFunctionIdItem `xml:"RANfunctionID-Item"`
+       } `xml:"value"`
+}
+
+type RICServiceQueryIEs struct {
+       Text        string `xml:",chardata"`
+       Id          string `xml:"id"`
+       Criticality struct {
+               Text   string `xml:",chardata"`
+               Reject string `xml:"reject"`
+       } `xml:"criticality"`
+       Value struct {
+               Text   string `xml:",chardata"`
+               RANFunctionIdList struct {
+                       Text string `xml:",chardata"`
+                       ProtocolIESingleContainer []RicServiceQueryProtocolIESingleContainer `xml:"ProtocolIE-SingleContainer"`
+               } `xml:"RANfunctionsID-List"`
+       } `xml:"value"`
+}
+
+type RICServiceQuery struct {
+       Text    string   `xml:",chardata"`
+       ProtocolIEs struct {
+               Text              string `xml:",chardata"`
+               RICServiceQueryIEs []RICServiceQueryIEs `xml:"RICserviceQuery-IEs"`
+       } `xml:"protocolIEs"`
+}
+
+type InitiatingMessage struct {
+       Text          string `xml:",chardata"`
+       ProcedureCode string `xml:"procedureCode"`
+       Criticality   struct {
+               Text   string `xml:",chardata"`
+               Ignore string `xml:"ignore"`
+       } `xml:"criticality"`
+       Value struct {
+               Text           string         `xml:",chardata"`
+               RICServiceQuery RICServiceQuery `xml:"RICserviceQuery"`
+       } `xml:"value"`
+}
+
+type RicServiceQueryE2APPDU struct {
+       XMLName xml.Name `xml:"E2AP-PDU"`
+       Text              string `xml:",chardata"`
+       InitiatingMessage InitiatingMessage `xml:"initiatingMessage"`
+}
+
+
+type RICServiceQueryMessage struct{
+       XMLName xml.Name `xml:"RICserviceQueryMessage"`
+       Text    string   `xml:",chardata"`
+       E2APPDU RicServiceQueryE2APPDU  `xml:"E2AP-PDU"`
+}
+
+func NewRicServiceQueryMessage(ranFunctions []*entities.RanFunction) RICServiceQueryMessage {
+       initiatingMessage := InitiatingMessage{}
+       initiatingMessage.ProcedureCode = "6"
+       initiatingMessage.Value.RICServiceQuery.ProtocolIEs.RICServiceQueryIEs = make([]RICServiceQueryIEs,1)
+       initiatingMessage.Value.RICServiceQuery.ProtocolIEs.RICServiceQueryIEs[0].Id = "9"
+       protocolIESingleContainer := make([]RicServiceQueryProtocolIESingleContainer,len(ranFunctions))
+       for i := 0; i < len(ranFunctions); i++ {
+               protocolIESingleContainer[i].Id = "6"
+               protocolIESingleContainer[i].Value.RanFunctionIdItem.RanFunctionId = ranFunctions[i].RanFunctionId
+               protocolIESingleContainer[i].Value.RanFunctionIdItem.RanFunctionRevision = ranFunctions[i].RanFunctionRevision
+       }
+       initiatingMessage.Value.RICServiceQuery.ProtocolIEs.RICServiceQueryIEs[0].Value.RANFunctionIdList.ProtocolIESingleContainer = protocolIESingleContainer
+
+       return RICServiceQueryMessage{E2APPDU:RicServiceQueryE2APPDU{InitiatingMessage:initiatingMessage}}
+}
+
+
index 13bfa16..941af4d 100644 (file)
@@ -80,6 +80,7 @@ const (
        RIC_E2_SETUP_REQ                                         = C.RIC_E2_SETUP_REQ
        RIC_E2_SETUP_RESP                    = C.RIC_E2_SETUP_RESP
        RIC_E2_SETUP_FAILURE                 = C.RIC_E2_SETUP_FAILURE
        RIC_E2_SETUP_REQ                                         = C.RIC_E2_SETUP_REQ
        RIC_E2_SETUP_RESP                    = C.RIC_E2_SETUP_RESP
        RIC_E2_SETUP_FAILURE                 = C.RIC_E2_SETUP_FAILURE
+       RIC_SERVICE_QUERY                    = C.RIC_SERVICE_QUERY
 )
 
 const (
 )
 
 const (
index eae55cf..c99f18f 100644 (file)
@@ -124,6 +124,7 @@ data:
           "MC_REPORT=30010",
           "DCAPTERM_RTPM_RMR_MSGTYPE=33001",
           "DCAPTERM_GEO_RMR_MSGTYPE=33002",
           "MC_REPORT=30010",
           "DCAPTERM_RTPM_RMR_MSGTYPE=33001",
           "DCAPTERM_GEO_RMR_MSGTYPE=33002",
+          "RIC_SERVICE_QUERY=12060",
           ]
        "PlatformRoutes": [
          { 'messagetype': 'RIC_SUB_REQ', 'senderendpoint': 'SUBMAN', 'subscriptionid': -1, 'endpoint': '', 'meid': '%meid'},
           ]
        "PlatformRoutes": [
          { 'messagetype': 'RIC_SUB_REQ', 'senderendpoint': 'SUBMAN', 'subscriptionid': -1, 'endpoint': '', 'meid': '%meid'},
index 6fb0449..25fa801 100644 (file)
@@ -124,6 +124,7 @@ data:
           "MC_REPORT=30010",
           "DCAPTERM_RTPM_RMR_MSGTYPE=33001",
           "DCAPTERM_GEO_RMR_MSGTYPE=33002",
           "MC_REPORT=30010",
           "DCAPTERM_RTPM_RMR_MSGTYPE=33001",
           "DCAPTERM_GEO_RMR_MSGTYPE=33002",
+          "RIC_SERVICE_QUERY=12060",
           ]
        "PlatformRoutes": [
          { 'messagetype': 'RIC_SUB_REQ', 'senderendpoint': 'SUBMAN', 'subscriptionid': -1, 'endpoint': '', 'meid': '%meid'},
           ]
        "PlatformRoutes": [
          { 'messagetype': 'RIC_SUB_REQ', 'senderendpoint': 'SUBMAN', 'subscriptionid': -1, 'endpoint': '', 'meid': '%meid'},