From: ss412g Date: Tue, 17 Mar 2020 16:34:42 +0000 (+0200) Subject: Merge R4 branch to master X-Git-Tag: R5_RC~123 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=011bb9161ca8e7ad0d0cf282b818672a88a5dfbf;p=ric-plt%2Fe2mgr.git Merge R4 branch to master Change-Id: I831804666f6391ef72aff6ac1a84fe632a661364 Signed-off-by: ss412g --- diff --git a/.gitreview b/.gitreview index e1956af..5de862e 100644 --- a/.gitreview +++ b/.gitreview @@ -2,4 +2,5 @@ host=gerrit.o-ran-sc.org port=29418 project=ric-plt/e2mgr -defaultbranch=master \ No newline at end of file +defaultbranch=master + diff --git a/Automation/Tests/KeepAlive/keep_alive_test.robot b/Automation/Tests/KeepAlive/keep_alive_test.robot index 07faee2..f83aa36 100644 --- a/Automation/Tests/KeepAlive/keep_alive_test.robot +++ b/Automation/Tests/KeepAlive/keep_alive_test.robot @@ -54,9 +54,9 @@ X2 - Get Nodeb String response body enb servedCells 0 choiceEutraMode fdd ulTransmissionBandwidth BW50 String response body enb servedCells 0 choiceEutraMode fdd dlTransmissionBandwidth BW50 -#prepare logs for tests -# Remove log files -# Save logs +prepare logs for tests + Remove log files + Save logs X2 - RAN Connected message going to be sent ${result} find_rmr_message.verify_logs ${EXECDIR} ${e2mgr_log_filename} ${RAN_CONNECTED_message_type} ${Meid_test1} diff --git a/Automation/Tests/Lost_Connection/Lost_Connetion_CONNECTING_TO_DISCONNECTED.robot b/Automation/Tests/Lost_Connection/LostConnectionTestConnectedRan.robot similarity index 65% rename from Automation/Tests/Lost_Connection/Lost_Connetion_CONNECTING_TO_DISCONNECTED.robot rename to Automation/Tests/Lost_Connection/LostConnectionTestConnectedRan.robot index 90002eb..43c1166 100644 --- a/Automation/Tests/Lost_Connection/Lost_Connetion_CONNECTING_TO_DISCONNECTED.robot +++ b/Automation/Tests/Lost_Connection/LostConnectionTestConnectedRan.robot @@ -23,39 +23,39 @@ Suite Setup Prepare Enviorment Resource ../Resource/resource.robot Resource ../Resource/Keywords.robot +Library ../Scripts/e2mdbscripts.py Library OperatingSystem Library Collections Library REST ${url} - - - *** Test Cases *** -Pre Condition for Connecting - no simu - Run And Return Rc And Output ${stop_simu} - ${result}= Run And Return Rc And Output ${docker_command} - Should Be Equal As Integers ${result[1]} ${docker_number-1} +prepare logs for tests + Remove log files + Save logs -Prepare Ran in Connecting connectionStatus - Sleep 1s +Setup Ran and verify it's CONNECTED and associated Post Request setup node b x-2 - Integer response status 204 - Sleep 1s - GET /v1/nodeb/test1 + Integer response status 204 + Get Request node b enb test1 Integer response status 200 String response body ranName test1 - #String response body connectionStatus CONNECTING - + String response body connectionStatus CONNECTED + String response body associatedE2tInstanceAddress e2t.att.com:38000 +Restart simulator + Restart simulator -Verfiy Disconnected ConnectionStatus - Sleep 10s +Verify connection status is DISCONNECTED and RAN is not associated with E2T instance + Sleep 5s GET /v1/nodeb/test1 Integer response status 200 String response body ranName test1 + Missing response body associatedE2tInstanceAddress String response body connectionStatus DISCONNECTED - Integer response body connectionAttempts 3 +Verify E2T instance is NOT associated with RAN + ${result} e2mdbscripts.verify_ran_is_associated_with_e2t_instance test1 e2t.att.com:38000 + Should Be True ${result} == False diff --git a/E2Manager/Dockerfile b/E2Manager/Dockerfile index 99dfc35..6a95812 100755 --- a/E2Manager/Dockerfile +++ b/E2Manager/Dockerfile @@ -41,8 +41,8 @@ COPY --from=ubuntu /opt/E2Manager/router.txt /opt/E2Manager/router.txt COPY --from=ubuntu /opt/E2Manager/main /opt/E2Manager/main COPY --from=ubuntu /opt/E2Manager/resources/configuration.yaml /opt/E2Manager/resources/configuration.yaml COPY --from=ubuntu /opt/E2Manager/resources/rmr.verbose /tmp/rmr.verbose -COPY --from=ubuntu /usr/local/lib/librmr_nng.so.1 /usr/local/lib/librmr_nng.so.1 -COPY --from=ubuntu /usr/local/lib/libnng.so.1 /usr/local/lib/libnng.so.1 +COPY --from=ubuntu /usr/local/lib/librmr_si.so.3 /usr/local/lib/librmr_si.so.3 + WORKDIR /opt/E2Manager ENV LD_LIBRARY_PATH=/usr/local/lib \ port=3800 diff --git a/E2Manager/app/main.go b/E2Manager/app/main.go index 6f180e3..719e8d7 100644 --- a/E2Manager/app/main.go +++ b/E2Manager/app/main.go @@ -60,7 +60,7 @@ func main() { e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger) routingManagerClient := clients.NewRoutingManagerClient(logger, config, clients.NewHttpClient()) e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient) - e2tShutdownManager := managers.NewE2TShutdownManager(logger, config, rnibDataService, e2tInstancesManager, e2tAssociationManager, ranSetupManager) + e2tShutdownManager := managers.NewE2TShutdownManager(logger, config, rnibDataService, e2tInstancesManager, e2tAssociationManager) e2tKeepAliveWorker := managers.NewE2TKeepAliveWorker(logger, rmrSender, e2tInstancesManager, e2tShutdownManager, config) rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider() rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient, e2tAssociationManager) diff --git a/E2Manager/build-e2mgr-ubuntu.sh b/E2Manager/build-e2mgr-ubuntu.sh index 693ca84..ae1794d 100755 --- a/E2Manager/build-e2mgr-ubuntu.sh +++ b/E2Manager/build-e2mgr-ubuntu.sh @@ -49,11 +49,11 @@ git clone https://github.com/nanomsg/nng.git \ && rm -r nng # Install RMR from deb packages at packagecloud.io -rmr=rmr_1.13.0_amd64.deb +rmr=rmr_3.5.1_amd64.deb wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/$rmr/download.deb dpkg -i $rmr rm $rmr -rmrdev=rmr-dev_1.13.0_amd64.deb +rmrdev=rmr-dev_3.5.1_amd64.deb wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/$rmrdev/download.deb dpkg -i $rmrdev rm $rmrdev diff --git a/E2Manager/clients/routing_manager_client.go b/E2Manager/clients/routing_manager_client.go index 318b7cf..2625612 100644 --- a/E2Manager/clients/routing_manager_client.go +++ b/E2Manager/clients/routing_manager_client.go @@ -47,7 +47,7 @@ type IRoutingManagerClient interface { AssociateRanToE2TInstance(e2tAddress string, ranName string) error DissociateRanE2TInstance(e2tAddress string, ranName string) error DissociateAllRans(e2tAddresses []string) error - DeleteE2TInstance(e2tAddress string, ransToBeDissociated []string, e2tToRansAssociations map[string][]string) error + DeleteE2TInstance(e2tAddress string, ransToBeDissociated []string) error } func NewRoutingManagerClient(logger *logger.Logger, config *configuration.Configuration, httpClient IHttpClient) *RoutingManagerClient { @@ -90,9 +90,8 @@ func (c *RoutingManagerClient) DissociateAllRans(e2tAddresses []string) error { return c.PostMessage(url, data) } -func (c *RoutingManagerClient) DeleteE2TInstance(e2tAddress string, ransTobeDissociated []string, e2tToRansAssociations map[string][]string) error { - e2tDataList := convertE2TToRansAssociationsMapToE2TDataList(e2tToRansAssociations) - data := models.NewRoutingManagerDeleteRequestModel(e2tAddress, ransTobeDissociated, e2tDataList) +func (c *RoutingManagerClient) DeleteE2TInstance(e2tAddress string, ransTobeDissociated []string) error { + data := models.NewRoutingManagerDeleteRequestModel(e2tAddress, ransTobeDissociated, nil) url := c.config.RoutingManager.BaseUrl + DeleteE2TInstanceApiSuffix return c.DeleteMessage(url, data) } diff --git a/E2Manager/clients/routing_manager_client_test.go b/E2Manager/clients/routing_manager_client_test.go index 2af458c..bf5f82c 100644 --- a/E2Manager/clients/routing_manager_client_test.go +++ b/E2Manager/clients/routing_manager_client_test.go @@ -50,50 +50,38 @@ func initRoutingManagerClientTest(t *testing.T) (*RoutingManagerClient, *mocks.H func TestDeleteE2TInstanceSuccess(t *testing.T) { rmClient, httpClientMock, config := initRoutingManagerClientTest(t) - e2tToRansAssociations := map[string][]string{ - E2TAddress2: {"test1"}, - } - e2tDataList := convertE2TToRansAssociationsMapToE2TDataList(e2tToRansAssociations) - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"},e2tDataList) + data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil) marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) url := config.RoutingManager.BaseUrl + "e2t" respBody := ioutil.NopCloser(bytes.NewBufferString("")) httpClientMock.On("Delete", url, "application/json", body).Return(&http.Response{StatusCode: http.StatusOK, Body: respBody}, nil) - err := rmClient.DeleteE2TInstance(E2TAddress, []string{"test1"}, e2tToRansAssociations) + err := rmClient.DeleteE2TInstance(E2TAddress, []string{"test1"}) assert.Nil(t, err) } func TestDeleteE2TInstanceFailure(t *testing.T) { rmClient, httpClientMock, config := initRoutingManagerClientTest(t) - e2tToRansAssociations := map[string][]string{ - E2TAddress2: {"test1"}, - } - e2tDataList := convertE2TToRansAssociationsMapToE2TDataList(e2tToRansAssociations) - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"},e2tDataList) + data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"},nil) marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) url := config.RoutingManager.BaseUrl + "e2t" respBody := ioutil.NopCloser(bytes.NewBufferString("")) httpClientMock.On("Delete", url, "application/json", body).Return(&http.Response{StatusCode: http.StatusBadRequest, Body: respBody}, nil) - err := rmClient.DeleteE2TInstance(E2TAddress, []string{"test1"}, e2tToRansAssociations) + err := rmClient.DeleteE2TInstance(E2TAddress, []string{"test1"}) assert.IsType(t, &e2managererrors.RoutingManagerError{}, err) } func TestDeleteE2TInstanceDeleteFailure(t *testing.T) { rmClient, httpClientMock, config := initRoutingManagerClientTest(t) - e2tToRansAssociations := map[string][]string{ - E2TAddress2: {"test1"}, - } - e2tDataList := convertE2TToRansAssociationsMapToE2TDataList(e2tToRansAssociations) - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"},e2tDataList) + data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"},nil) marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) url := config.RoutingManager.BaseUrl + "e2t" httpClientMock.On("Delete", url, "application/json", body).Return(&http.Response{}, errors.New("error")) - err := rmClient.DeleteE2TInstance(E2TAddress, []string{"test1"}, e2tToRansAssociations) + err := rmClient.DeleteE2TInstance(E2TAddress, []string{"test1"}) assert.IsType(t, &e2managererrors.RoutingManagerError{}, err) } diff --git a/E2Manager/container-tag.yaml b/E2Manager/container-tag.yaml index a789c9f..d2a66d2 100644 --- a/E2Manager/container-tag.yaml +++ b/E2Manager/container-tag.yaml @@ -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. --- -tag: 3.0.5.2 +tag: 4.0.2 diff --git a/E2Manager/go.mod b/E2Manager/go.mod index 59a3fc9..39966d0 100644 --- a/E2Manager/go.mod +++ b/E2Manager/go.mod @@ -1,13 +1,13 @@ module e2mgr require ( - gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.29 - gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.29 - gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.29 + gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.32 + gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.32 + gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.32 gerrit.o-ran-sc.org/r/ric-plt/sdlgo v0.5.2 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect github.com/go-ozzo/ozzo-validation v3.5.0+incompatible - github.com/golang/protobuf v1.3.2 + github.com/golang/protobuf v1.3.4 github.com/gorilla/mux v1.7.0 github.com/magiconair/properties v1.8.1 github.com/pelletier/go-toml v1.5.0 // indirect diff --git a/E2Manager/go.sum b/E2Manager/go.sum index ad692e7..a72c008 100644 --- a/E2Manager/go.sum +++ b/E2Manager/go.sum @@ -1,10 +1,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.29 h1:T0ydbEy2pmP2n8A/eyx5iF5PNm0XYa3A5G5HmXsN0Wo= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.29/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.29 h1:H/6CeGFUwS4S1DJ2OVwjt/qKmm/VTdgcgHcxBJfrQt4= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.29/go.mod h1:Fh23KkroYw5CRBh39WzZzxpKSkpQWL3scdzGnMngLo8= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.29 h1:eke+zU8y2gQmEBxAQryBXwBWwvXSHeu+pC11t8luQBQ= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.29/go.mod h1:EPOJ7YGXDS5F+IK1pa9cv2JYlj73PYOXVvgolhhCSfM= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.32 h1:rth8ETFAQxKd5LzB/j8Xic5gDU/NQ4K9LBioBXBMMb4= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.32/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.32 h1:9xffoKE1Y4FR6KzncK/FhjbljoshPT90kDSeU78H6G8= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.32/go.mod h1:G+4sUBMbLfQ+RrGS65U15tKmbnP+/1b5oLTPmMfyfT4= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.32 h1:TSpWWIccJhSyvqBibXQFgyP13KqhsFA14auTSqvEpz0= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.32/go.mod h1:oPHTwdTeaOEuvqVRAog9WoCTW7O6ynE6rOyFB/sp9C0= gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2 h1:UK7awyRKIkVdokWvvkYvazlg3EWIfMnIqCcJxTnLlDA= gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= @@ -50,8 +50,8 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U= diff --git a/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler.go b/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler.go new file mode 100644 index 0000000..603458e --- /dev/null +++ b/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler.go @@ -0,0 +1,166 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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 rmrmsghandlers + +import ( + "bytes" + "e2mgr/logger" + "e2mgr/managers" + "e2mgr/models" + "e2mgr/rmrCgo" + "e2mgr/services" + "e2mgr/services/rmrsender" + "e2mgr/utils" + "encoding/xml" + "errors" + "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" +) + +type E2SetupRequestNotificationHandler struct { + logger *logger.Logger + e2tInstancesManager managers.IE2TInstancesManager + rmrSender *rmrsender.RmrSender + rNibDataService services.RNibDataService + e2tAssociationManager *managers.E2TAssociationManager +} + +func NewE2SetupRequestNotificationHandler(logger *logger.Logger, e2tInstancesManager managers.IE2TInstancesManager, rmrSender *rmrsender.RmrSender, rNibDataService services.RNibDataService, e2tAssociationManager *managers.E2TAssociationManager) E2SetupRequestNotificationHandler { + return E2SetupRequestNotificationHandler{ + logger: logger, + e2tInstancesManager: e2tInstancesManager, + rmrSender: rmrSender, + rNibDataService: rNibDataService, + e2tAssociationManager: e2tAssociationManager, + } +} + +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) + + setupRequest, e2tIpAddress, err := h.parseSetupRequest(request.Payload) + if err != nil { + h.logger.Errorf(err.Error()) + return + } + + h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - E2T Address: %s - handling E2_SETUP_REQUEST", e2tIpAddress) + + _, err = h.e2tInstancesManager.GetE2TInstance(e2tIpAddress) + + if err != nil { + h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed retrieving E2TInstance. error: %s", err) + return + } + + nodebInfo, err := h.rNibDataService.GetNodeb(ranName) + if err != nil{ + if _, ok := err.(*common.ResourceNotFoundError); ok{ + nbIdentity := h.buildNbIdentity(ranName, setupRequest) + nodebInfo = h.buildNodebInfo(ranName, e2tIpAddress, setupRequest) + err = h.rNibDataService.SaveNodeb(nbIdentity, nodebInfo) + if err != nil{ + h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to save nodebInfo entity. Error: %s", ranName, err) + return + } + } else{ + h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to retrieve nodebInfo entity. Error: %s", ranName, err) + return + } + + } else { + if nodebInfo.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN { + h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", nodebInfo.RanName, nodebInfo.ConnectionStatus) + h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling setup request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime)) + return + } + h.updateNodeBFunctions(nodebInfo, setupRequest) + } + 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) + return + } + successResponse := &models.E2SetupSuccessResponseMessage{} + successResponse.SetPlmnId(setupRequest.GetPlmnId()) + successResponse.SetNbId("&" + fmt.Sprintf("%020b", 0xf0)) + responsePayload, err := xml.Marshal(successResponse) + if err != nil{ + h.logger.Warnf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - Error marshalling E2 Setup Response. Response: %x", 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) + //TODO err = h.rmrSender.Send(msg) + +} + +func (h E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte)(*models.E2SetupRequestMessage, string, error){ + + 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") + } + + e2tIpAddress := string(payload[:colonInd]) + if len(e2tIpAddress) == 0 { + return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Empty E2T Address received") + } + + pipInd := bytes.IndexByte(payload, '|') + if pipInd < 0 { + return nil, "", errors.New( "#E2SetupRequestNotificationHandler.parseSetupRequest - Error parsing E2 Setup Request failed extract Payload: no | separator found") + } + + setupRequest := &models.E2SetupRequestMessage{} + err := xml.Unmarshal(payload[pipInd + 1:], &setupRequest) + if err != nil { + return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Error unmarshalling E2 Setup Request payload: %s") + } + + return setupRequest, e2tIpAddress, nil +} + +func (h E2SetupRequestNotificationHandler) updateNodeBFunctions(nodeB *entities.NodebInfo, request *models.E2SetupRequestMessage){ + //TODO the function should be implemented in the scope of the US 192 "Save the entire Setup request in RNIB" +} + +func (h E2SetupRequestNotificationHandler) buildNodebInfo(ranName string, e2tAddress string, request *models.E2SetupRequestMessage) *entities.NodebInfo{ + nodebInfo := &entities.NodebInfo{ + AssociatedE2TInstanceAddress: e2tAddress, + ConnectionStatus: entities.ConnectionStatus_CONNECTED, + RanName: ranName, + NodeType: entities.Node_GNB, + Configuration: &entities.NodebInfo_Gnb{Gnb: &entities.Gnb{}}, + } + h.updateNodeBFunctions(nodebInfo, request) + return nodebInfo +} + +func (h E2SetupRequestNotificationHandler) buildNbIdentity(ranName string, setupRequest *models.E2SetupRequestMessage)*entities.NbIdentity{ + return &entities.NbIdentity{ + InventoryName:ranName, + GlobalNbId: &entities.GlobalNbId{ + PlmnId: setupRequest.GetPlmnId(), + NbId: setupRequest.GetNbId(), + }, + } +} \ No newline at end of file diff --git a/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler_test.go b/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler_test.go new file mode 100644 index 0000000..ad3d0ca --- /dev/null +++ b/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler_test.go @@ -0,0 +1,524 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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 rmrmsghandlers + +import ( + "bytes" + "e2mgr/configuration" + "e2mgr/logger" + "e2mgr/managers" + "e2mgr/mocks" + "e2mgr/models" + "e2mgr/services" + "e2mgr/tests" + "errors" + "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/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "io" + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +const ( + prefix = "10.0.2.15:9999|" + logFilePath = "./loggerTest.txt" + e2tInstanceAddress = "10.0.2.15" + nodebRanName = "gnb:310-410-b5c67788" +) + +func TestE2SetupRequestNotificationHandler_HandleNewGnbSuccess(t *testing.T) { + path, err :=filepath.Abs("../../tests/resources/setupRequest_gnb.xml") + if err != nil { + t.Fatal(err) + } + xmlGnb, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + logFile, err := os.Create(logFilePath) + if err != nil{ + t.Errorf("e2_setup_request_notification_handler_test.TestE2SetupRequestNotificationHandler_HandleNewGnbSuccess - failed to create file, error: %s", err) + } + oldStdout := os.Stdout + defer changeStdout(oldStdout) + defer removeLogFile(t) + os.Stdout = logFile + + handler := stubMockSuccessFlowNewNodeb(t) + prefBytes := []byte(prefix) + notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)} + handler.Handle(notificationRequest) + assertSuccessFlowNewNodebLogs(t) +} + +func TestE2SetupRequestNotificationHandler_HandleNewEnGnbSuccess(t *testing.T) { + path, err :=filepath.Abs("../../tests/resources/setupRequest_en-gNB.xml") + if err != nil { + t.Fatal(err) + } + xmlEnGnb, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + logFile, err := os.Create(logFilePath) + if err != nil{ + t.Errorf("e2_setup_request_notification_handler_test.TestE2SetupRequestNotificationHandler_HandleNewEnGnbSuccess - failed to create file, error: %s", err) + } + oldStdout := os.Stdout + defer changeStdout(oldStdout) + defer removeLogFile(t) + os.Stdout = logFile + + handler := stubMockSuccessFlowNewNodeb(t) + prefBytes := []byte(prefix) + notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlEnGnb...)} + handler.Handle(notificationRequest) + assertSuccessFlowNewNodebLogs(t) +} + +func TestE2SetupRequestNotificationHandler_HandleNewNgEnbSuccess(t *testing.T) { + path, err :=filepath.Abs("../../tests/resources/setupRequest_ng-eNB.xml") + if err != nil { + t.Fatal(err) + } + xmlEnGnb, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + logFile, err := os.Create(logFilePath) + if err != nil{ + t.Errorf("e2_setup_request_notification_handler_test.TestE2SetupRequestNotificationHandler_HandleNewNgEnbSuccess - failed to create file, error: %s", err) + } + oldStdout := os.Stdout + defer changeStdout(oldStdout) + defer removeLogFile(t) + os.Stdout = logFile + + handler := stubMockSuccessFlowNewNodeb(t) + prefBytes := []byte(prefix) + notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlEnGnb...)} + handler.Handle(notificationRequest) + assertSuccessFlowNewNodebLogs(t) +} + +func TestE2SetupRequestNotificationHandler_HandleExistingGnbSuccess(t *testing.T) { + path, err :=filepath.Abs("../../tests/resources/setupRequest_gnb.xml") + if err != nil { + t.Fatal(err) + } + xmlGnb, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + logFile, err := os.Create(logFilePath) + if err != nil{ + t.Errorf("e2_setup_request_notification_handler_test.TestE2SetupRequestNotificationHandler_HandleNewGnbSuccess - failed to create file, error: %s", err) + } + oldStdout := os.Stdout + defer changeStdout(oldStdout) + defer removeLogFile(t) + os.Stdout = logFile + + handler := stubMockSuccessFlowExistingNodeb(t) + prefBytes := []byte(prefix) + notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)} + handler.Handle(notificationRequest) + assertSuccessFlowExistingNodebLogs(t) +} + +func TestE2SetupRequestNotificationHandler_HandleParseError(t *testing.T) { + path, err :=filepath.Abs("../../tests/resources/setupRequest_gnb.xml") + if err != nil { + t.Fatal(err) + } + xmlGnb, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + logFile, err := os.Create(logFilePath) + if err != nil{ + t.Errorf("e2_setup_request_notification_handler_test.TestE2SetupRequestNotificationHandler_HandleNewGnbSuccess - failed to create file, error: %s", err) + } + oldStdout := os.Stdout + defer changeStdout(oldStdout) + defer removeLogFile(t) + os.Stdout = logFile + + _, handler, _, _, _, _, _ := initMocks(t) + prefBytes := []byte("invalid_prefix") + notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)} + handler.Handle(notificationRequest) + assertParseErrorFlowLogs(t) +} + +func TestE2SetupRequestNotificationHandler_HandleUnmarshalError(t *testing.T) { + logFile, err := os.Create(logFilePath) + if err != nil{ + t.Errorf("e2_setup_request_notification_handler_test.TestE2SetupRequestNotificationHandler_HandleNewGnbSuccess - failed to create file, error: %s", err) + } + oldStdout := os.Stdout + defer changeStdout(oldStdout) + defer removeLogFile(t) + os.Stdout = logFile + + _, handler, _, _, _, _, _ := initMocks(t) + prefBytes := []byte(prefix) + notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, "xmlGnb"...)} + handler.Handle(notificationRequest) + assertUnmarshalErrorFlowLogs(t) +} + +func TestE2SetupRequestNotificationHandler_HandleGetE2TInstanceError(t *testing.T) { + path, err :=filepath.Abs("../../tests/resources/setupRequest_gnb.xml") + if err != nil { + t.Fatal(err) + } + xmlGnb, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + logFile, err := os.Create(logFilePath) + if err != nil{ + t.Errorf("e2_setup_request_notification_handler_test.TestE2SetupRequestNotificationHandler_HandleNewGnbSuccess - failed to create file, error: %s", err) + } + oldStdout := os.Stdout + defer changeStdout(oldStdout) + defer removeLogFile(t) + os.Stdout = logFile + + _, handler, _, _, _, e2tInstancesManagerMock, _ := initMocks(t) + var e2tInstance * entities.E2TInstance + e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewResourceNotFoundError("Not found")) + prefBytes := []byte(prefix) + notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)} + handler.Handle(notificationRequest) + assertGetE2TInstanceErrorLogs(t) +} + +func TestE2SetupRequestNotificationHandler_HandleGetNodebError(t *testing.T) { + path, err :=filepath.Abs("../../tests/resources/setupRequest_gnb.xml") + if err != nil { + t.Fatal(err) + } + xmlGnb, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + logFile, err := os.Create(logFilePath) + if err != nil{ + t.Errorf("e2_setup_request_notification_handler_test.TestE2SetupRequestNotificationHandler_HandleNewGnbSuccess - failed to create file, error: %s", err) + } + oldStdout := os.Stdout + defer changeStdout(oldStdout) + defer removeLogFile(t) + os.Stdout = logFile + _, handler, readerMock, _, _, e2tInstancesManagerMock, _ := initMocks(t) + var e2tInstance = &entities.E2TInstance{} + e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) + var gnb *entities.NodebInfo + readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewInternalError(errors.New("Some error"))) + prefBytes := []byte(prefix) + notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)} + handler.Handle(notificationRequest) + assertGetNodebErrorLogs(t) +} + +func TestE2SetupRequestNotificationHandler_HandleAssociationError(t *testing.T) { + path, err :=filepath.Abs("../../tests/resources/setupRequest_gnb.xml") + if err != nil { + t.Fatal(err) + } + xmlGnb, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + logFile, err := os.Create(logFilePath) + if err != nil{ + t.Errorf("e2_setup_request_notification_handler_test.TestE2SetupRequestNotificationHandler_HandleNewGnbSuccess - failed to create file, error: %s", err) + } + oldStdout := os.Stdout + defer changeStdout(oldStdout) + defer removeLogFile(t) + os.Stdout = logFile + + _, handler, readerMock, writerMock, _, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t) + var e2tInstance = &entities.E2TInstance{} + e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) + var gnb *entities.NodebInfo + readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found")) + writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil) + routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceAddress, mock.Anything).Return(errors.New("association error")) + + prefBytes := []byte(prefix) + notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)} + handler.Handle(notificationRequest) + assertAssociationErrorLogs(t) +} + +func TestE2SetupRequestNotificationHandler_HandleExistingGnbInvalidStatusError(t *testing.T) { + path, err :=filepath.Abs("../../tests/resources/setupRequest_gnb.xml") + if err != nil { + t.Fatal(err) + } + xmlGnb, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + logFile, err := os.Create(logFilePath) + if err != nil{ + t.Errorf("e2_setup_request_notification_handler_test.TestE2SetupRequestNotificationHandler_HandleNewGnbSuccess - failed to create file, error: %s", err) + } + oldStdout := os.Stdout + defer changeStdout(oldStdout) + defer removeLogFile(t) + os.Stdout = logFile + + handler := stubMockInvalidStatusFlowExistingNodeb(t) + prefBytes := []byte(prefix) + notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)} + handler.Handle(notificationRequest) + assertInvalidNodebStatusLogs(t) +} + +func assertInvalidNodebStatusLogs(t *testing.T){ + buf := getLogFileBuffer(t) + assertReceivedAndParsedLog(buf, t) + assertInvalidNodebStatusLog(buf, t) + assertNoMoreRecordsLog(buf, t) +} + +func assertInvalidNodebStatusLog(buf *bytes.Buffer, t *testing.T) { + record, _ := buf.ReadString('\n') + assert.Contains(t, record, "#RnibDataService.GetNodeb") + assert.Contains(t, record, "connection status: SHUTTING_DOWN") + record, _ = buf.ReadString('\n') + assert.Contains(t, record, "#E2SetupRequestNotificationHandler.Handle") + assert.Contains(t, record, "connection status: SHUTTING_DOWN - nodeB entity in incorrect state") + record, _ = buf.ReadString('\n') + assert.Contains(t, record, "#E2SetupRequestNotificationHandler.Handle") + assert.Contains(t, record, "Summary: elapsed time for receiving and handling setup request message from E2 terminator") +} + +func assertAssociationErrorLogs(t *testing.T){ + buf := getLogFileBuffer(t) + assertReceivedAndParsedLog(buf, t) + assertNewNodebSavedLog(buf, t) + assertAssociationErrorLog(buf, t) + assertNoMoreRecordsLog(buf, t) +} + +func assertAssociationErrorLog(buf *bytes.Buffer, t *testing.T) { + record, _ := buf.ReadString('\n') + assert.Contains(t, record, "#E2TAssociationManager.AssociateRan - Associating RAN") + record, _ = buf.ReadString('\n') + assert.Contains(t, record, "#E2TAssociationManager.AssociateRan - RoutingManager failure: Failed to associate RAN") + record, _ = buf.ReadString('\n') + assert.Contains(t, record, "#E2SetupRequestNotificationHandler.Handle - RAN name:") + assert.Contains(t, record, "failed to associate E2T to nodeB entity") +} + +func assertGetNodebErrorLogs(t *testing.T) { + buf := getLogFileBuffer(t) + assertReceivedAndParsedLog(buf, t) + assertGetNodebErrorLog(buf, t) + assertNoMoreRecordsLog(buf, t) +} + +func assertGetNodebErrorLog(buf *bytes.Buffer, t *testing.T) { + record, _ := buf.ReadString('\n') + assert.Contains(t, record, "failed to retrieve nodebInfo entity") +} + +func assertGetE2TInstanceErrorLogs(t *testing.T) { + buf := getLogFileBuffer(t) + assertReceivedAndParsedLog(buf, t) + assertGetE2TInstanceErrorLog(buf, t) + assertNoMoreRecordsLog(buf, t) +} + +func assertGetE2TInstanceErrorLog(buf *bytes.Buffer, t *testing.T) { + record, _ := buf.ReadString('\n') + assert.Contains(t, record, "Failed retrieving E2TInstance") +} + +func removeLogFile(t *testing.T) { + err := os.Remove(logFilePath) + if err != nil { + t.Errorf("e2_setup_request_notification_handler_test.TestE2SetupRequestNotificationHandler_HandleGnbSuccess - failed to remove file, error: %s", err) + } +} + +func assertParseErrorFlowLogs(t *testing.T) { + buf := getLogFileBuffer(t) + assertReceivedAndFailedParseLog(buf, t) + assertNoMoreRecordsLog(buf, t) +} + +func assertUnmarshalErrorFlowLogs(t *testing.T) { + buf := getLogFileBuffer(t) + assertReceivedAndFailedUnmarshalLog(buf, t) + assertNoMoreRecordsLog(buf, t) +} + +func assertSuccessFlowNewNodebLogs(t *testing.T){ + buf := getLogFileBuffer(t) + assertReceivedAndParsedLog(buf, t) + assertNewNodebSavedLog(buf, t) + assertAssociatedLog(buf, t) + assertRequestBuiltLog(buf, t) + assertNoMoreRecordsLog(buf, t) +} + +func assertSuccessFlowExistingNodebLogs(t *testing.T){ + buf := getLogFileBuffer(t) + assertReceivedAndParsedLog(buf, t) + assertExistingNodebRetrievedLog(buf, t) + assertAssociatedLog(buf, t) + assertRequestBuiltLog(buf, t) + assertNoMoreRecordsLog(buf, t) +} + +func assertReceivedAndParsedLog(buf *bytes.Buffer, t *testing.T) { + record, _ := buf.ReadString('\n') + assert.Contains(t, record, "received E2 Setup Request") + record, _ = buf.ReadString('\n') + assert.Contains(t, record, "handling E2_SETUP_REQUEST") +} + +func assertReceivedAndFailedParseLog(buf *bytes.Buffer, t *testing.T) { + record, _ := buf.ReadString('\n') + assert.Contains(t, record, "received E2 Setup Request") + record, _ = buf.ReadString('\n') + assert.Contains(t, record, "Error parsing E2 Setup Request") +} + +func assertReceivedAndFailedUnmarshalLog(buf *bytes.Buffer, t *testing.T) { + record, _ := buf.ReadString('\n') + assert.Contains(t, record, "received E2 Setup Request") + record, _ = buf.ReadString('\n') + assert.Contains(t, record, "Error unmarshalling E2 Setup Request") +} + +func assertNewNodebSavedLog(buf *bytes.Buffer, t *testing.T) { + record, _ := buf.ReadString('\n') + assert.Contains(t, record, "#RnibDataService.SaveNodeb - nbIdentity:") +} + +func assertExistingNodebRetrievedLog(buf *bytes.Buffer, t *testing.T) { + record, _ := buf.ReadString('\n') + assert.Contains(t, record, "#RnibDataService.GetNodeb - RAN name:") +} + +func assertAssociatedLog(buf *bytes.Buffer, t *testing.T){ + record, _ := buf.ReadString('\n') + assert.Contains(t, record, "#E2TAssociationManager.AssociateRan - Associating RAN") + record, _ = buf.ReadString('\n') + assert.Contains(t, record, "#RnibDataService.UpdateNodebInfo") + record, _ = buf.ReadString('\n') + assert.Contains(t, record, "#E2TAssociationManager.AssociateRan - successfully associated RAN") +} + +func assertRequestBuiltLog(buf *bytes.Buffer, t *testing.T) { + record, _ := buf.ReadString('\n') + assert.Contains(t, record, "E2 Setup Request has been built") +} + +func assertNoMoreRecordsLog(buf *bytes.Buffer, t *testing.T) { + record, _ := buf.ReadString('\n') + assert.Empty(t, record) +} + +func stubMockSuccessFlowNewNodeb(t *testing.T) E2SetupRequestNotificationHandler{ + _, handler, readerMock, writerMock, _, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t) + var e2tInstance = &entities.E2TInstance{} + e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) + var gnb *entities.NodebInfo + readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found")) + writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil) + routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceAddress, mock.Anything).Return(nil) + writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil) + e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil) + return handler +} + +func stubMockSuccessFlowExistingNodeb(t *testing.T) E2SetupRequestNotificationHandler{ + _, handler, readerMock, writerMock, _, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t) + var e2tInstance = &entities.E2TInstance{} + e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) + var gnb = &entities.NodebInfo{RanName: nodebRanName} + readerMock.On("GetNodeb", mock.Anything).Return(gnb, nil) + routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceAddress, mock.Anything).Return(nil) + writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil) + e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil) + return handler +} + +func stubMockInvalidStatusFlowExistingNodeb(t *testing.T) E2SetupRequestNotificationHandler{ + _, handler, readerMock, _, _, e2tInstancesManagerMock, _ := initMocks(t) + var e2tInstance = &entities.E2TInstance{} + e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) + var gnb = &entities.NodebInfo{RanName: nodebRanName, ConnectionStatus:entities.ConnectionStatus_SHUTTING_DOWN} + readerMock.On("GetNodeb", mock.Anything).Return(gnb, nil) + return handler +} + +func initMocks(t *testing.T) (*logger.Logger, E2SetupRequestNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock, *mocks.RoutingManagerClientMock) { + logger := tests.InitLog(t) + config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3} + rmrMessengerMock := &mocks.RmrMessengerMock{} + rmrSender := tests.InitRmrSender(rmrMessengerMock, logger) + readerMock := &mocks.RnibReaderMock{} + writerMock := &mocks.RnibWriterMock{} + routingManagerClientMock := &mocks.RoutingManagerClientMock{} + rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock) + e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{} + e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManagerMock, routingManagerClientMock) + handler := NewE2SetupRequestNotificationHandler(logger, e2tInstancesManagerMock, rmrSender, rnibDataService, e2tAssociationManager) + return logger, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock +} + +func changeStdout(old *os.File) { + os.Stdout = old +} + +func getLogFileBuffer(t *testing.T) *bytes.Buffer { + logFile, err := os.Open(logFilePath) + if err != nil { + t.Errorf("e2_setup_request_notification_handler_test.assertSuccessFlowNewNodebLogRecords - failed to open file, error: %s", err) + } + var buf bytes.Buffer + _, err = io.Copy(&buf, logFile) + if err != nil { + t.Errorf("e2_setup_request_notification_handler_test.assertSuccessFlowNewNodebLogRecords - failed to copy bytes, error: %s", err) + } + return &buf +} + diff --git a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go index c75140f..0059b2a 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go @@ -31,18 +31,18 @@ import ( ) type E2TermInitNotificationHandler struct { - logger *logger.Logger - ranReconnectionManager *managers.RanReconnectionManager - e2tInstancesManager managers.IE2TInstancesManager - routingManagerClient clients.IRoutingManagerClient + logger *logger.Logger + ranDisconnectionManager *managers.RanDisconnectionManager + e2tInstancesManager managers.IE2TInstancesManager + routingManagerClient clients.IRoutingManagerClient } -func NewE2TermInitNotificationHandler(logger *logger.Logger, ranReconnectionManager *managers.RanReconnectionManager, e2tInstancesManager managers.IE2TInstancesManager, routingManagerClient clients.IRoutingManagerClient) E2TermInitNotificationHandler { +func NewE2TermInitNotificationHandler(logger *logger.Logger, ranDisconnectionManager *managers.RanDisconnectionManager, e2tInstancesManager managers.IE2TInstancesManager, routingManagerClient clients.IRoutingManagerClient) E2TermInitNotificationHandler { return E2TermInitNotificationHandler{ - logger: logger, - ranReconnectionManager: ranReconnectionManager, - e2tInstancesManager: e2tInstancesManager, - routingManagerClient: routingManagerClient, + logger: logger, + ranDisconnectionManager: ranDisconnectionManager, + e2tInstancesManager: e2tInstancesManager, + routingManagerClient: routingManagerClient, } } @@ -88,13 +88,6 @@ func (h E2TermInitNotificationHandler) Handle(request *models.NotificationReques return } - if e2tInstance.State == entities.RoutingManagerFailure { - err := h.e2tInstancesManager.SetE2tInstanceState(e2tAddress, e2tInstance.State, entities.Active) - if err != nil { - return - } - } - h.HandleExistingE2TInstance(e2tInstance) h.logger.Infof("#E2TermInitNotificationHandler.Handle - Completed handling of E2_TERM_INIT") @@ -104,10 +97,8 @@ func (h E2TermInitNotificationHandler) HandleExistingE2TInstance(e2tInstance *en for _, ranName := range e2tInstance.AssociatedRanList { - if err := h.ranReconnectionManager.ReconnectRan(ranName); err != nil { - h.logger.Errorf("#E2TermInitNotificationHandler.HandleExistingE2TInstance - Ran name: %s - connection attempt failure, error: %s", ranName, err) - _, ok := err.(*common.ResourceNotFoundError) - if !ok { + if err := h.ranDisconnectionManager.DisconnectRan(ranName); err != nil { + if _, ok := err.(*common.ResourceNotFoundError); !ok{ break } } diff --git a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go index 1b7cba6..95b818b 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go @@ -24,7 +24,6 @@ import ( "bytes" "e2mgr/clients" "e2mgr/configuration" - "e2mgr/e2pdus" "e2mgr/logger" "e2mgr/managers" "e2mgr/mocks" @@ -43,17 +42,13 @@ import ( "testing" ) -const e2tInstanceAddress = "10.0.2.15" const e2tInitPayload = "{\"address\":\"10.0.2.15\", \"fqdn\":\"\"}" -func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock, *mocks.RoutingManagerClientMock) { +func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.E2TInstancesManagerMock, *mocks.RoutingManagerClientMock) { logger := initLog(t) config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3} - rmrMessengerMock := &mocks.RmrMessengerMock{} - rmrSender := initRmrSender(rmrMessengerMock, logger) - readerMock := &mocks.RnibReaderMock{} writerMock := &mocks.RnibWriterMock{} @@ -61,25 +56,21 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotifica routingManagerClientMock := &mocks.RoutingManagerClientMock{} rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock) - ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService) e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{} e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManagerMock, routingManagerClientMock) - ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tAssociationManager) - handler := NewE2TermInitNotificationHandler(logger, ranReconnectionManager, e2tInstancesManagerMock, routingManagerClientMock) + ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager) + handler := NewE2TermInitNotificationHandler(logger, ranDisconnectionManager, e2tInstancesManagerMock, routingManagerClientMock) - return logger, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock + return logger, handler, readerMock, writerMock, e2tInstancesManagerMock, routingManagerClientMock } -func initRanLostConnectionTestWithRealE2tInstanceManager(t *testing.T) (*logger.Logger, *configuration.Configuration, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.HttpClientMock) { +func initRanLostConnectionTestWithRealE2tInstanceManager(t *testing.T) (*logger.Logger, *configuration.Configuration, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) { logger := initLog(t) config := configuration.ParseConfiguration() - rmrMessengerMock := &mocks.RmrMessengerMock{} - rmrSender := initRmrSender(rmrMessengerMock, logger) - readerMock := &mocks.RnibReaderMock{} writerMock := &mocks.RnibWriterMock{} @@ -87,17 +78,16 @@ func initRanLostConnectionTestWithRealE2tInstanceManager(t *testing.T) (*logger. routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClientMock) rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock) - ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService) e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger) e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient) - ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tAssociationManager) - handler := NewE2TermInitNotificationHandler(logger, ranReconnectionManager, e2tInstancesManager, routingManagerClient) - return logger, config, handler, readerMock, writerMock, rmrMessengerMock, httpClientMock + ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager) + handler := NewE2TermInitNotificationHandler(logger, ranDisconnectionManager, e2tInstancesManager, routingManagerClient) + return logger, config, handler, readerMock, writerMock, httpClientMock } func TestE2TermInitUnmarshalPayloadFailure(t *testing.T) { - _, handler, _, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) + _, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte("asd")} handler.Handle(notificationRequest) e2tInstancesManagerMock.AssertNotCalled(t, "GetE2TInstance") @@ -105,7 +95,7 @@ func TestE2TermInitUnmarshalPayloadFailure(t *testing.T) { } func TestE2TermInitEmptyE2TAddress(t *testing.T) { - _, handler, _, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) + _, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte("{\"address\":\"\"}")} handler.Handle(notificationRequest) e2tInstancesManagerMock.AssertNotCalled(t, "GetE2TInstance") @@ -113,7 +103,7 @@ func TestE2TermInitEmptyE2TAddress(t *testing.T) { } func TestE2TermInitGetE2TInstanceFailure(t *testing.T) { - _, handler, _, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) + _, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) var e2tInstance *entities.E2TInstance e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewInternalError(fmt.Errorf("internal error"))) notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} @@ -122,17 +112,16 @@ func TestE2TermInitGetE2TInstanceFailure(t *testing.T) { } func TestE2TermInitGetE2TInstanceDbFailure(t *testing.T) { - _, _, handler, readerMock, writerMock, rmrMessengerMock,_ := initRanLostConnectionTestWithRealE2tInstanceManager(t) + _, _, handler, readerMock, writerMock, _ := initRanLostConnectionTestWithRealE2tInstanceManager(t) var e2tInstance *entities.E2TInstance readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewInternalError(fmt.Errorf("internal error"))) notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} handler.Handle(notificationRequest) writerMock.AssertNotCalled(t, "UpdateNodebInfo") - rmrMessengerMock.AssertNotCalled(t, "SendMsg") } func TestE2TermInitNewE2TInstance(t *testing.T) { - _, config, handler, readerMock, writerMock, _, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t) + _, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t) var e2tInstance *entities.E2TInstance readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewResourceNotFoundError("not found")) @@ -156,8 +145,9 @@ func TestE2TermInitNewE2TInstance(t *testing.T) { writerMock.AssertCalled(t, "SaveE2TAddresses", e2tAddresses) } -func TestE2TermInitNewE2TInstance_RoutingManagerError(t *testing.T) { - _, config, handler, readerMock, writerMock, _, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t) +func TestE2TermInitNewE2TInstance__RoutingManagerError(t *testing.T) { + _, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t) + var e2tInstance *entities.E2TInstance readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewResourceNotFoundError("not found")) @@ -168,13 +158,11 @@ func TestE2TermInitNewE2TInstance_RoutingManagerError(t *testing.T) { notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} handler.Handle(notificationRequest) - httpClientMock.AssertCalled(t, "Post", url, mock.Anything, mock.Anything) - writerMock.AssertNotCalled(t, "SaveE2TInstance", mock.Anything) - writerMock.AssertNotCalled(t, "SaveE2TAddresses", mock.Anything) + writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 0) } func TestE2TermInitExistingE2TInstanceNoAssociatedRans(t *testing.T) { - _, handler, _, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) + _, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} @@ -183,125 +171,94 @@ func TestE2TermInitExistingE2TInstanceNoAssociatedRans(t *testing.T) { } func TestE2TermInitHandlerSuccessOneRan(t *testing.T) { - _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) - var rnibErr error + _, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t) - var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} + var rnibErr error + var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr) - var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} + var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) - payload := e2pdus.PackedX2setupRequest - xaction := []byte(RanName) - msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction) + var disconnectedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} + readerMock.On("GetNodeb", RanName).Return(disconnectedNodeb, rnibErr) - rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil) + var updatedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""} + writerMock.On("UpdateNodebInfo", updatedNodeb).Return(rnibErr) e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) - e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) - notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} - - handler.Handle(notificationRequest) - - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) -} - -func TestE2TermInitHandlerSuccessOneRanShuttingdown(t *testing.T) { - _, _, handler, readerMock, writerMock, rmrMessengerMock,_ := initRanLostConnectionTestWithRealE2tInstanceManager(t) - var rnibErr error - - var initialNodeb = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr) - - var argNodeb = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 0} - writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) - - payload := e2pdus.PackedX2setupRequest - xaction := []byte(RanName) - msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction) + readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil) + writerMock.On("SaveE2TInstance", mock.Anything).Return(nil) - rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil) + respBody := ioutil.NopCloser(bytes.NewBufferString("")) + url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix + httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil) - e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) - e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) - readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} handler.Handle(notificationRequest) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) - rmrMessengerMock.AssertNotCalled(t, "SendMsg") + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) + writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1) + httpClientMock.AssertNumberOfCalls(t, "Post", 1) } -func TestE2TermInitHandlerSuccessOneRan_ToBeDeleted(t *testing.T) { - _, _, handler, readerMock, writerMock, rmrMessengerMock, httpClientMock:= initRanLostConnectionTestWithRealE2tInstanceManager(t) - var rnibErr error +func TestE2TermInitHandlerSuccessOneRan_RoutingManagerError(t *testing.T) { + _, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t) - var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} + var rnibErr error + var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr) - var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} + var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) - payload := e2pdus.PackedX2setupRequest - xaction := []byte(RanName) - msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction) + var disconnectedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} + readerMock.On("GetNodeb", RanName).Return(disconnectedNodeb, rnibErr) - rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil) + var updatedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""} + writerMock.On("UpdateNodebInfo", updatedNodeb).Return(rnibErr) e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) - e2tInstance.State = entities.ToBeDeleted e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) + readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil) + writerMock.On("SaveE2TInstance", mock.Anything).Return(nil) + + url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix + httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{}, errors.New("error")) - readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} handler.Handle(notificationRequest) - httpClientMock.AssertNotCalled(t, "Post", mock.Anything, mock.Anything, mock.Anything) - writerMock.AssertNotCalled(t, "UpdateNodebInfo") - rmrMessengerMock.AssertNotCalled(t, "SendMsg") + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) + writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1) + httpClientMock.AssertNumberOfCalls(t, "Post", 1) } -func TestE2TermInitHandlerSuccessTwoRans_RoutingManagerFailure(t *testing.T) { - _, _, handler, readerMock, writerMock, rmrMessengerMock, httpClientMock:= initRanLostConnectionTestWithRealE2tInstanceManager(t) - +func TestE2TermInitHandlerSuccessOneRanShuttingdown(t *testing.T) { + _, _, handler, readerMock, writerMock, _ := initRanLostConnectionTestWithRealE2tInstanceManager(t) var rnibErr error - var initialNodeb0 = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb1 = &entities.NodebInfo{RanName: "test2", ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", RanName).Return(initialNodeb0, rnibErr) - readerMock.On("GetNodeb", "test2").Return(initialNodeb1, rnibErr) - writerMock.On("UpdateNodebInfo", mock.Anything).Return(rnibErr) - payload := e2pdus.PackedX2setupRequest - xaction := []byte(RanName) - msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction) + var initialNodeb = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} + readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr) - rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil) + var argNodeb = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 0} + writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) - e2tInstance.State = entities.RoutingManagerFailure - e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName, "test2") - + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) - writerMock.On("SaveE2TInstance", mock.Anything).Return(nil) - notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} handler.Handle(notificationRequest) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) - - httpClientMock.AssertNotCalled(t, "Post", mock.Anything, mock.Anything, mock.Anything) - writerMock.AssertCalled(t, "SaveE2TInstance", mock.Anything) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) } -func TestE2TermInitHandlerSuccessOneRan_RoutingManagerFailure_Error(t *testing.T) { - _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) +func TestE2TermInitHandlerSuccessOneRan_ToBeDeleted(t *testing.T) { + _, _, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t) var rnibErr error var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} @@ -310,209 +267,171 @@ func TestE2TermInitHandlerSuccessOneRan_RoutingManagerFailure_Error(t *testing.T var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) - payload := e2pdus.PackedX2setupRequest - xaction := []byte(RanName) - msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction) - - rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil) - e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) - e2tInstance.State = entities.RoutingManagerFailure + e2tInstance.State = entities.ToBeDeleted e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) - e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) - e2tInstancesManagerMock.On("SetE2tInstanceState", e2tInstanceAddress, e2tInstance.State, entities.Active).Return(fmt.Errorf(" Error ")) - writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) - + readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} handler.Handle(notificationRequest) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) + httpClientMock.AssertNotCalled(t, "Post", mock.Anything, mock.Anything, mock.Anything) + writerMock.AssertNotCalled(t, "UpdateNodebInfo") } func TestE2TermInitHandlerSuccessTwoRans(t *testing.T) { - _, _, handler, readerMock, writerMock, rmrMessengerMock, httpClientMock:= initRanLostConnectionTestWithRealE2tInstanceManager(t) - var rnibErr error - var initialNodeb0 = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb1 = &entities.NodebInfo{RanName: "test2", ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", RanName).Return(initialNodeb0, rnibErr) - readerMock.On("GetNodeb", "test2").Return(initialNodeb1, rnibErr) - writerMock.On("UpdateNodebInfo", mock.Anything).Return(rnibErr) - payload := e2pdus.PackedX2setupRequest - xaction := []byte(RanName) - msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction) + _, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t) - rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil) + var rnibErr error + test2 := "test2" - e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) - e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName, "test2") - readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) - notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} + //First RAN + var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} + var disconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} + readerMock.On("GetNodeb", RanName).Return(firstRan, rnibErr).Return(disconnectedFirstRan, rnibErr) - handler.Handle(notificationRequest) + var updatedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} + writerMock.On("UpdateNodebInfo", updatedFirstRan).Return(rnibErr) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2) - httpClientMock.AssertNotCalled(t, "Post", mock.Anything, mock.Anything, mock.Anything) -} - -func TestE2TermInitHandlerSuccessTwoRansSecondRanShutdown(t *testing.T) { - _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) - var rnibErr error - var initialNodeb0 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb1 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", RanName).Return(initialNodeb0, rnibErr) - readerMock.On("GetNodeb", "test2").Return(initialNodeb1, rnibErr) + var updatedDisconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""} + writerMock.On("UpdateNodebInfo", updatedDisconnectedFirstRan).Return(rnibErr) - var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) + //Second RAN + var secondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"} + var disconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"} + readerMock.On("GetNodeb", test2).Return(secondRan, rnibErr).Return(disconnectedSecondRan, rnibErr) - payload := e2pdus.PackedX2setupRequest - xaction := []byte(RanName) - msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction) + var updatedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"} + writerMock.On("UpdateNodebInfo", updatedSecondRan).Return(rnibErr) - rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil) + var updatedDisconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: ""} + writerMock.On("UpdateNodebInfo", updatedDisconnectedSecondRan).Return(rnibErr) e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) - e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName, "test2") - e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2) + readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil) + writerMock.On("SaveE2TInstance", mock.Anything).Return(nil) + + respBody := ioutil.NopCloser(bytes.NewBufferString("")) + url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix + httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil) + notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} handler.Handle(notificationRequest) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) - writerMock.AssertExpectations(t) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 4) + writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 2) + httpClientMock.AssertNumberOfCalls(t, "Post", 2) } -func TestE2TermInitHandlerSuccessThreeRansFirstRmrFailure(t *testing.T) { - log, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) - var rnibErr error +func TestE2TermInitHandlerSuccessTwoRansSecondRanShutdown(t *testing.T) { + _, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t) - ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}} + var rnibErr error + test2 := "test2" - var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr) - readerMock.On("GetNodeb", ids[1].InventoryName).Return(initialNodeb1, rnibErr) - readerMock.On("GetNodeb", ids[2].InventoryName).Return(initialNodeb2, rnibErr) + //First RAN + var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} + var disconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} + readerMock.On("GetNodeb", RanName).Return(firstRan, rnibErr).Return(disconnectedFirstRan, rnibErr) - var argNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - var argNodeb0Fail = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 0} - writerMock.On("UpdateNodebInfo", argNodeb0).Return(rnibErr) - writerMock.On("UpdateNodebInfo", argNodeb0Fail).Return(rnibErr) + var updatedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} + writerMock.On("UpdateNodebInfo", updatedFirstRan).Return(rnibErr) - payload := models.NewE2RequestMessage(ids[0].InventoryName /*tid*/, "", 0, ids[0].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) - xaction := []byte(ids[0].InventoryName) - msg0 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) + var updatedDisconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""} + writerMock.On("UpdateNodebInfo", updatedDisconnectedFirstRan).Return(rnibErr) - rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg0, fmt.Errorf("RMR Error")) + //Second RAN + var secondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"} + readerMock.On("GetNodeb", test2).Return(secondRan, rnibErr) e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) - e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, "test1", "test2", "test3") - e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) + readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil) + writerMock.On("SaveE2TInstance", mock.Anything).Return(nil) + + respBody := ioutil.NopCloser(bytes.NewBufferString("")) + url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix + httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil) + notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} handler.Handle(notificationRequest) - //test1 (before send +1, after failure +1), test2 (0) test3 (0) writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) - //test1 failure (+1), test2 (0). test3 (0) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) + writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1) + httpClientMock.AssertNumberOfCalls(t, "Post", 1) } -func TestE2TermInitHandlerSuccessThreeRansSecondNotFoundFailure(t *testing.T) { - log, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) +func TestE2TermInitHandlerSuccessTwoRansFirstNotFoundFailure(t *testing.T) { + _, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t) + var rnibErr error + test2 := "test2" - ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}} + //First RAN + var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} + readerMock.On("GetNodeb", RanName).Return(firstRan, common.NewResourceNotFoundError("not found")) - var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr) - readerMock.On("GetNodeb", ids[1].InventoryName).Return(initialNodeb1, common.NewResourceNotFoundError("not found")) - readerMock.On("GetNodeb", ids[2].InventoryName).Return(initialNodeb2, rnibErr) + //Second RAN + var secondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"} + var disconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"} + readerMock.On("GetNodeb", test2).Return(secondRan, rnibErr).Return(disconnectedSecondRan, rnibErr) - var argNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - var argNodeb0Success = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb0).Return(rnibErr) - writerMock.On("UpdateNodebInfo", argNodeb0Success).Return(rnibErr) + var updatedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"} + writerMock.On("UpdateNodebInfo", updatedSecondRan).Return(rnibErr) - var argNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - var argNodeb2Success = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb2).Return(rnibErr) - writerMock.On("UpdateNodebInfo", argNodeb2Success).Return(rnibErr) + var updatedDisconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: ""} + writerMock.On("UpdateNodebInfo", updatedDisconnectedSecondRan).Return(rnibErr) - payload := models.NewE2RequestMessage(ids[0].InventoryName /*tid*/, "", 0, ids[0].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) - xaction := []byte(ids[0].InventoryName) - msg0 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) + e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2) + readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil) + writerMock.On("SaveE2TInstance", mock.Anything).Return(nil) - rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg0, nil) + respBody := ioutil.NopCloser(bytes.NewBufferString("")) + url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix + httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil) - e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) - e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, "test1", "test2", "test3") - e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} handler.Handle(notificationRequest) - readerMock.AssertNumberOfCalls(t, "GetNodeb", 3) - //test1 (+1), test2 failure (0) test3 (+1) writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) - //test1 success (+1), test2 (0). test3 (+1) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2) + writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1) + httpClientMock.AssertNumberOfCalls(t, "Post", 1) } -func TestE2TermInitHandlerSuccessThreeRansSecondRnibInternalErrorFailure(t *testing.T) { - log, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) - var rnibErr error - - ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}} - - var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr) - readerMock.On("GetNodeb", ids[1].InventoryName).Return(initialNodeb1, common.NewInternalError(fmt.Errorf("internal error"))) - readerMock.On("GetNodeb", ids[2].InventoryName).Return(initialNodeb2, rnibErr) - - var argNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - var argNodeb0Success = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb0).Return(rnibErr) - writerMock.On("UpdateNodebInfo", argNodeb0Success).Return(rnibErr) +func TestE2TermInitHandlerSuccessTwoRansFirstRnibInternalErrorFailure(t *testing.T) { + _, _, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t) - var argNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - var argNodeb2Success = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb2).Return(rnibErr) - writerMock.On("UpdateNodebInfo", argNodeb2Success).Return(rnibErr) + test2 := "test2" - payload := models.NewE2RequestMessage(ids[0].InventoryName /*tid*/, "", 0, ids[0].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) - xaction := []byte(ids[0].InventoryName) - msg0 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) - - rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg0, nil) + //First RAN + var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"} + readerMock.On("GetNodeb", RanName).Return(firstRan, common.NewInternalError(fmt.Errorf("internal error"))) e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) - e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, "test1", "test2", "test3") - e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2) + readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil) + notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} handler.Handle(notificationRequest) - readerMock.AssertNumberOfCalls(t, "GetNodeb", 2) - //test1 (+1), test2 failure (0) test3 (0) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) - //test1 success (+1), test2 (0). test3 (+1) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0) + writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 0) + httpClientMock.AssertNumberOfCalls(t, "Post", 0) } func TestE2TermInitHandlerSuccessZeroRans(t *testing.T) { - _, handler, _, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) + _, handler, _, writerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) @@ -521,11 +440,10 @@ func TestE2TermInitHandlerSuccessZeroRans(t *testing.T) { handler.Handle(notificationRequest) writerMock.AssertNotCalled(t, "UpdateNodebInfo") - rmrMessengerMock.AssertNotCalled(t, "SendMsg") } func TestE2TermInitHandlerFailureGetNodebInternalError(t *testing.T) { - _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) + _, handler, readerMock, writerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) var nodebInfo *entities.NodebInfo readerMock.On("GetNodeb", "test1").Return(nodebInfo, common.NewInternalError(fmt.Errorf("internal error"))) @@ -537,38 +455,8 @@ func TestE2TermInitHandlerFailureGetNodebInternalError(t *testing.T) { handler.Handle(notificationRequest) writerMock.AssertNotCalled(t, "UpdateNodebInfo") - rmrMessengerMock.AssertNotCalled(t, "SendMsg") } -func TestE2TermInitHandlerSuccessTwoRansSecondIsDisconnected(t *testing.T) { - _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t) - var rnibErr error - var initialNodeb0 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb1 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", RanName).Return(initialNodeb0, rnibErr) - readerMock.On("GetNodeb", "test2").Return(initialNodeb1, rnibErr) - - var argNodeb1 = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb1).Return(rnibErr) - - payload := e2pdus.PackedX2setupRequest - xaction := []byte(RanName) - msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction) - - rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil) - - e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) - e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName, "test2") - e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) - notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} - - handler.Handle(notificationRequest) - - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2) -} - - // TODO: extract to test_utils func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender { rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock) diff --git a/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler.go b/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler.go index 6c3569f..12d4df1 100644 --- a/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler.go +++ b/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler.go @@ -27,14 +27,14 @@ import ( ) type RanLostConnectionHandler struct { - ranReconnectionManager managers.IRanReconnectionManager - logger *logger.Logger + ranDisconnectionManager managers.IRanDisconnectionManager + logger *logger.Logger } -func NewRanLostConnectionHandler(logger *logger.Logger, ranReconnectionManager managers.IRanReconnectionManager) RanLostConnectionHandler { +func NewRanLostConnectionHandler(logger *logger.Logger, ranDisconnectionManager managers.IRanDisconnectionManager) RanLostConnectionHandler { return RanLostConnectionHandler{ - logger: logger, - ranReconnectionManager: ranReconnectionManager, + logger: logger, + ranDisconnectionManager: ranDisconnectionManager, } } func (h RanLostConnectionHandler) Handle(request *models.NotificationRequest) { @@ -43,5 +43,5 @@ func (h RanLostConnectionHandler) Handle(request *models.NotificationRequest) { h.logger.Warnf("#RanLostConnectionHandler.Handle - RAN name: %s - Received lost connection notification", ranName) - _ = h.ranReconnectionManager.ReconnectRan(ranName) + _ = h.ranDisconnectionManager.DisconnectRan(ranName) } diff --git a/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go b/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go index 836c02a..a1043a7 100644 --- a/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go +++ b/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go @@ -42,42 +42,39 @@ func TestLostConnectionHandlerSuccess(t *testing.T) { logger, _ := logger.InitLogger(logger.InfoLevel) notificationRequest := models.NotificationRequest{RanName: ranName} - ranReconnectionManagerMock := &mocks.RanReconnectionManagerMock{} - ranReconnectionManagerMock.On("ReconnectRan", ranName).Return(nil) - handler := NewRanLostConnectionHandler(logger, ranReconnectionManagerMock) + ranDisconnectionManagerMock := &mocks.RanDisconnectionManagerMock{} + ranDisconnectionManagerMock.On("DisconnectRan", ranName).Return(nil) + handler := NewRanLostConnectionHandler(logger, ranDisconnectionManagerMock) handler.Handle(¬ificationRequest) - ranReconnectionManagerMock.AssertCalled(t, "ReconnectRan", ranName) + ranDisconnectionManagerMock.AssertCalled(t, "DisconnectRan", ranName) } func TestLostConnectionHandlerFailure(t *testing.T) { logger, _ := logger.InitLogger(logger.InfoLevel) notificationRequest := models.NotificationRequest{RanName: ranName} - ranReconnectionManagerMock := &mocks.RanReconnectionManagerMock{} - ranReconnectionManagerMock.On("ReconnectRan", ranName).Return(errors.New("error")) - handler := NewRanLostConnectionHandler(logger, ranReconnectionManagerMock) + ranDisconnectionManagerMock := &mocks.RanDisconnectionManagerMock{} + ranDisconnectionManagerMock.On("DisconnectRan", ranName).Return(errors.New("error")) + handler := NewRanLostConnectionHandler(logger, ranDisconnectionManagerMock) handler.Handle(¬ificationRequest) - ranReconnectionManagerMock.AssertCalled(t, "ReconnectRan", ranName) + ranDisconnectionManagerMock.AssertCalled(t, "DisconnectRan", ranName) } -func setupLostConnectionHandlerTestWithRealReconnectionManager(t *testing.T, isSuccessfulHttpPost bool) (RanLostConnectionHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) { +func setupLostConnectionHandlerTestWithRealDisconnectionManager(t *testing.T, isSuccessfulHttpPost bool) (RanLostConnectionHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) { logger, _ := logger.InitLogger(logger.InfoLevel) config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3} - rmrMessengerMock := &mocks.RmrMessengerMock{} - rmrSender := initRmrSender(rmrMessengerMock, logger) readerMock := &mocks.RnibReaderMock{} writerMock := &mocks.RnibWriterMock{} rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock) e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger) - ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService) httpClientMock := &mocks.HttpClientMock{} routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClientMock) e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient) - ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tAssociationManager) - handler := NewRanLostConnectionHandler(logger, ranReconnectionManager) + ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager) + handler := NewRanLostConnectionHandler(logger, ranDisconnectionManager) - origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: e2tAddress} + origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, AssociatedE2TInstanceAddress: e2tAddress} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) updatedNodebInfo1 := *origNodebInfo @@ -87,10 +84,10 @@ func setupLostConnectionHandlerTestWithRealReconnectionManager(t *testing.T, isS updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED updatedNodebInfo2.AssociatedE2TInstanceAddress = "" writerMock.On("UpdateNodebInfo", &updatedNodebInfo2).Return(rnibErr) - e2tInstance := &entities.E2TInstance{Address: e2tAddress, AssociatedRanList:[]string{ranName}} + e2tInstance := &entities.E2TInstance{Address: e2tAddress, AssociatedRanList: []string{ranName}} readerMock.On("GetE2TInstance", e2tAddress).Return(e2tInstance, nil) e2tInstanceToSave := *e2tInstance - e2tInstanceToSave .AssociatedRanList = []string{} + e2tInstanceToSave.AssociatedRanList = []string{} writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil) mockHttpClient(httpClientMock, isSuccessfulHttpPost) @@ -111,8 +108,8 @@ func mockHttpClient(httpClientMock *mocks.HttpClientMock, isSuccessful bool) { httpClientMock.On("Post", clients.DissociateRanE2TInstanceApiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil) } -func TestLostConnectionHandlerFailureWithRealReconnectionManager(t *testing.T) { - handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTestWithRealReconnectionManager(t, false) +func TestLostConnectionHandlerFailureWithRealDisconnectionManager(t *testing.T) { + handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTestWithRealDisconnectionManager(t, false) notificationRequest := models.NotificationRequest{RanName: ranName} handler.Handle(¬ificationRequest) @@ -123,8 +120,8 @@ func TestLostConnectionHandlerFailureWithRealReconnectionManager(t *testing.T) { writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) } -func TestLostConnectionHandlerSuccessWithRealReconnectionManager(t *testing.T) { - handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTestWithRealReconnectionManager(t, true) +func TestLostConnectionHandlerSuccessWithRealDisconnectionManager(t *testing.T) { + handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTestWithRealDisconnectionManager(t, true) notificationRequest := models.NotificationRequest{RanName: ranName} handler.Handle(¬ificationRequest) diff --git a/E2Manager/managers/e2t_association_manager.go b/E2Manager/managers/e2t_association_manager.go index 1b105b0..822c01a 100644 --- a/E2Manager/managers/e2t_association_manager.go +++ b/E2Manager/managers/e2t_association_manager.go @@ -101,14 +101,13 @@ func (m *E2TAssociationManager) DissociateRan(e2tAddress string, ranName string) return nil } -func (m *E2TAssociationManager) RemoveE2tInstance(e2tInstance *entities.E2TInstance, ransToBeDissociated []string, ranAssociationList map[string][]string) error { - m.logger.Infof("#E2TAssociationManager.RemoveE2tInstance - Removing E2T %s and re-associating its associated RANs.", e2tInstance.Address) +func (m *E2TAssociationManager) RemoveE2tInstance(e2tInstance *entities.E2TInstance) error { + m.logger.Infof("#E2TAssociationManager.RemoveE2tInstance - Removing E2T %s and dessociating its associated RANs.", e2tInstance.Address) - err := m.rmClient.DeleteE2TInstance(e2tInstance.Address, ransToBeDissociated, ranAssociationList) + err := m.rmClient.DeleteE2TInstance(e2tInstance.Address, e2tInstance.AssociatedRanList) if err != nil { - _ = m.setStateToRoutingManagerFailure(e2tInstance) - m.logger.Errorf("#E2TAssociationManager.RemoveE2tInstance - RoutingManager failure: Failed to delete E2T %s. Error: %s", e2tInstance.Address, err) - return err + m.logger.Warnf("#E2TAssociationManager.RemoveE2tInstance - RoutingManager failure: Failed to delete E2T %s. Error: %s", e2tInstance.Address, err) + // log and continue } err = m.e2tInstanceManager.RemoveE2TInstance(e2tInstance.Address) @@ -117,23 +116,6 @@ func (m *E2TAssociationManager) RemoveE2tInstance(e2tInstance *entities.E2TInsta return err } - for e2tAddress, associatedRans := range ranAssociationList { - err = m.e2tInstanceManager.AddRansToInstance(e2tAddress, associatedRans) - if err != nil { - m.logger.Errorf("#E2TAssociationManager.RemoveE2tInstance - Failed to add RANs %s to E2T %s. Error: %s", associatedRans, e2tAddress, err) - return err - } - } - m.logger.Infof("#E2TAssociationManager.RemoveE2tInstance - E2T %s successfully removed.", e2tInstance.Address) return nil } - -func (m *E2TAssociationManager) setStateToRoutingManagerFailure(e2tInstance *entities.E2TInstance) error { - - err := m.e2tInstanceManager.SetE2tInstanceState(e2tInstance.Address, e2tInstance.State, entities.RoutingManagerFailure) - if err != nil { - return err - } - return nil -} diff --git a/E2Manager/managers/e2t_association_manager_test.go b/E2Manager/managers/e2t_association_manager_test.go index 3f31f6b..73be905 100644 --- a/E2Manager/managers/e2t_association_manager_test.go +++ b/E2Manager/managers/e2t_association_manager_test.go @@ -31,7 +31,6 @@ import ( "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/mock" "io/ioutil" "net/http" "testing" @@ -285,43 +284,6 @@ func TestDissociateRanRoutingManagerError(t *testing.T) { httpClientMock.AssertExpectations(t) } -func TestRemoveE2tInstanceSuccess(t *testing.T) { - manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress2, RanName), models.NewRoutingManagerE2TData(E2TAddress3, "test1")} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, e2tDataList) - mockHttpClientDelete(httpClientMock, data, true) - - writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) - e2tAddresses := []string{E2TAddress, E2TAddress2, E2TAddress3} - readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) - e2tAddressesNew := []string{E2TAddress2, E2TAddress3} - writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil) - - e2tInstance1 := &entities.E2TInstance{Address: E2TAddress} - e2tInstance2 := &entities.E2TInstance{Address: E2TAddress2} - readerMock.On("GetE2TInstance", E2TAddress2).Return(e2tInstance2, nil) - e2tInstance3 := &entities.E2TInstance{Address: E2TAddress3} - readerMock.On("GetE2TInstance", E2TAddress3).Return(e2tInstance3, nil) - - e2tInstance2updated := *e2tInstance2 - e2tInstance2updated.AssociatedRanList = []string{RanName} - writerMock.On("SaveE2TInstance", &e2tInstance2updated).Return(nil) - e2tInstance3updated := *e2tInstance3 - e2tInstance3updated.AssociatedRanList = []string{"test1"} - writerMock.On("SaveE2TInstance", &e2tInstance3updated).Return(nil) - - ranNamesToBeAssociated := make(map[string][]string) - ranNamesToBeAssociated[E2TAddress2] = []string{RanName} - ranNamesToBeAssociated[E2TAddress3] = []string{"test1"} - err := manager.RemoveE2tInstance(e2tInstance1, nil, ranNamesToBeAssociated) - - assert.Nil(t, err) - readerMock.AssertExpectations(t) - writerMock.AssertExpectations(t) - httpClientMock.AssertExpectations(t) -} - func TestRemoveE2tInstanceSuccessWithOrphans(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) @@ -335,8 +297,8 @@ func TestRemoveE2tInstanceSuccessWithOrphans(t *testing.T) { e2tAddressesNew := []string{} writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil) - e2tInstance1 := &entities.E2TInstance{Address: E2TAddress} - err := manager.RemoveE2tInstance(e2tInstance1, ranNamesToBeDissociated, nil) + e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:ranNamesToBeDissociated} + err := manager.RemoveE2tInstance(e2tInstance1) assert.Nil(t, err) readerMock.AssertExpectations(t) @@ -347,63 +309,20 @@ func TestRemoveE2tInstanceSuccessWithOrphans(t *testing.T) { func TestRemoveE2tInstanceFailureRoutingManager(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, e2tDataList) + data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil) mockHttpClientDelete(httpClientMock, data, false) - e2tInstance1 := entities.NewE2TInstance(E2TAddress) - e2tInstance1.State = entities.Active - readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil) - e2tInstance2 := *e2tInstance1 - e2tInstance2.State = entities.RoutingManagerFailure - writerMock.On("SaveE2TInstance", &e2tInstance2).Return(nil) - ranNamesToBeAssociated := make(map[string][]string) - ranNamesToBeAssociated[E2TAddress] = []string{"test"} - err := manager.RemoveE2tInstance(e2tInstance1, []string{"test1"}, ranNamesToBeAssociated) - - assert.NotNil(t, err) - readerMock.AssertExpectations(t) - writerMock.AssertExpectations(t) - httpClientMock.AssertExpectations(t) -} - -func TestRemoveE2tInstanceFailureRoutingManagerAndGetInstance(t *testing.T) { - manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, e2tDataList) - mockHttpClientDelete(httpClientMock, data, false) - - e2tInstance1 := &entities.E2TInstance{Address: E2TAddress} - readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewRnibDbError()) - ranNamesToBeAssociated := make(map[string][]string) - ranNamesToBeAssociated[E2TAddress] = []string{"test"} - err := manager.RemoveE2tInstance(e2tInstance1, []string{"test1"}, ranNamesToBeAssociated) - - assert.NotNil(t, err) - readerMock.AssertExpectations(t) - writerMock.AssertExpectations(t) - httpClientMock.AssertExpectations(t) -} - -func TestRemoveE2tInstanceFailureRoutingManagerAndSetInstanceState(t *testing.T) { - manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, e2tDataList) - mockHttpClientDelete(httpClientMock, data, false) + writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) + e2tAddresses := []string{E2TAddress} + readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + e2tAddressesNew := []string{} + writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil) - e2tInstance1 := entities.NewE2TInstance(E2TAddress) - e2tInstance1.State = entities.Active - readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil) - e2tInstance2 := *e2tInstance1 - e2tInstance2.State = entities.RoutingManagerFailure - writerMock.On("SaveE2TInstance", &e2tInstance2).Return(e2managererrors.NewRnibDbError()) - ranNamesToBeAssociated := make(map[string][]string) - ranNamesToBeAssociated[E2TAddress] = []string{"test"} - err := manager.RemoveE2tInstance(e2tInstance1, []string{"test1"}, ranNamesToBeAssociated) + e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:[]string{"test1"}} + //readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewRnibDbError()) + err := manager.RemoveE2tInstance(e2tInstance1) - assert.NotNil(t, err) + assert.Nil(t, err) readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) @@ -411,8 +330,7 @@ func TestRemoveE2tInstanceFailureRoutingManagerAndSetInstanceState(t *testing.T) func TestRemoveE2tInstanceFailureInE2TInstanceManager(t *testing.T) { - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, e2tDataList) + data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil) manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) mockHttpClientDelete(httpClientMock, data, true) @@ -420,10 +338,8 @@ func TestRemoveE2tInstanceFailureInE2TInstanceManager(t *testing.T) { var e2tAddresses []string readerMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError()) - ranNamesToBeAssociated := make(map[string][]string) - ranNamesToBeAssociated[E2TAddress] = []string{"test"} - e2tInstance1 := &entities.E2TInstance{Address: E2TAddress} - err := manager.RemoveE2tInstance(e2tInstance1, []string{"test1"}, ranNamesToBeAssociated) + e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:[]string{"test1"}} + err := manager.RemoveE2tInstance(e2tInstance1) assert.NotNil(t, err) readerMock.AssertExpectations(t) @@ -434,8 +350,7 @@ func TestRemoveE2tInstanceFailureInE2TInstanceManager(t *testing.T) { func TestRemoveE2tInstanceFailureInE2tInstanceAddRansToInstance(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress2, RanName), models.NewRoutingManagerE2TData(E2TAddress3, "test1")} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, e2tDataList) + data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, nil) mockHttpClientDelete(httpClientMock, data, true) writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) @@ -444,17 +359,10 @@ func TestRemoveE2tInstanceFailureInE2tInstanceAddRansToInstance(t *testing.T) { e2tAddressesNew := []string{E2TAddress2, E2TAddress3} writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil) - var e2tInstance2 *entities.E2TInstance - readerMock.On("GetE2TInstance", mock.Anything).Return(e2tInstance2, e2managererrors.NewRnibDbError()) - - ranNamesToBeAssociated := make(map[string][]string) - ranNamesToBeAssociated[E2TAddress2] = []string{RanName} - ranNamesToBeAssociated[E2TAddress3] = []string{"test1"} - e2tInstance1 := &entities.E2TInstance{Address: E2TAddress} - err := manager.RemoveE2tInstance(e2tInstance1, nil, ranNamesToBeAssociated) + err := manager.RemoveE2tInstance(e2tInstance1) - assert.NotNil(t, err) + assert.Nil(t, err) readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) diff --git a/E2Manager/managers/e2t_instances_manager.go b/E2Manager/managers/e2t_instances_manager.go index d4cc3d8..f8def48 100644 --- a/E2Manager/managers/e2t_instances_manager.go +++ b/E2Manager/managers/e2t_instances_manager.go @@ -371,7 +371,7 @@ func (m *E2TInstancesManager) ResetKeepAliveTimestamp(e2tAddress string) error { return err } - if e2tInstance.State == entities.ToBeDeleted || e2tInstance.State == entities.RoutingManagerFailure { + if e2tInstance.State == entities.ToBeDeleted { m.logger.Warnf("#E2TInstancesManager.ResetKeepAliveTimestamp - Ignore. This Instance is about to be deleted") return nil diff --git a/E2Manager/managers/e2t_instances_manager_test.go b/E2Manager/managers/e2t_instances_manager_test.go index 41fea42..2674349 100644 --- a/E2Manager/managers/e2t_instances_manager_test.go +++ b/E2Manager/managers/e2t_instances_manager_test.go @@ -300,12 +300,12 @@ func TestActivateE2TInstanceSuccess(t *testing.T) { rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) - e2tInstance1.State = entities.RoutingManagerFailure + e2tInstance1.State = entities.ToBeDeleted e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"} rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil) rnibWriterMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.State == entities.Active })).Return(nil) - err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.RoutingManagerFailure, entities.Active) + err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.ToBeDeleted, entities.Active) assert.Nil(t, err) assert.Equal(t, entities.Active, e2tInstance1.State) rnibWriterMock.AssertExpectations(t) @@ -317,7 +317,7 @@ func TestActivateE2TInstance_RnibError(t *testing.T) { var e2tInstance1 *entities.E2TInstance rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, common.NewInternalError(errors.New("for test"))) - err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.RoutingManagerFailure, entities.Active) + err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.ToBeDeleted, entities.Active) assert.NotNil(t, err) rnibWriterMock.AssertExpectations(t) } @@ -328,7 +328,7 @@ func TestActivateE2TInstance_NoInstance(t *testing.T) { var e2tInstance1 *entities.E2TInstance rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewResourceNotFoundError()) - err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.RoutingManagerFailure, entities.Active) + err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.ToBeDeleted, entities.Active) assert.NotNil(t, err) rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance") @@ -387,20 +387,6 @@ func TestResetKeepAliveTimestampToBeDeleted(t *testing.T) { rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance") } -func TestResetKeepAliveTimestampRoutingManagerFailure(t *testing.T) { - rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) - - address := "10.10.2.15:9800" - e2tInstance := entities.NewE2TInstance(address) - e2tInstance.State = entities.RoutingManagerFailure - rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil) - - err := e2tInstancesManager.ResetKeepAliveTimestamp(address) - assert.Nil(t, err) - rnibReaderMock.AssertCalled(t, "GetE2TInstance", address) - rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance") -} - func TestResetKeepAliveTimestampsForAllE2TInstancesGetE2TInstancesFailure(t *testing.T) { rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) rnibReaderMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("Error"))) @@ -422,7 +408,7 @@ func TestResetKeepAliveTimestampsForAllE2TInstancesNoActiveInstances(t *testing. e2tInstance1 := entities.NewE2TInstance(E2TAddress) e2tInstance1.State = entities.ToBeDeleted e2tInstance2 := entities.NewE2TInstance(E2TAddress2) - e2tInstance2.State = entities.RoutingManagerFailure + e2tInstance2.State = entities.ToBeDeleted rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil) e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances() rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance") @@ -508,3 +494,59 @@ func TestRemoveE2TInstanceRnibErrorInSaveAddresses(t *testing.T) { rnibReaderMock.AssertExpectations(t) rnibWriterMock.AssertExpectations(t) } + +func TestSetE2tInstanceStateCurrentStateHasChanged(t *testing.T) { + rnibReaderMock, _, e2tInstancesManager := initE2TInstancesManagerTest(t) + + e2tInstance := entities.NewE2TInstance(E2TAddress) + e2tInstance.State = entities.Active + + rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil) + + err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.ToBeDeleted, entities.Active) + assert.NotNil(t, err) + assert.IsType(t, e2managererrors.NewInternalError(), err) + rnibReaderMock.AssertExpectations(t) +} + +func TestSetE2tInstanceStateErrorInSaveE2TInstance(t *testing.T) { + rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) + + e2tInstance := entities.NewE2TInstance(E2TAddress) + e2tInstance.State = entities.ToBeDeleted + rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil) + rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(fmt.Errorf("for testing"))) + + err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.ToBeDeleted, entities.Active) + assert.NotNil(t, err) + assert.IsType(t, &common.InternalError{}, err) + rnibReaderMock.AssertExpectations(t) +} + +func TestClearRansOfAllE2TInstancesEmptyList(t *testing.T) { + rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) + E2TAddresses := []string{} + rnibReaderMock.On("GetE2TAddresses").Return(E2TAddresses, nil) + err := e2tInstancesManager.ClearRansOfAllE2TInstances() + assert.Nil(t, err) + rnibReaderMock.AssertExpectations(t) + rnibWriterMock.AssertExpectations(t) +} + +func TestClearRansOfAllE2TInstancesErrorInSaveE2TInstance(t *testing.T) { + rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) + addresses := []string{E2TAddress, E2TAddress2} + e2tInstance1 := entities.NewE2TInstance(E2TAddress) + e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test3"} + e2tInstance2 := entities.NewE2TInstance(E2TAddress2) + e2tInstance2.AssociatedRanList = []string{"test4", "test5", "test6", "test7"} + + rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil) + rnibReaderMock.On("GetE2TInstances", addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil) + rnibWriterMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress})).Return(common.NewInternalError(fmt.Errorf("for testing"))) + rnibWriterMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress2})).Return(nil) + err := e2tInstancesManager.ClearRansOfAllE2TInstances() + assert.Nil(t, err) + rnibReaderMock.AssertExpectations(t) + rnibWriterMock.AssertExpectations(t) +} diff --git a/E2Manager/managers/e2t_shutdown_manager.go b/E2Manager/managers/e2t_shutdown_manager.go index dd71ad4..2bb5d0f 100644 --- a/E2Manager/managers/e2t_shutdown_manager.go +++ b/E2Manager/managers/e2t_shutdown_manager.go @@ -39,17 +39,15 @@ type E2TShutdownManager struct { rnibDataService services.RNibDataService e2TInstancesManager IE2TInstancesManager e2tAssociationManager *E2TAssociationManager - ranSetupManager IRanSetupManager } -func NewE2TShutdownManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, e2TInstancesManager IE2TInstancesManager, e2tAssociationManager *E2TAssociationManager, ranSetupManager IRanSetupManager) *E2TShutdownManager { +func NewE2TShutdownManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, e2TInstancesManager IE2TInstancesManager, e2tAssociationManager *E2TAssociationManager) *E2TShutdownManager { return &E2TShutdownManager{ logger: logger, config: config, rnibDataService: rnibDataService, e2TInstancesManager: e2TInstancesManager, e2tAssociationManager: e2tAssociationManager, - ranSetupManager: ranSetupManager, } } @@ -68,58 +66,25 @@ func (m E2TShutdownManager) Shutdown(e2tInstance *entities.E2TInstance) error { return err } - ranNamesToBeDissociated := []string{} - ranNamesToBeAssociated := make(map[string][]string) // e2tAddress -> associatedRanList - - for _, ranName := range e2tInstance.AssociatedRanList { - ranNamesToBeDissociated, err = m.reAssociateRanInMemory(ranName, ranNamesToBeAssociated, ranNamesToBeDissociated) - if err != nil { - m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to re-associate nodeb %s.", ranName) - return err - } - } - - err = m.e2tAssociationManager.RemoveE2tInstance(e2tInstance, ranNamesToBeDissociated, ranNamesToBeAssociated) - if err != nil { - m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to remove E2T %s.", e2tInstance.Address) - return err - } - - err = m.clearNodebsAssociation(ranNamesToBeDissociated) + err = m.clearNodebsAssociation(e2tInstance.AssociatedRanList) if err != nil { m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to clear nodebs association to E2T %s.", e2tInstance.Address) return err } - err = m.reassociateNodebs(ranNamesToBeAssociated) + err = m.e2tAssociationManager.RemoveE2tInstance(e2tInstance) if err != nil { - m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to re-associate nodebs after killing E2T %s.", e2tInstance.Address) + m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to remove E2T %s.", e2tInstance.Address) return err } - m.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s was sutdown successfully.", e2tInstance.Address) - return nil -} - -func (m E2TShutdownManager) reassociateNodebs(ranNamesToBeAssociated map[string][]string) error { - for e2tAddress, ranNames := range ranNamesToBeAssociated { - - err := m.associateAndSetupNodebs(ranNames, e2tAddress) - if err != nil { - return err - } - } + m.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s was shutdown successfully.", e2tInstance.Address) return nil } func (m E2TShutdownManager) clearNodebsAssociation(ranNamesToBeDissociated []string) error { - return m.associateAndSetupNodebs(ranNamesToBeDissociated, "") -} - -func (m E2TShutdownManager) associateAndSetupNodebs(ranNamesToBeUpdated []string, e2tAddress string) error { - isDissociatedRans := len(e2tAddress) == 0 - for _, ranName := range ranNamesToBeUpdated { + for _, ranName := range ranNamesToBeDissociated { nodeb, err := m.rnibDataService.GetNodeb(ranName) if err != nil { m.logger.Warnf("#E2TShutdownManager.associateAndSetupNodebs - Failed to get nodeb %s from db.", ranName) @@ -129,59 +94,18 @@ func (m E2TShutdownManager) associateAndSetupNodebs(ranNamesToBeUpdated []string } return err } - nodeb.AssociatedE2TInstanceAddress = e2tAddress - if isDissociatedRans{ - nodeb.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED - } + nodeb.AssociatedE2TInstanceAddress = "" + nodeb.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED err = m.rnibDataService.UpdateNodebInfo(nodeb) if err != nil { m.logger.Errorf("#E2TShutdownManager.associateAndSetupNodebs - Failed to save nodeb %s from db.", ranName) return err } - - if !isDissociatedRans { - err = m.ranSetupManager.ExecuteSetup(nodeb, entities.ConnectionStatus_CONNECTING) - if err != nil { - m.logger.Errorf("#E2TShutdownManager.associateAndSetupNodebs - Failed to execute Setup for nodeb %s.", ranName) - continue - } - } } return nil } -func (m E2TShutdownManager) reAssociateRanInMemory(ranName string, ranNamesToBeAssociated map[string][]string, ranNamesToBeDissociated []string) ([]string, error) { - nodeb, err := m.rnibDataService.GetNodeb(ranName) - if err != nil { - - _, ok := err.(*common.ResourceNotFoundError) - - if !ok { - m.logger.Errorf("#E2TShutdownManager.reAssociateRanInMemory - Failed to get nodeb %s from db.", ranName) - return ranNamesToBeDissociated, err - } - - m.logger.Errorf("#E2TShutdownManager.reAssociateRanInMemory - nodeb %s not found in db. Skipping it...", ranName) - return ranNamesToBeDissociated, nil - } - - if nodeb.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN || nodeb.ConnectionStatus == entities.ConnectionStatus_SHUT_DOWN { - m.logger.Errorf("#E2TShutdownManager.reAssociateRanInMemory - nodeb %s status is %s. Skipping it...", ranName, nodeb.ConnectionStatus) - return ranNamesToBeDissociated, nil - } - - selectedE2tAddress, err := m.e2TInstancesManager.SelectE2TInstance() - if err != nil { - m.logger.Infof("#E2TShutdownManager.reAssociateRanInMemory - No selected E2T instance for nodeb %s found.", ranName) - ranNamesToBeDissociated = append(ranNamesToBeDissociated, ranName) - return ranNamesToBeDissociated, nil - } - - ranNamesToBeAssociated[selectedE2tAddress] = append(ranNamesToBeAssociated[selectedE2tAddress], ranName) - return ranNamesToBeDissociated, nil -} - func (m E2TShutdownManager) markE2tInstanceToBeDeleted(e2tInstance *entities.E2TInstance) error { e2tInstance.State = entities.ToBeDeleted e2tInstance.DeletionTimestamp = time.Now().UnixNano() diff --git a/E2Manager/managers/e2t_shutdown_manager_test.go b/E2Manager/managers/e2t_shutdown_manager_test.go index cd69fcf..570cf62 100644 --- a/E2Manager/managers/e2t_shutdown_manager_test.go +++ b/E2Manager/managers/e2t_shutdown_manager_test.go @@ -25,10 +25,8 @@ import ( "e2mgr/clients" "e2mgr/configuration" "e2mgr/e2managererrors" - "e2mgr/e2pdus" "e2mgr/mocks" "e2mgr/models" - "e2mgr/rmrCgo" "e2mgr/services" "encoding/json" "fmt" @@ -44,7 +42,7 @@ import ( const E2TAddress3 = "10.10.2.17:9800" -func initE2TShutdownManagerTest(t *testing.T) (*E2TShutdownManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock, *mocks.RmrMessengerMock) { +func initE2TShutdownManagerTest(t *testing.T) (*E2TShutdownManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) { log := initLog(t) config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, E2TInstanceDeletionTimeoutMs: 15000} @@ -56,16 +54,14 @@ func initE2TShutdownManagerTest(t *testing.T) (*E2TShutdownManager, *mocks.RnibR httpClientMock := &mocks.HttpClientMock{} rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock) associationManager := NewE2TAssociationManager(log, rnibDataService, e2tInstancesManager, rmClient) - rmrMessengerMock := &mocks.RmrMessengerMock{} - rmrSender := initRmrSender(rmrMessengerMock, log) - ranSetupManager := NewRanSetupManager(log, rmrSender, rnibDataService) - shutdownManager := NewE2TShutdownManager(log, config, rnibDataService, e2tInstancesManager, associationManager, ranSetupManager) - return shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock + shutdownManager := NewE2TShutdownManager(log, config, rnibDataService, e2tInstancesManager, associationManager) + + return shutdownManager, readerMock, writerMock, httpClientMock } func TestShutdownSuccess1OutOf3Instances(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) + shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) e2tInstance1.State = entities.Active @@ -87,10 +83,8 @@ func TestShutdownSuccess1OutOf3Instances(t *testing.T) { e2tAddresses := []string{E2TAddress, E2TAddress2,E2TAddress3} readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) - readerMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance2,e2tInstance3}, nil) - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress2, "test1", "test5")} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, e2tDataList) + data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, e2tInstance1.AssociatedRanList, nil) marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) respBody := ioutil.NopCloser(bytes.NewBufferString("")) @@ -99,50 +93,29 @@ func TestShutdownSuccess1OutOf3Instances(t *testing.T) { writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) writerMock.On("SaveE2TAddresses", []string{E2TAddress2,E2TAddress3}).Return(nil) - readerMock.On("GetE2TInstance", E2TAddress2).Return(e2tInstance2, nil) - e2tInstance2updated := *e2tInstance2 - e2tInstance2updated.AssociatedRanList = append(e2tInstance2updated.AssociatedRanList, "test1", "test5") - writerMock.On("SaveE2TInstance", &e2tInstance2updated).Return(nil) - - nodeb1new := *nodeb1 - nodeb1new.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb1new.ConnectionStatus = entities.ConnectionStatus_CONNECTING - nodeb1new.ConnectionAttempts = 1 - writerMock.On("UpdateNodebInfo", &nodeb1new).Return(nil) - nodeb5new := *nodeb5 - nodeb5new.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb5new.ConnectionStatus = entities.ConnectionStatus_CONNECTING - nodeb5new.ConnectionAttempts = 1 - writerMock.On("UpdateNodebInfo", &nodeb5new).Return(nil) - nodeb1connected := *nodeb1 - nodeb1connected.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb1connected.ConnectionStatus = entities.ConnectionStatus_CONNECTED + nodeb1connected.AssociatedE2TInstanceAddress = "" + nodeb1connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED writerMock.On("UpdateNodebInfo", &nodeb1connected).Return(nil) + nodeb2connected := *nodeb2 + nodeb2connected.AssociatedE2TInstanceAddress = "" + nodeb2connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + writerMock.On("UpdateNodebInfo", &nodeb2connected).Return(nil) nodeb5connected := *nodeb5 - nodeb5connected.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb5connected.ConnectionStatus = entities.ConnectionStatus_CONNECTED + nodeb5connected.AssociatedE2TInstanceAddress = "" + nodeb5connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED writerMock.On("UpdateNodebInfo", &nodeb5connected).Return(nil) - payload := e2pdus.PackedX2setupRequest - xaction1 := []byte("test1") - msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), "test1", &payload, &xaction1) - rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg1, nil) - xaction5 := []byte("test5") - msg5 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), "test5", &payload, &xaction5) - rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg5, nil) - err := shutdownManager.Shutdown(e2tInstance1) assert.Nil(t, err) readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2) } func TestShutdownSuccess1InstanceWithoutRans(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) + shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) e2tInstance1.State = entities.Active @@ -165,11 +138,10 @@ func TestShutdownSuccess1InstanceWithoutRans(t *testing.T) { readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) } func TestShutdownSuccess1Instance2Rans(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) + shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) e2tInstance1.State = entities.Active @@ -187,10 +159,6 @@ func TestShutdownSuccess1Instance2Rans(t *testing.T) { respBody := ioutil.NopCloser(bytes.NewBufferString("")) httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil) - e2tInstance1updated := *e2tInstance1 - e2tInstance1updated.State = entities.ToBeDeleted - readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance1updated}, nil) - writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil) writerMock.On("SaveE2TAddresses", []string{}).Return(nil) @@ -210,13 +178,11 @@ func TestShutdownSuccess1Instance2Rans(t *testing.T) { readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) + } - - func TestShutdownE2tInstanceAlreadyBeingDeleted(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) + shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) e2tInstance1.State = entities.ToBeDeleted @@ -229,11 +195,11 @@ func TestShutdownE2tInstanceAlreadyBeingDeleted(t *testing.T) { readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) + } func TestShutdownFailureMarkInstanceAsToBeDeleted(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) + shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) e2tInstance1.State = entities.Active @@ -246,94 +212,11 @@ func TestShutdownFailureMarkInstanceAsToBeDeleted(t *testing.T) { readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) -} - -func TestShutdownFailureReassociatingInMemoryNodebNotFound(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) - - e2tInstance1 := entities.NewE2TInstance(E2TAddress) - e2tInstance1.State = entities.Active - e2tInstance1.AssociatedRanList = []string{"test1", "test2"} - e2tInstance2 := entities.NewE2TInstance(E2TAddress2) - e2tInstance2.State = entities.Active - e2tInstance2.AssociatedRanList = []string{"test3"} - writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil) - - var nodeb1 *entities.NodebInfo - readerMock.On("GetNodeb", "test1").Return(nodeb1, common.NewResourceNotFoundError("for tests")) - nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", "test2").Return(nodeb2, nil) - - e2tAddresses := []string{E2TAddress, E2TAddress2} - readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) - readerMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance2}, nil) - - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress2, "test2")} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, e2tDataList) - marshaled, _ := json.Marshal(data) - body := bytes.NewBuffer(marshaled) - respBody := ioutil.NopCloser(bytes.NewBufferString("")) - httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil) - - writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) - writerMock.On("SaveE2TAddresses", []string{E2TAddress2}).Return(nil) - - readerMock.On("GetE2TInstance", E2TAddress2).Return(e2tInstance2, nil) - e2tInstance2updated := *e2tInstance2 - e2tInstance2updated.AssociatedRanList = append(e2tInstance2updated.AssociatedRanList, "test2") - writerMock.On("SaveE2TInstance", &e2tInstance2updated).Return(nil) - - nodeb2new := *nodeb2 - nodeb2new.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb2new.ConnectionStatus = entities.ConnectionStatus_CONNECTING - nodeb2new.ConnectionAttempts = 1 - writerMock.On("UpdateNodebInfo", &nodeb2new).Return(nil) - - nodeb2connected := *nodeb2 - nodeb2connected.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb2connected.ConnectionStatus = entities.ConnectionStatus_CONNECTED - writerMock.On("UpdateNodebInfo", &nodeb2connected).Return(nil) - - payload := e2pdus.PackedX2setupRequest - xaction2 := []byte("test2") - msg2 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), "test2", &payload, &xaction2) - rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg2, nil) - - err := shutdownManager.Shutdown(e2tInstance1) - - assert.Nil(t, err) - readerMock.AssertExpectations(t) - writerMock.AssertExpectations(t) - httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) -} - -func TestShutdownFailureReassociatingInMemoryGetNodebError(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) - - e2tInstance1 := entities.NewE2TInstance(E2TAddress) - e2tInstance1.State = entities.Active - e2tInstance1.AssociatedRanList = []string{"test1", "test2"} - e2tInstance2 := entities.NewE2TInstance(E2TAddress2) - e2tInstance2.State = entities.Active - e2tInstance2.AssociatedRanList = []string{"test3"} - writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil) - - var nodeb1 *entities.NodebInfo - readerMock.On("GetNodeb", "test1").Return(nodeb1, common.NewInternalError(fmt.Errorf("for tests"))) - - err := shutdownManager.Shutdown(e2tInstance1) - - assert.NotNil(t, err) - readerMock.AssertExpectations(t) - writerMock.AssertExpectations(t) - httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) + } func TestShutdownFailureRoutingManagerError(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) + shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) e2tInstance1.State = entities.Active @@ -355,29 +238,40 @@ func TestShutdownFailureRoutingManagerError(t *testing.T) { e2tAddresses := []string{E2TAddress, E2TAddress2,E2TAddress3} readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) - readerMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance2,e2tInstance3}, nil) - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress2, "test1", "test5")} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, e2tDataList) + data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, e2tInstance1.AssociatedRanList, nil) marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) respBody := ioutil.NopCloser(bytes.NewBufferString("")) httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusBadRequest, Body: respBody}, nil) - readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil) - writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.RoutingManagerFailure })).Return(nil) + writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) + writerMock.On("SaveE2TAddresses", []string{E2TAddress2,E2TAddress3}).Return(nil) + + nodeb1connected := *nodeb1 + nodeb1connected.AssociatedE2TInstanceAddress = "" + nodeb1connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + writerMock.On("UpdateNodebInfo", &nodeb1connected).Return(nil) + nodeb2connected := *nodeb2 + nodeb2connected.AssociatedE2TInstanceAddress = "" + nodeb2connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + writerMock.On("UpdateNodebInfo", &nodeb2connected).Return(nil) + nodeb5connected := *nodeb5 + nodeb5connected.AssociatedE2TInstanceAddress = "" + nodeb5connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + writerMock.On("UpdateNodebInfo", &nodeb5connected).Return(nil) err := shutdownManager.Shutdown(e2tInstance1) - assert.NotNil(t, err) + assert.Nil(t, err) readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) + } func TestShutdownFailureInClearNodebsAssociation(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) + shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) e2tInstance1.State = entities.Active @@ -386,22 +280,6 @@ func TestShutdownFailureInClearNodebsAssociation(t *testing.T) { nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} readerMock.On("GetNodeb", "test1").Return(nodeb1, nil) - nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", "test2").Return(nodeb2, nil) - - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1", "test2"}, nil) - marshaled, _ := json.Marshal(data) - body := bytes.NewBuffer(marshaled) - respBody := ioutil.NopCloser(bytes.NewBufferString("")) - httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil) - - e2tInstance1updated := *e2tInstance1 - e2tInstance1updated.State = entities.ToBeDeleted - readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance1updated}, nil) - - writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) - readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil) - writerMock.On("SaveE2TAddresses", []string{}).Return(nil) nodeb1new := *nodeb1 nodeb1new.AssociatedE2TInstanceAddress = "" @@ -414,155 +292,76 @@ func TestShutdownFailureInClearNodebsAssociation(t *testing.T) { readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) } -func TestShutdownFailureInRmr(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) +func TestShutdownResourceNotFoundErrorInGetNodeb(t *testing.T) { + shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) e2tInstance1.State = entities.Active - e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"} - e2tInstance2 := entities.NewE2TInstance(E2TAddress2) - e2tInstance2.State = entities.Active - e2tInstance2.AssociatedRanList = []string{"test3"} - e2tInstance3 := entities.NewE2TInstance(E2TAddress3) - e2tInstance3.State = entities.Active - e2tInstance3.AssociatedRanList = []string{"test4"} + e2tInstance1.AssociatedRanList = []string{"test1", "test2"} writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil) nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} readerMock.On("GetNodeb", "test1").Return(nodeb1, nil) - nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", "test2").Return(nodeb2, nil) - nodeb5 := &entities.NodebInfo{RanName:"test5", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", "test5").Return(nodeb5, nil) - - e2tAddresses := []string{E2TAddress, E2TAddress2,E2TAddress3} - readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) - readerMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance2,e2tInstance3}, nil) - - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress2, "test1", "test5")} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, e2tDataList) - marshaled, _ := json.Marshal(data) - body := bytes.NewBuffer(marshaled) - respBody := ioutil.NopCloser(bytes.NewBufferString("")) - httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil) - - writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) - writerMock.On("SaveE2TAddresses", []string{E2TAddress2,E2TAddress3}).Return(nil) - - readerMock.On("GetE2TInstance", E2TAddress2).Return(e2tInstance2, nil) - e2tInstance2updated := *e2tInstance2 - e2tInstance2updated.AssociatedRanList = []string{"test3", "test1", "test5"} - writerMock.On("SaveE2TInstance", &e2tInstance2updated).Return(nil) - - nodeb1reassigned := *nodeb1 - nodeb1reassigned.AssociatedE2TInstanceAddress = E2TAddress2 - writerMock.On("UpdateNodebInfo", &nodeb1reassigned).Return(nil) - nodeb5reassigned := *nodeb5 - nodeb5reassigned.AssociatedE2TInstanceAddress = E2TAddress2 - writerMock.On("UpdateNodebInfo", &nodeb5reassigned).Return(nil) + var nodeb2 *entities.NodebInfo + readerMock.On("GetNodeb", "test2").Return(nodeb2, common.NewResourceNotFoundError("for testing")) nodeb1new := *nodeb1 - nodeb1new.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb1new.ConnectionStatus = entities.ConnectionStatus_CONNECTING - nodeb1new.ConnectionAttempts = 1 + nodeb1new.AssociatedE2TInstanceAddress = "" + nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED writerMock.On("UpdateNodebInfo", &nodeb1new).Return(nil) - nodeb5new := *nodeb5 - nodeb5new.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb5new.ConnectionStatus = entities.ConnectionStatus_CONNECTING - nodeb5new.ConnectionAttempts = 1 - writerMock.On("UpdateNodebInfo", &nodeb5new).Return(nil) - - nodeb1connected := *nodeb1 - nodeb1connected.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb1connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED - nodeb1connected.ConnectionAttempts = 0 - //nodeb1connected.E2ApplicationProtocol = entities.E2ApplicationProtocol_X2_SETUP_REQUEST - writerMock.On("UpdateNodebInfo", &nodeb1connected).Return(nil) - nodeb5connected := *nodeb5 - nodeb5connected.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb5connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED - nodeb5connected.ConnectionAttempts = 0 - //nodeb5connected.E2ApplicationProtocol = entities.E2ApplicationProtocol_X2_SETUP_REQUEST - writerMock.On("UpdateNodebInfo", &nodeb5connected).Return(nil) - - payload := e2pdus.PackedX2setupRequest - xaction1 := []byte("test1") - msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), "test1", &payload, &xaction1) - rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg1, common.NewInternalError(fmt.Errorf("for test"))) - xaction2 := []byte("test5") - msg2 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), "test5", &payload, &xaction2) - rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg2, common.NewInternalError(fmt.Errorf("for test"))) err := shutdownManager.Shutdown(e2tInstance1) - assert.Nil(t, err) + assert.NotNil(t, err) readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2) } -func TestShutdownFailureDbErrorInAsociateAndSetupNodebs(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) +func TestShutdownResourceGeneralErrorInGetNodeb(t *testing.T) { + shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) e2tInstance1.State = entities.Active - e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"} - e2tInstance2 := entities.NewE2TInstance(E2TAddress2) - e2tInstance2.State = entities.Active - e2tInstance2.AssociatedRanList = []string{"test3"} - e2tInstance3 := entities.NewE2TInstance(E2TAddress3) - e2tInstance3.State = entities.Active - e2tInstance3.AssociatedRanList = []string{"test4"} + e2tInstance1.AssociatedRanList = []string{"test1", "test2"} writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil) - nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", "test1").Return(nodeb1, nil) - nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} + var nodeb1 *entities.NodebInfo + readerMock.On("GetNodeb", "test1").Return(nodeb1, common.NewInternalError(fmt.Errorf("for testing"))) + nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} readerMock.On("GetNodeb", "test2").Return(nodeb2, nil) - nodeb5 := &entities.NodebInfo{RanName:"test5", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", "test5").Return(nodeb5, nil) - - e2tAddresses := []string{E2TAddress, E2TAddress2,E2TAddress3} - readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) - readerMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance2,e2tInstance3}, nil) - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress2, "test1", "test5")} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, e2tDataList) + data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1", "test2"}, nil) marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) respBody := ioutil.NopCloser(bytes.NewBufferString("")) httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil) writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) - writerMock.On("SaveE2TAddresses", []string{E2TAddress2,E2TAddress3}).Return(nil) - - readerMock.On("GetE2TInstance", E2TAddress2).Return(e2tInstance2, nil) - e2tInstance2updated := *e2tInstance2 - e2tInstance2updated.AssociatedRanList = []string{"test3", "test1", "test5"} - writerMock.On("SaveE2TInstance", &e2tInstance2updated).Return(nil) + readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil) + writerMock.On("SaveE2TAddresses", []string{}).Return(nil) - nodeb1reassigned := *nodeb1 - nodeb1reassigned.AssociatedE2TInstanceAddress = E2TAddress2 - writerMock.On("UpdateNodebInfo", &nodeb1reassigned).Return(common.NewInternalError(fmt.Errorf("for tests"))) + nodeb2new := *nodeb2 + nodeb2new.AssociatedE2TInstanceAddress = "" + nodeb2new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + writerMock.On("UpdateNodebInfo", &nodeb2new).Return(nil) err := shutdownManager.Shutdown(e2tInstance1) - assert.NotNil(t, err) + assert.Nil(t, err) readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) + } -func TestShutdownSuccess1OutOf3InstancesStateIsRoutingManagerFailure(t *testing.T) { - shutdownManager, readerMock, writerMock, httpClientMock, rmrMessengerMock := initE2TShutdownManagerTest(t) +func TestShutdownFailureInRemoveE2TInstance(t *testing.T) { + shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) - e2tInstance1.State = entities.RoutingManagerFailure + e2tInstance1.State = entities.Active e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"} e2tInstance2 := entities.NewE2TInstance(E2TAddress2) e2tInstance2.State = entities.Active @@ -579,60 +378,31 @@ func TestShutdownSuccess1OutOf3InstancesStateIsRoutingManagerFailure(t *testing. nodeb5 := &entities.NodebInfo{RanName:"test5", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} readerMock.On("GetNodeb", "test5").Return(nodeb5, nil) - e2tAddresses := []string{E2TAddress, E2TAddress2,E2TAddress3} - readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) - readerMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance2,e2tInstance3}, nil) - - e2tDataList := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress2, "test1", "test5")} - data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, e2tDataList) + data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, e2tInstance1.AssociatedRanList, nil) marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) respBody := ioutil.NopCloser(bytes.NewBufferString("")) httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil) - writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) - writerMock.On("SaveE2TAddresses", []string{E2TAddress2,E2TAddress3}).Return(nil) - - readerMock.On("GetE2TInstance", E2TAddress2).Return(e2tInstance2, nil) - e2tInstance2updated := *e2tInstance2 - e2tInstance2updated.AssociatedRanList = []string{"test3", "test1", "test5"} - writerMock.On("SaveE2TInstance", &e2tInstance2updated).Return(nil) - - nodeb1new := *nodeb1 - nodeb1new.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb1new.ConnectionStatus = entities.ConnectionStatus_CONNECTING - nodeb1new.ConnectionAttempts = 1 - writerMock.On("UpdateNodebInfo", &nodeb1new).Return(nil) - nodeb5new := *nodeb5 - nodeb5new.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb5new.ConnectionStatus = entities.ConnectionStatus_CONNECTING - nodeb5new.ConnectionAttempts = 1 - writerMock.On("UpdateNodebInfo", &nodeb5new).Return(nil) + writerMock.On("RemoveE2TInstance", E2TAddress).Return(common.NewInternalError(fmt.Errorf("for tests"))) nodeb1connected := *nodeb1 - nodeb1connected.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb1connected.ConnectionStatus = entities.ConnectionStatus_CONNECTED - //nodeb1connected.E2ApplicationProtocol = entities.E2ApplicationProtocol_X2_SETUP_REQUEST + nodeb1connected.AssociatedE2TInstanceAddress = "" + nodeb1connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED writerMock.On("UpdateNodebInfo", &nodeb1connected).Return(nil) + nodeb2connected := *nodeb2 + nodeb2connected.AssociatedE2TInstanceAddress = "" + nodeb2connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + writerMock.On("UpdateNodebInfo", &nodeb2connected).Return(nil) nodeb5connected := *nodeb5 - nodeb5connected.AssociatedE2TInstanceAddress = E2TAddress2 - nodeb5connected.ConnectionStatus = entities.ConnectionStatus_CONNECTED - //nodeb5connected.E2ApplicationProtocol = entities.E2ApplicationProtocol_X2_SETUP_REQUEST + nodeb5connected.AssociatedE2TInstanceAddress = "" + nodeb5connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED writerMock.On("UpdateNodebInfo", &nodeb5connected).Return(nil) - payload := e2pdus.PackedX2setupRequest - xaction1 := []byte("test1") - msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), "test1", &payload, &xaction1) - rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg1, nil) - xaction5 := []byte("test5") - msg5 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), "test5", &payload, &xaction5) - rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg5, nil) - err := shutdownManager.Shutdown(e2tInstance1) - assert.Nil(t, err) + assert.IsType(t, &e2managererrors.RnibDbError{}, err) readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2) } \ No newline at end of file diff --git a/E2Manager/managers/ran_disconnection_manager.go b/E2Manager/managers/ran_disconnection_manager.go new file mode 100644 index 0000000..c34e528 --- /dev/null +++ b/E2Manager/managers/ran_disconnection_manager.go @@ -0,0 +1,95 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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 managers + +import ( + "e2mgr/configuration" + "e2mgr/logger" + "e2mgr/services" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" +) + +type IRanDisconnectionManager interface { + DisconnectRan(inventoryName string) error +} + +type RanDisconnectionManager struct { + logger *logger.Logger + config *configuration.Configuration + rnibDataService services.RNibDataService + ranSetupManager *RanSetupManager + e2tAssociationManager *E2TAssociationManager +} + +func NewRanDisconnectionManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, e2tAssociationManager *E2TAssociationManager) *RanDisconnectionManager { + return &RanDisconnectionManager{ + logger: logger, + config: config, + rnibDataService: rnibDataService, + e2tAssociationManager: e2tAssociationManager, + } +} + +func (m *RanDisconnectionManager) DisconnectRan(inventoryName string) error { + nodebInfo, err := m.rnibDataService.GetNodeb(inventoryName) + + if err != nil { + m.logger.Errorf("#RanDisconnectionManager.DisconnectRan - RAN name: %s - Failed fetching RAN from rNib. Error: %v", inventoryName, err) + return err + } + + connectionStatus := nodebInfo.GetConnectionStatus() + m.logger.Infof("#RanDisconnectionManager.DisconnectRan - RAN name: %s - RAN's connection status: %s", nodebInfo.RanName, connectionStatus) + + + if connectionStatus == entities.ConnectionStatus_SHUT_DOWN { + m.logger.Warnf("#RanDisconnectionManager.DisconnectRan - RAN name: %s - quit. RAN's connection status is SHUT_DOWN", nodebInfo.RanName) + return nil + } + + nodebInfo.ConnectionAttempts = 0; + + if connectionStatus == entities.ConnectionStatus_SHUTTING_DOWN { + return m.updateNodebInfo(nodebInfo, entities.ConnectionStatus_SHUT_DOWN) + } + + err = m.updateNodebInfo(nodebInfo, entities.ConnectionStatus_DISCONNECTED) + + if err != nil { + return err + } + + e2tAddress := nodebInfo.AssociatedE2TInstanceAddress + return m.e2tAssociationManager.DissociateRan(e2tAddress, nodebInfo.RanName) +} + +func (m *RanDisconnectionManager) updateNodebInfo(nodebInfo *entities.NodebInfo, connectionStatus entities.ConnectionStatus) error { + + nodebInfo.ConnectionStatus = connectionStatus; + err := m.rnibDataService.UpdateNodebInfo(nodebInfo) + + if err != nil { + m.logger.Errorf("#RanDisconnectionManager.updateNodebInfo - RAN name: %s - Failed updating RAN's connection status to %s in rNib. Error: %v", nodebInfo.RanName, connectionStatus, err) + return err + } + + m.logger.Infof("#RanDisconnectionManager.updateNodebInfo - RAN name: %s - Successfully updated rNib. RAN's current connection status: %s", nodebInfo.RanName, nodebInfo.ConnectionStatus) + return nil +} diff --git a/E2Manager/managers/ran_reconnection_manager_test.go b/E2Manager/managers/ran_disconnection_manager_test.go similarity index 64% rename from E2Manager/managers/ran_reconnection_manager_test.go rename to E2Manager/managers/ran_disconnection_manager_test.go index 7927d0c..6ef0f54 100644 --- a/E2Manager/managers/ran_reconnection_manager_test.go +++ b/E2Manager/managers/ran_disconnection_manager_test.go @@ -17,7 +17,6 @@ // This source code is part of the near-RT RIC (RAN Intelligent Controller) // platform project (RICP). - package managers import ( @@ -33,14 +32,13 @@ import ( "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/mock" "testing" ) const ranName = "test" const e2tAddress = "10.10.2.15:9800" -func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessengerMock, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *RanReconnectionManager, *mocks.HttpClientMock) { +func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessengerMock, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *RanDisconnectionManager, *mocks.HttpClientMock) { logger, err := logger.InitLogger(logger.DebugLevel) if err != nil { t.Errorf("#... - failed to initialize logger, error: %s", err) @@ -48,47 +46,42 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessenge config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3} rmrMessengerMock := &mocks.RmrMessengerMock{} - rmrSender := initRmrSender(rmrMessengerMock, logger) - readerMock := &mocks.RnibReaderMock{} - writerMock := &mocks.RnibWriterMock{} - rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock) e2tInstancesManager := NewE2TInstancesManager(rnibDataService, logger) - ranSetupManager := NewRanSetupManager(logger, rmrSender, rnibDataService) httpClient := &mocks.HttpClientMock{} routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClient) e2tAssociationManager := NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient) - ranReconnectionManager := NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tAssociationManager) - return logger, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager, httpClient + ranDisconnectionManager := NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager) + return logger, rmrMessengerMock, readerMock, writerMock, ranDisconnectionManager, httpClient } -func TestRanReconnectionGetNodebFailure(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) +func TestRanDisconnectionGetNodebFailure(t *testing.T) { + _, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t) var nodebInfo *entities.NodebInfo readerMock.On("GetNodeb", ranName).Return(nodebInfo, common.NewInternalError(errors.New("Error"))) - err := ranReconnectionManager.ReconnectRan(ranName) + err := ranDisconnectionManager.DisconnectRan(ranName) assert.NotNil(t, err) readerMock.AssertCalled(t, "GetNodeb", ranName) writerMock.AssertNotCalled(t, "UpdateNodebInfo") } -func TestShutdownRanReconnection(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) +func TestShutdownRan(t *testing.T) { + _, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t) origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) - err := ranReconnectionManager.ReconnectRan(ranName) + err := ranDisconnectionManager.DisconnectRan(ranName) assert.Nil(t, err) readerMock.AssertCalled(t, "GetNodeb", ranName) writerMock.AssertNotCalled(t, "UpdateNodebInfo") } -func TestShuttingdownRanReconnection(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) +func TestShuttingdownRan(t *testing.T) { + _, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t) origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN} var rnibErr error @@ -96,16 +89,46 @@ func TestShuttingdownRanReconnection(t *testing.T) { updatedNodebInfo := *origNodebInfo updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(rnibErr) - err := ranReconnectionManager.ReconnectRan(ranName) + err := ranDisconnectionManager.DisconnectRan(ranName) assert.Nil(t, err) readerMock.AssertCalled(t, "GetNodeb", ranName) writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) } -func TestConnectingRanWithMaxAttemptsReconnectionDissociateSucceeds(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager, httpClient:= initRanLostConnectionTest(t) +func TestShuttingDownRanUpdateNodebInfoFailure(t *testing.T) { + _, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t) + + origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN} + var rnibErr error + readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error"))) + err := ranDisconnectionManager.DisconnectRan(ranName) + assert.NotNil(t, err) + readerMock.AssertCalled(t, "GetNodeb", ranName) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) +} + +func TestConnectingRanUpdateNodebInfoFailure(t *testing.T) { + _, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t) + + origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING} + var rnibErr error + readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error"))) + err := ranDisconnectionManager.DisconnectRan(ranName) + assert.NotNil(t, err) + readerMock.AssertCalled(t, "GetNodeb", ranName) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) +} + +func TestConnectingRanDisconnectSucceeds(t *testing.T) { + _, _, readerMock, writerMock, ranDisconnectionManager, httpClient := initRanLostConnectionTest(t) - origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: E2TAddress} + origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, AssociatedE2TInstanceAddress: E2TAddress} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) updatedNodebInfo1 := *origNodebInfo @@ -115,22 +138,22 @@ func TestConnectingRanWithMaxAttemptsReconnectionDissociateSucceeds(t *testing.T updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED updatedNodebInfo2.AssociatedE2TInstanceAddress = "" writerMock.On("UpdateNodebInfo", &updatedNodebInfo2).Return(rnibErr) - e2tInstance := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:[]string{ranName}} + e2tInstance := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{ranName}} readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil) e2tInstanceToSave := * e2tInstance - e2tInstanceToSave .AssociatedRanList = []string{} + e2tInstanceToSave.AssociatedRanList = []string{} writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil) mockHttpClient(httpClient, clients.DissociateRanE2TInstanceApiSuffix, true) - err := ranReconnectionManager.ReconnectRan(ranName) + err := ranDisconnectionManager.DisconnectRan(ranName) assert.Nil(t, err) readerMock.AssertCalled(t, "GetNodeb", ranName) writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) } -func TestConnectingRanWithMaxAttemptsReconnectionDissociateFails(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) +func TestConnectingRanDissociateFailsRmError(t *testing.T) { + _, _, readerMock, writerMock, ranDisconnectionManager, httpClient := initRanLostConnectionTest(t) - origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: e2tAddress} + origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, AssociatedE2TInstanceAddress: E2TAddress} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) updatedNodebInfo1 := *origNodebInfo @@ -140,69 +163,38 @@ func TestConnectingRanWithMaxAttemptsReconnectionDissociateFails(t *testing.T) { updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED updatedNodebInfo2.AssociatedE2TInstanceAddress = "" writerMock.On("UpdateNodebInfo", &updatedNodebInfo2).Return(rnibErr) - e2tInstance := &entities.E2TInstance{Address:e2tAddress, AssociatedRanList:[]string{ranName}} - readerMock.On("GetE2TInstance",e2tAddress).Return(e2tInstance, common.NewInternalError(errors.New("Error"))) - err := ranReconnectionManager.ReconnectRan(ranName) - assert.NotNil(t, err) - readerMock.AssertCalled(t, "GetNodeb", ranName) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) - writerMock.AssertNotCalled(t, "SaveE2TInstance", ) -} - -func TestUnconnectableRanUpdateNodebInfoFailure(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) - - origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN} - var rnibErr error - readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) - updatedNodebInfo := *origNodebInfo - updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN - writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error"))) - err := ranReconnectionManager.ReconnectRan(ranName) - assert.NotNil(t, err) - readerMock.AssertCalled(t, "GetNodeb", ranName) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) -} - -func TestConnectedRanExecuteSetupSuccess(t *testing.T) { - _, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) - - origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST} - var rnibErr error - readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) - updatedNodebInfo := *origNodebInfo - updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTING - updatedNodebInfo.ConnectionAttempts++ - writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(nil) - rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(&rmrCgo.MBuf{}, nil) - err := ranReconnectionManager.ReconnectRan(ranName) + e2tInstance := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{ranName}} + readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil) + e2tInstanceToSave := * e2tInstance + e2tInstanceToSave.AssociatedRanList = []string{} + writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil) + mockHttpClient(httpClient, clients.DissociateRanE2TInstanceApiSuffix, false) + err := ranDisconnectionManager.DisconnectRan(ranName) assert.Nil(t, err) readerMock.AssertCalled(t, "GetNodeb", ranName) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) } -func TestConnectedRanExecuteSetupFailure(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) +func TestConnectingRanDissociateFailsDbError(t *testing.T) { + _, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t) - origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTED} + origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, AssociatedE2TInstanceAddress: e2tAddress} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) - updatedNodebInfo := *origNodebInfo - updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTING - updatedNodebInfo.ConnectionAttempts++ - writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error"))) - err := ranReconnectionManager.ReconnectRan(ranName) + updatedNodebInfo1 := *origNodebInfo + updatedNodebInfo1.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + writerMock.On("UpdateNodebInfo", &updatedNodebInfo1).Return(rnibErr) + updatedNodebInfo2 := *origNodebInfo + updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + updatedNodebInfo2.AssociatedE2TInstanceAddress = "" + writerMock.On("UpdateNodebInfo", &updatedNodebInfo2).Return(rnibErr) + e2tInstance := &entities.E2TInstance{Address: e2tAddress, AssociatedRanList: []string{ranName}} + readerMock.On("GetE2TInstance", e2tAddress).Return(e2tInstance, common.NewInternalError(errors.New("Error"))) + err := ranDisconnectionManager.DisconnectRan(ranName) assert.NotNil(t, err) readerMock.AssertCalled(t, "GetNodeb", ranName) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) -} - -func TestNoSetConnectionStatus(t *testing.T) { - _, _, _, _, ranReconnectionManager, _ := initRanLostConnectionTest(t) - nodebInfo := &entities.NodebInfo{RanName: "ranName", GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTED} - err := ranReconnectionManager.updateUnconnectableRan(nodebInfo) - assert.Nil(t, err) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) + writerMock.AssertNotCalled(t, "SaveE2TInstance", ) } func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender { diff --git a/E2Manager/managers/ran_reconnection_manager.go b/E2Manager/managers/ran_reconnection_manager.go deleted file mode 100644 index b733142..0000000 --- a/E2Manager/managers/ran_reconnection_manager.go +++ /dev/null @@ -1,131 +0,0 @@ -// -// Copyright 2019 AT&T Intellectual Property -// Copyright 2019 Nokia -// -// 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 managers - -import ( - "e2mgr/configuration" - "e2mgr/logger" - "e2mgr/services" - "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" -) - -type IRanReconnectionManager interface { - ReconnectRan(inventoryName string) error -} - -type RanReconnectionManager struct { - logger *logger.Logger - config *configuration.Configuration - rnibDataService services.RNibDataService - ranSetupManager *RanSetupManager - e2tAssociationManager *E2TAssociationManager -} - -func NewRanReconnectionManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, ranSetupManager *RanSetupManager, e2tAssociationManager *E2TAssociationManager) *RanReconnectionManager { - return &RanReconnectionManager{ - logger: logger, - config: config, - rnibDataService: rnibDataService, - ranSetupManager: ranSetupManager, - e2tAssociationManager: e2tAssociationManager, - } -} - -func (m *RanReconnectionManager) isRanExceededConnectionAttempts(nodebInfo *entities.NodebInfo) bool { - return int(nodebInfo.GetConnectionAttempts()) >= m.config.MaxConnectionAttempts -} - -func (m *RanReconnectionManager) ReconnectRan(inventoryName string) error { - nodebInfo, rnibErr := m.rnibDataService.GetNodeb(inventoryName) - - if rnibErr != nil { - m.logger.Errorf("#RanReconnectionManager.ReconnectRan - RAN name: %s - Failed fetching RAN from rNib. Error: %v", inventoryName, rnibErr) - return rnibErr - } - - m.logger.Infof("#RanReconnectionManager.ReconnectRan - RAN name: %s - RAN's connection status: %s, RAN's connection attempts: %d", nodebInfo.RanName, nodebInfo.ConnectionStatus, nodebInfo.ConnectionAttempts) - - if !m.canReconnectRan(nodebInfo) { - e2tAddress := nodebInfo.AssociatedE2TInstanceAddress - err := m.updateUnconnectableRan(nodebInfo) - - if err != nil { - return err - } - - if m.isRanExceededConnectionAttempts(nodebInfo) { - return m.e2tAssociationManager.DissociateRan(e2tAddress, nodebInfo.RanName) - } - - return nil - } - - err := m.ranSetupManager.ExecuteSetup(nodebInfo, entities.ConnectionStatus_CONNECTING) - - if err != nil { - m.logger.Errorf("#RanReconnectionManager.ReconnectRan - RAN name: %s - Failed executing setup. Error: %v", inventoryName, err) - return err - } - - return nil -} - -func (m *RanReconnectionManager) canReconnectRan(nodebInfo *entities.NodebInfo) bool { - connectionStatus := nodebInfo.GetConnectionStatus() - return connectionStatus != entities.ConnectionStatus_SHUT_DOWN && connectionStatus != entities.ConnectionStatus_SHUTTING_DOWN && - int(nodebInfo.GetConnectionAttempts()) < m.config.MaxConnectionAttempts -} - -func (m *RanReconnectionManager) updateNodebInfo(nodebInfo *entities.NodebInfo, connectionStatus entities.ConnectionStatus) error { - - nodebInfo.ConnectionStatus = connectionStatus; - - err := m.rnibDataService.UpdateNodebInfo(nodebInfo) - - if err != nil { - m.logger.Errorf("#RanReconnectionManager.updateNodebInfo - RAN name: %s - Failed updating RAN's connection status to %s in rNib. Error: %v", nodebInfo.RanName, connectionStatus, err) - return err - } - - m.logger.Infof("#RanReconnectionManager.updateNodebInfo - RAN name: %s - Successfully updated rNib. RAN's current connection status: %s", nodebInfo.RanName, nodebInfo.ConnectionStatus) - return nil -} - -func (m *RanReconnectionManager) updateUnconnectableRan(nodebInfo *entities.NodebInfo) error { - connectionStatus := nodebInfo.GetConnectionStatus() - - if connectionStatus == entities.ConnectionStatus_SHUT_DOWN { - m.logger.Warnf("#RanReconnectionManager.updateUnconnectableRan - RAN name: %s - Cannot reconnect RAN. Reason: connection status is SHUT_DOWN", nodebInfo.RanName) - return nil - } - - if connectionStatus == entities.ConnectionStatus_SHUTTING_DOWN { - m.logger.Warnf("#RanReconnectionManager.updateUnconnectableRan - RAN name: %s - Cannot reconnect RAN. Reason: connection status is SHUTTING_DOWN", nodebInfo.RanName) - return m.updateNodebInfo(nodebInfo, entities.ConnectionStatus_SHUT_DOWN) - } - - if m.isRanExceededConnectionAttempts(nodebInfo) { - m.logger.Warnf("#RanReconnectionManager.updateUnconnectableRan - RAN name: %s - Cannot reconnect RAN. Reason: RAN's connection attempts exceeded the limit (%d)", nodebInfo.RanName, m.config.MaxConnectionAttempts) - return m.updateNodebInfo(nodebInfo, entities.ConnectionStatus_DISCONNECTED) - } - - return nil -} diff --git a/E2Manager/mocks/ran_reconnection_manager_mock.go b/E2Manager/mocks/ran_reconnection_manager_mock.go index 8a3b249..18edaaf 100644 --- a/E2Manager/mocks/ran_reconnection_manager_mock.go +++ b/E2Manager/mocks/ran_reconnection_manager_mock.go @@ -22,11 +22,11 @@ import ( "github.com/stretchr/testify/mock" ) -type RanReconnectionManagerMock struct { +type RanDisconnectionManagerMock struct { mock.Mock } -func (m *RanReconnectionManagerMock) ReconnectRan(inventoryName string) error { +func (m *RanDisconnectionManagerMock) DisconnectRan(inventoryName string) error { args := m.Called(inventoryName) return args.Error(0) diff --git a/E2Manager/mocks/routing_manager_client_mock.go b/E2Manager/mocks/routing_manager_client_mock.go index 0652276..717703d 100644 --- a/E2Manager/mocks/routing_manager_client_mock.go +++ b/E2Manager/mocks/routing_manager_client_mock.go @@ -51,8 +51,8 @@ args := m.Called(e2tAddresses) return args.Error(0) } -func (m *RoutingManagerClientMock) DeleteE2TInstance(e2tAddress string, ransToBeDissociated []string, e2tToRansAssociations map[string][]string) error { +func (m *RoutingManagerClientMock) DeleteE2TInstance(e2tAddress string, ransToBeDissociated []string) error { - args := m.Called(e2tAddress, ransToBeDissociated, e2tToRansAssociations) + args := m.Called(e2tAddress, ransToBeDissociated) return args.Error(0) } \ No newline at end of file diff --git a/E2Manager/models/e2_setup_request_message.go b/E2Manager/models/e2_setup_request_message.go new file mode 100644 index 0000000..d07f4df --- /dev/null +++ b/E2Manager/models/e2_setup_request_message.go @@ -0,0 +1,176 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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 E2SetupRequestMessage struct { + XMLName xml.Name `xml:"E2SetupRequestMessage"` + Text string `xml:",chardata"` + E2APPDU struct { + Text string `xml:",chardata"` + InitiatingMessage struct { + Text string `xml:",chardata"` + ProcedureCode string `xml:"procedureCode"` + Criticality struct { + Text string `xml:",chardata"` + Reject string `xml:"reject"` + } `xml:"criticality"` + Value struct { + Text string `xml:",chardata"` + E2setupRequest struct { + Text string `xml:",chardata"` + ProtocolIEs struct { + Text string `xml:",chardata"` + E2setupRequestIEs []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"` + GlobalE2nodeID struct { + Text string `xml:",chardata"` + GNB struct { + Text string `xml:",chardata"` + GlobalGNBID struct { + Text string `xml:",chardata"` + PlmnID string `xml:"plmn-id"` + GnbID struct { + Text string `xml:",chardata"` + GnbID string `xml:"gnb-ID"` + } `xml:"gnb-id"` + } `xml:"global-gNB-ID"` + } `xml:"gNB"` + EnGNB struct { + Text string `xml:",chardata"` + GlobalGNBID struct { + Text string `xml:",chardata"` + PlmnID string `xml:"plmn-id"` + GnbID struct { + Text string `xml:",chardata"` + GnbID string `xml:"gnb-ID"` + } `xml:"gnb-id"` + } `xml:"global-gNB-ID"` + } `xml:"en-gNB"` + NgENB struct { + Text string `xml:",chardata"` + GlobalNgENBID struct { + Text string `xml:",chardata"` + PlmnID string `xml:"plmn-id"` + GnbID struct { + Text string `xml:",chardata"` + GnbID string `xml:"gnb-ID"` + } `xml:"gnb-id"` + } `xml:"global-ng-eNB-ID"` + } `xml:"ng-eNB"` + ENB struct { + Text string `xml:",chardata"` + GlobalENBID struct { + Text string `xml:",chardata"` + PlmnID string `xml:"plmn-id"` + GnbID struct { + Text string `xml:",chardata"` + GnbID string `xml:"gnb-ID"` + } `xml:"gnb-id"` + } `xml:"global-eNB-ID"` + } `xml:"eNB"` + } `xml:"GlobalE2node-ID"` + RANfunctionsList struct { + Text string `xml:",chardata"` + ProtocolIESingleContainer []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"` + RANfunctionItem struct { + Text string `xml:",chardata"` + RanFunctionID string `xml:"ranFunctionID"` + RanFunctionDefinition string `xml:"ranFunctionDefinition"` + RanFunctionRevision string `xml:"ranFunctionRevision"` + } `xml:"RANfunction-Item"` + } `xml:"value"` + } `xml:"ProtocolIE-SingleContainer"` + } `xml:"RANfunctions-List"` + } `xml:"value"` + } `xml:"E2setupRequestIEs"` + } `xml:"protocolIEs"` + } `xml:"E2setupRequest"` + } `xml:"value"` + } `xml:"initiatingMessage"` + } `xml:"E2AP-PDU"` +} + +func (m *E2SetupRequestMessage) GetNodeType() entities.Node_Type{ + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.GNB.GlobalGNBID.PlmnID; id!= ""{ + return entities.Node_GNB + } + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.EnGNB.GlobalGNBID.PlmnID; id!= ""{ + return entities.Node_GNB + } + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.ENB.GlobalENBID.PlmnID; id!= ""{ + return entities.Node_ENB + } + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.NgENB.GlobalNgENBID.PlmnID; id!= ""{ + return entities.Node_GNB + } + return entities.Node_UNKNOWN +} + +func (m *E2SetupRequestMessage) GetPlmnId() string{ + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.GNB.GlobalGNBID.PlmnID; id!= ""{ + return id + } + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.EnGNB.GlobalGNBID.PlmnID; id!= ""{ + return id + } + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.ENB.GlobalENBID.PlmnID; id!= ""{ + return id + } + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.NgENB.GlobalNgENBID.PlmnID; id!= ""{ + return id + } + return "" +} + +func (m *E2SetupRequestMessage) GetNbId() string{ + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.GNB.GlobalGNBID.GnbID.GnbID; id!= ""{ + return id + } + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.EnGNB.GlobalGNBID.GnbID.GnbID; id!= ""{ + return id + } + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.ENB.GlobalENBID.GnbID.GnbID; id!= ""{ + return id + } + if id := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID.NgENB.GlobalNgENBID.GnbID.GnbID; id!= ""{ + return id + } + return "" +} \ No newline at end of file diff --git a/E2Manager/models/e2_setup_success_response_message.go b/E2Manager/models/e2_setup_success_response_message.go new file mode 100644 index 0000000..5e58de0 --- /dev/null +++ b/E2Manager/models/e2_setup_success_response_message.go @@ -0,0 +1,73 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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" +) + +type E2SetupSuccessResponseMessage struct { + XMLName xml.Name `xml:"E2SetupSuccessResponseMessage"` + Text string `xml:",chardata"` + E2APPDU struct { + Text string `xml:",chardata"` + SuccessfulOutcome struct { + Text string `xml:",chardata"` + ProcedureCode string `xml:"procedureCode"` + Criticality struct { + Text string `xml:",chardata"` + Reject string `xml:"reject"` + } `xml:"criticality"` + Value struct { + Text string `xml:",chardata"` + E2setupResponse struct { + Text string `xml:",chardata"` + ProtocolIEs struct { + Text string `xml:",chardata"` + E2setupResponseIEs 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"` + GlobalRICID struct { + Text string `xml:",chardata"` + PLMNIdentity string `xml:"pLMN-Identity"` + RicID string `xml:"ric-ID"` + } `xml:"GlobalRIC-ID"` + } `xml:"value"` + } `xml:"E2setupResponseIEs"` + } `xml:"protocolIEs"` + } `xml:"E2setupResponse"` + } `xml:"value"` + } `xml:"successfulOutcome"` + } `xml:"E2AP-PDU"` +} + + +func (m *E2SetupSuccessResponseMessage) SetPlmnId(plmnId string){ + m.E2APPDU.SuccessfulOutcome.Value.E2setupResponse.ProtocolIEs.E2setupResponseIEs.Value.GlobalRICID.PLMNIdentity = plmnId +} + +func (m *E2SetupSuccessResponseMessage) SetNbId(ricID string){ + m.E2APPDU.SuccessfulOutcome.Value.E2setupResponse.ProtocolIEs.E2setupResponseIEs.Value.GlobalRICID.RicID = ricID +} \ No newline at end of file diff --git a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go index 3d79c28..b161841 100644 --- a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go +++ b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go @@ -17,7 +17,6 @@ // This source code is part of the near-RT RIC (RAN Intelligent Controller) // platform project (RICP). - package rmrmsghandlerprovider import ( @@ -69,7 +68,7 @@ func (provider *NotificationHandlerProvider) Init(logger *logger.Logger, config x2ResetResponseExtractor := converters.NewX2ResetResponseExtractor(logger) // Init managers - ranReconnectionManager := managers.NewRanReconnectionManager(logger, config, rnibDataService, ranSetupManager, e2tAssociationManager) + ranReconnectionManager := managers.NewRanDisconnectionManager(logger, config, rnibDataService, e2tAssociationManager) ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender) x2SetupResponseManager := managers.NewX2SetupResponseManager(x2SetupResponseConverter) x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter) @@ -89,6 +88,7 @@ func (provider *NotificationHandlerProvider) Init(logger *logger.Logger, config x2ResetRequestNotificationHandler := rmrmsghandlers.NewX2ResetRequestNotificationHandler(logger, rnibDataService, ranStatusChangeManager, rmrSender) e2TermInitNotificationHandler := rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranReconnectionManager, e2tInstancesManager, routingManagerClient) e2TKeepAliveResponseHandler := rmrmsghandlers.NewE2TKeepAliveResponseHandler(logger, rnibDataService, e2tInstancesManager) + e2SetupRequestNotificationHandler := rmrmsghandlers.NewE2SetupRequestNotificationHandler(logger, e2tInstancesManager, rmrSender, rnibDataService, e2tAssociationManager) provider.Register(rmrCgo.RIC_X2_SETUP_RESP, x2SetupResponseHandler) provider.Register(rmrCgo.RIC_X2_SETUP_FAILURE, x2SetupFailureResponseHandler) @@ -102,4 +102,5 @@ func (provider *NotificationHandlerProvider) Init(logger *logger.Logger, config provider.Register(rmrCgo.RIC_X2_RESET, x2ResetRequestNotificationHandler) provider.Register(rmrCgo.RIC_E2_TERM_INIT, e2TermInitNotificationHandler) provider.Register(rmrCgo.E2_TERM_KEEP_ALIVE_RESP, e2TKeepAliveResponseHandler) + provider.Register(rmrCgo.RIC_E2_SETUP_REQ, e2SetupRequestNotificationHandler) } diff --git a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go index 5d20a5f..c5167c0 100644 --- a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go +++ b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go @@ -64,7 +64,7 @@ func TestGetNotificationHandlerSuccess(t *testing.T) { logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient, e2tAssociationManager := initTestCase(t) - ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tAssociationManager) + ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager) ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender) x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger) @@ -89,11 +89,11 @@ func TestGetNotificationHandlerSuccess(t *testing.T) { {rmrCgo.RIC_X2_SETUP_FAILURE, rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, x2SetupFailureResponseManager, ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_FAILURE)}, {rmrCgo.RIC_ENDC_X2_SETUP_RESP, rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, endcSetupResponseManager, ranStatusChangeManager, rmrCgo.RIC_ENDC_X2_SETUP_RESP)}, {rmrCgo.RIC_ENDC_X2_SETUP_FAILURE, rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, endcSetupFailureResponseManager, ranStatusChangeManager, rmrCgo.RIC_ENDC_X2_SETUP_FAILURE),}, - {rmrCgo.RIC_SCTP_CONNECTION_FAILURE, rmrmsghandlers.NewRanLostConnectionHandler(logger, ranReconnectionManager)}, + {rmrCgo.RIC_SCTP_CONNECTION_FAILURE, rmrmsghandlers.NewRanLostConnectionHandler(logger, ranDisconnectionManager)}, {rmrCgo.RIC_ENB_LOAD_INFORMATION, rmrmsghandlers.NewEnbLoadInformationNotificationHandler(logger, rnibDataService, converters.NewEnbLoadInformationExtractor(logger))}, {rmrCgo.RIC_ENB_CONF_UPDATE, rmrmsghandlers.NewX2EnbConfigurationUpdateHandler(logger, rmrSender)}, {rmrCgo.RIC_ENDC_CONF_UPDATE, rmrmsghandlers.NewEndcConfigurationUpdateHandler(logger, rmrSender)}, - {rmrCgo.RIC_E2_TERM_INIT, rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranReconnectionManager, e2tInstancesManager, routingManagerClient)}, + {rmrCgo.RIC_E2_TERM_INIT, rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranDisconnectionManager, e2tInstancesManager, routingManagerClient)}, {rmrCgo.E2_TERM_KEEP_ALIVE_RESP, rmrmsghandlers.NewE2TKeepAliveResponseHandler(logger, rnibDataService, e2tInstancesManager)}, {rmrCgo.RIC_X2_RESET_RESP, rmrmsghandlers.NewX2ResetResponseHandler(logger, rnibDataService, ranStatusChangeManager, converters.NewX2ResetResponseExtractor(logger))}, {rmrCgo.RIC_X2_RESET, rmrmsghandlers.NewX2ResetRequestNotificationHandler(logger, rnibDataService, ranStatusChangeManager, rmrSender)}, diff --git a/E2Manager/rmrCgo/rmrCgoApi.go b/E2Manager/rmrCgo/rmrCgoApi.go index 308ab63..d247efb 100644 --- a/E2Manager/rmrCgo/rmrCgoApi.go +++ b/E2Manager/rmrCgo/rmrCgoApi.go @@ -20,7 +20,7 @@ package rmrCgo -// #cgo LDFLAGS: -L/usr/local/lib -lrmr_nng -lnng +// #cgo LDFLAGS: -L/usr/local/lib -lrmr_si // #include // #include import "C" diff --git a/E2Manager/rmrCgo/rmrCgoTypes.go b/E2Manager/rmrCgo/rmrCgoTypes.go index eff707c..d7dcbef 100644 --- a/E2Manager/rmrCgo/rmrCgoTypes.go +++ b/E2Manager/rmrCgo/rmrCgoTypes.go @@ -20,7 +20,7 @@ package rmrCgo -// #cgo LDFLAGS: -L/usr/local/lib -lrmr_nng -lnng +// #cgo LDFLAGS: -L/usr/local/lib -lrmr_si // #include // #include // #include @@ -76,6 +76,9 @@ const ( RAN_RECONFIGURED = C.RAN_RECONFIGURED E2_TERM_KEEP_ALIVE_REQ = C.E2_TERM_KEEP_ALIVE_REQ E2_TERM_KEEP_ALIVE_RESP = C.E2_TERM_KEEP_ALIVE_RESP + 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 ) const ( diff --git a/E2Manager/rmrCgo/rmrCgoUtils.go b/E2Manager/rmrCgo/rmrCgoUtils.go index ca29747..8b895c0 100644 --- a/E2Manager/rmrCgo/rmrCgoUtils.go +++ b/E2Manager/rmrCgo/rmrCgoUtils.go @@ -20,7 +20,7 @@ package rmrCgo -// #cgo LDFLAGS: -L/usr/local/lib -lrmr_nng -lnng +// #cgo LDFLAGS: -L/usr/local/lib -lrmr_si // #include // #include import "C" diff --git a/E2Manager/tests/resources/setupRequest_en-gNB.xml b/E2Manager/tests/resources/setupRequest_en-gNB.xml new file mode 100644 index 0000000..95b137a --- /dev/null +++ b/E2Manager/tests/resources/setupRequest_en-gNB.xml @@ -0,0 +1,62 @@ + + + + 1 + + + + + + 3 + + + + + + 13 10 14 + + + 10110101110001100111011110001000 + + + + + + + + + 10 + + + + + 8 + + + + 1 + 33 44 55 + 0 + + + + + 8 + + + + 7 + 33 44 55 + 0 + + + + + + + + + + + + \ No newline at end of file diff --git a/E2Manager/tests/resources/setupRequest_gnb.xml b/E2Manager/tests/resources/setupRequest_gnb.xml new file mode 100644 index 0000000..1a74a2a --- /dev/null +++ b/E2Manager/tests/resources/setupRequest_gnb.xml @@ -0,0 +1,60 @@ + + + + 1 + + + + + + 3 + + + + + + 13 10 14 + + 10110101110001100111011110001000 + + + + + + + + 10 + + + + + 8 + + + + 1 + 33 44 55 + 0 + + + + + 8 + + + + 7 + 33 44 55 + 0 + + + + + + + + + + + + \ No newline at end of file diff --git a/E2Manager/tests/resources/setupRequest_ng-eNB.xml b/E2Manager/tests/resources/setupRequest_ng-eNB.xml new file mode 100644 index 0000000..c60775c --- /dev/null +++ b/E2Manager/tests/resources/setupRequest_ng-eNB.xml @@ -0,0 +1,60 @@ + + + + 1 + + + + + + 3 + + + + + + 13 10 14 + + 10110101110001100111011110001000 + + + + + + + + 10 + + + + + 8 + + + + 1 + 33 44 55 + 0 + + + + + 8 + + + + 7 + 33 44 55 + 0 + + + + + + + + + + + + \ No newline at end of file