From 8a5bfb08333e955f36321026444ab52989fbf3ec Mon Sep 17 00:00:00 2001 From: is005q Date: Wed, 25 Dec 2019 09:54:25 +0200 Subject: [PATCH 01/16] [RICPLT-2527] Fix request model of assoc/dissoc and add dissoc all Change-Id: I1e48844f93cda7e46b3c2ffd6efe1af129967a30 Signed-off-by: is005q --- E2Manager/clients/routing_manager_client.go | 26 ++++++++++++++++++---- E2Manager/clients/routing_manager_client_test.go | 12 +++++----- .../httpmsghandlers/setup_request_handler_test.go | 2 +- E2Manager/managers/e2t_association_manager_test.go | 2 +- E2Manager/models/routing_manager_e2t_data_list.go | 22 ++++++++++++++++++ 5 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 E2Manager/models/routing_manager_e2t_data_list.go diff --git a/E2Manager/clients/routing_manager_client.go b/E2Manager/clients/routing_manager_client.go index c584f5b..52e9250 100644 --- a/E2Manager/clients/routing_manager_client.go +++ b/E2Manager/clients/routing_manager_client.go @@ -65,7 +65,7 @@ func (c *RoutingManagerClient) AddE2TInstance(e2tAddress string) error { func (c *RoutingManagerClient) AssociateRanToE2TInstance(e2tAddress string, ranName string) error { - data := models.NewRoutingManagerE2TData(e2tAddress, ranName) + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(e2tAddress, ranName)} url := c.config.RoutingManager.BaseUrl + AssociateRanToE2TInstanceApiSuffix return c.PostMessage(data, url) @@ -73,13 +73,21 @@ func (c *RoutingManagerClient) AssociateRanToE2TInstance(e2tAddress string, ranN func (c *RoutingManagerClient) DissociateRanE2TInstance(e2tAddress string, ranName string) error { - data := models.NewRoutingManagerE2TData(e2tAddress, ranName) + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(e2tAddress, ranName)} url := c.config.RoutingManager.BaseUrl + DissociateRanE2TInstanceApiSuffix return c.PostMessage(data, url) } -func (c *RoutingManagerClient) PostMessage(data *models.RoutingManagerE2TData, url string) error { +func (c *RoutingManagerClient) DissociateAllRans(e2tAddresses []string) error { + + data := mapE2TAddressesToE2DataList(e2tAddresses) + url := c.config.RoutingManager.BaseUrl + DissociateRanE2TInstanceApiSuffix + + return c.PostMessage(data, url) +} + +func (c *RoutingManagerClient) PostMessage(data interface{}, url string) error { marshaled, err := json.Marshal(data) if err != nil { @@ -105,4 +113,14 @@ func (c *RoutingManagerClient) PostMessage(data *models.RoutingManagerE2TData, u c.logger.Errorf("[Routing Manager -> E2M] #RoutingManagerClient.PostMessage - failure. http status code: %d", resp.StatusCode) return e2managererrors.NewRoutingManagerError() -} \ No newline at end of file +} + +func mapE2TAddressesToE2DataList(e2tAddresses []string) models.RoutingManagerE2TDataList { + e2tDataList := make(models.RoutingManagerE2TDataList, len(e2tAddresses)) + + for i, v := range e2tAddresses { + e2tDataList[i] = models.NewRoutingManagerE2TData(v) + } + + return e2tDataList +} diff --git a/E2Manager/clients/routing_manager_client_test.go b/E2Manager/clients/routing_manager_client_test.go index 2d02cfd..59e6125 100644 --- a/E2Manager/clients/routing_manager_client_test.go +++ b/E2Manager/clients/routing_manager_client_test.go @@ -88,7 +88,7 @@ func TestAddE2TInstanceFailure(t *testing.T) { func TestAssociateRanToE2TInstance_Success(t *testing.T) { rmClient, httpClientMock, config := initRoutingManagerClientTest(t) - data := models.NewRoutingManagerE2TData(E2TAddress,RanName) + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress,RanName)} marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) url := config.RoutingManager.BaseUrl + AssociateRanToE2TInstanceApiSuffix @@ -101,7 +101,7 @@ func TestAssociateRanToE2TInstance_Success(t *testing.T) { func TestAssociateRanToE2TInstance_RoutingManagerError(t *testing.T) { rmClient, httpClientMock, config := initRoutingManagerClientTest(t) - data := models.NewRoutingManagerE2TData(E2TAddress,RanName) + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress,RanName)} marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) url := config.RoutingManager.BaseUrl + AssociateRanToE2TInstanceApiSuffix @@ -113,7 +113,7 @@ func TestAssociateRanToE2TInstance_RoutingManagerError(t *testing.T) { func TestAssociateRanToE2TInstance_RoutingManager_400(t *testing.T) { rmClient, httpClientMock, config := initRoutingManagerClientTest(t) - data := models.NewRoutingManagerE2TData(E2TAddress,RanName) + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress,RanName)} marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) url := config.RoutingManager.BaseUrl + AssociateRanToE2TInstanceApiSuffix @@ -126,7 +126,7 @@ func TestAssociateRanToE2TInstance_RoutingManager_400(t *testing.T) { func TestDissociateRanE2TInstance_Success(t *testing.T) { rmClient, httpClientMock, config := initRoutingManagerClientTest(t) - data := models.NewRoutingManagerE2TData(E2TAddress,RanName) + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress,RanName)} marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) url := config.RoutingManager.BaseUrl + DissociateRanE2TInstanceApiSuffix @@ -139,7 +139,7 @@ func TestDissociateRanE2TInstance_Success(t *testing.T) { func TestDissociateRanE2TInstance_RoutingManagerError(t *testing.T) { rmClient, httpClientMock, config := initRoutingManagerClientTest(t) - data := models.NewRoutingManagerE2TData(E2TAddress,RanName) + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress,RanName)} marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) url := config.RoutingManager.BaseUrl + DissociateRanE2TInstanceApiSuffix @@ -151,7 +151,7 @@ func TestDissociateRanE2TInstance_RoutingManagerError(t *testing.T) { func TestDissociateRanE2TInstance_RoutingManager_400(t *testing.T) { rmClient, httpClientMock, config := initRoutingManagerClientTest(t) - data := models.NewRoutingManagerE2TData(E2TAddress,RanName) + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress,RanName)} marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) url := config.RoutingManager.BaseUrl + DissociateRanE2TInstanceApiSuffix diff --git a/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go b/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go index 2fc1c5c..7586791 100644 --- a/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go +++ b/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go @@ -88,7 +88,7 @@ func initSetupRequestTestBasicMocks(t *testing.T, protocol entities.E2Applicatio } func mockHttpClientAssociateRan(httpClientMock *mocks.HttpClientMock) { - data := models.NewRoutingManagerE2TData(E2TAddress, RanName) + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)} marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) url := BaseRMUrl + clients.AssociateRanToE2TInstanceApiSuffix diff --git a/E2Manager/managers/e2t_association_manager_test.go b/E2Manager/managers/e2t_association_manager_test.go index 75cfb3b..6754a3b 100644 --- a/E2Manager/managers/e2t_association_manager_test.go +++ b/E2Manager/managers/e2t_association_manager_test.go @@ -57,7 +57,7 @@ func initE2TAssociationManagerTest(t *testing.T) (*E2TAssociationManager, *mocks } func mockHttpClientAssociateRan(httpClientMock *mocks.HttpClientMock, isSuccessful bool) { - data := models.NewRoutingManagerE2TData(E2TAddress, RanName) + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)} marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) url := BaseRMUrl + clients.AssociateRanToE2TInstanceApiSuffix diff --git a/E2Manager/models/routing_manager_e2t_data_list.go b/E2Manager/models/routing_manager_e2t_data_list.go new file mode 100644 index 0000000..4179d83 --- /dev/null +++ b/E2Manager/models/routing_manager_e2t_data_list.go @@ -0,0 +1,22 @@ +// +// 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 + +type RoutingManagerE2TDataList []*RoutingManagerE2TData -- 2.16.6 From 0c747ac879f6b50089ca7317f4d85a4b69175237 Mon Sep 17 00:00:00 2001 From: Amichai Date: Wed, 25 Dec 2019 14:06:40 +0200 Subject: [PATCH 02/16] [RICPLT-2527] Implementation of DissociateRan + UTs Change-Id: I5a285f4eeed731a051285e0856335105dca9d7f6 Signed-off-by: Amichai --- E2Manager/app/main.go | 2 +- .../e2_term_init_notification_handler_test.go | 6 +- E2Manager/managers/e2t_association_manager.go | 31 +++++ E2Manager/managers/e2t_association_manager_test.go | 138 +++++++++++++++++++-- E2Manager/managers/e2t_instances_manager.go | 4 +- .../notification_manager_test.go | 3 +- E2Manager/managers/ran_reconnection_manager.go | 24 ++-- .../managers/ran_reconnection_manager_test.go | 61 ++++----- .../notification_handler_provider.go | 4 +- .../notification_handler_provider_test.go | 15 +-- .../services/rmrreceiver/rmr_receiver_test.go | 3 +- 11 files changed, 213 insertions(+), 78 deletions(-) diff --git a/E2Manager/app/main.go b/E2Manager/app/main.go index e311dc8..0678611 100644 --- a/E2Manager/app/main.go +++ b/E2Manager/app/main.go @@ -65,7 +65,7 @@ func main() { routingManagerClient := clients.NewRoutingManagerClient(logger, config, &http.Client{}) e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient) rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider() - rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient) + rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient, e2tAssociationManager) notificationManager := notificationmanager.NewNotificationManager(logger, rmrNotificationHandlerProvider) rmrReceiver := rmrreceiver.NewRmrReceiver(logger, rmrMessenger, notificationManager) 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 18c89ca..c930b0e 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go @@ -64,8 +64,9 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotifica ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService) e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{} + e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManagerMock, routingManagerClientMock) - ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManagerMock) + ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tAssociationManager) handler := NewE2TermInitNotificationHandler(logger, ranReconnectionManager, e2tInstancesManagerMock, routingManagerClientMock) return logger, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock @@ -89,7 +90,8 @@ func initRanLostConnectionTestWithRealE2tInstanceManager(t *testing.T) (*logger. ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService) e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger) - ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManager) + 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 } diff --git a/E2Manager/managers/e2t_association_manager.go b/E2Manager/managers/e2t_association_manager.go index 3311e60..78ae6d7 100644 --- a/E2Manager/managers/e2t_association_manager.go +++ b/E2Manager/managers/e2t_association_manager.go @@ -73,3 +73,34 @@ func (m *E2TAssociationManager) AssociateRan(e2tAddress string, ranName string) m.logger.Infof("#E2TAssociationManager.AssociateRan - successfully associated RAN %s with E2T %s", ranName, e2tAddress) return nil } + +func (m *E2TAssociationManager) DissociateRan(e2tAddress string, ranName string) error { + m.logger.Infof("#E2TAssociationManager.DissociateRan - Dissociating RAN %s from E2T Instance address: %s", ranName, e2tAddress) + + nodebInfo, rnibErr := m.rnibDataService.GetNodeb(ranName) + if rnibErr != nil { + m.logger.Errorf("#E2TAssociationManager.DissociateRan - RAN name: %s - Failed fetching RAN from rNib. Error: %s", ranName, rnibErr) + return rnibErr + } + + nodebInfo.AssociatedE2TInstanceAddress = "" + rnibErr = m.rnibDataService.UpdateNodebInfo(nodebInfo) + if rnibErr != nil { + m.logger.Errorf("#E2TAssociationManager.DissociateRan - RAN name: %s - Failed to update RAN.AssociatedE2TInstanceAddress in rNib. Error: %s", ranName, rnibErr) + return rnibErr + } + + err := m.e2tInstanceManager.RemoveRanFromInstance(ranName, e2tAddress) + if err != nil { + m.logger.Errorf("#E2TAssociationManager.DissociateRan - RAN name: %s - Failed to remove RAN from E2T instance %s. Error: %s", ranName, e2tAddress, err) + return err + } + + err = m.rmClient.DissociateRanE2TInstance(e2tAddress, ranName) + if err != nil { + m.logger.Errorf("#E2TAssociationManager.DissociateRan - RoutingManager failure: Failed to dissociate RAN %s from E2T %s. Error: %s", ranName, e2tAddress, err) + } else { + m.logger.Infof("#E2TAssociationManager.DissociateRan - successfully dissociated RAN %s from E2T %s", ranName, e2tAddress) + } + return nil +} diff --git a/E2Manager/managers/e2t_association_manager_test.go b/E2Manager/managers/e2t_association_manager_test.go index 6754a3b..cdaed68 100644 --- a/E2Manager/managers/e2t_association_manager_test.go +++ b/E2Manager/managers/e2t_association_manager_test.go @@ -37,12 +37,10 @@ import ( ) const RanName = "test" -const BaseRMUrl = "http://10.10.2.15:12020/routingmanager" func initE2TAssociationManagerTest(t *testing.T) (*E2TAssociationManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) { log := initLog(t) config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3} - config.RoutingManager.BaseUrl = BaseRMUrl readerMock := &mocks.RnibReaderMock{} writerMock := &mocks.RnibWriterMock{} @@ -56,11 +54,10 @@ func initE2TAssociationManagerTest(t *testing.T) (*E2TAssociationManager, *mocks return manager, readerMock, writerMock, httpClientMock } -func mockHttpClientAssociateRan(httpClientMock *mocks.HttpClientMock, isSuccessful bool) { +func mockHttpClient(httpClientMock *mocks.HttpClientMock, apiSuffix string, isSuccessful bool) { data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)} marshaled, _ := json.Marshal(data) body := bytes.NewBuffer(marshaled) - url := BaseRMUrl + clients.AssociateRanToE2TInstanceApiSuffix respBody := ioutil.NopCloser(bytes.NewBufferString("")) var respStatusCode int if isSuccessful { @@ -68,12 +65,12 @@ func mockHttpClientAssociateRan(httpClientMock *mocks.HttpClientMock, isSuccessf } else { respStatusCode = http.StatusBadRequest } - httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil) + httpClientMock.On("Post", apiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil) } func TestAssociateRanSuccess(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - mockHttpClientAssociateRan(httpClientMock, true) + mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1} readerMock.On("GetNodeb", RanName).Return(nb, nil) updatedNb := *nb @@ -96,7 +93,7 @@ func TestAssociateRanSuccess(t *testing.T) { func TestAssociateRanRoutingManagerError(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - mockHttpClientAssociateRan(httpClientMock, false) + mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, false) err := manager.AssociateRan(E2TAddress, RanName) @@ -109,7 +106,7 @@ func TestAssociateRanRoutingManagerError(t *testing.T) { func TestAssociateRanGetNodebError(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - mockHttpClientAssociateRan(httpClientMock, true) + mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) var nb *entities.NodebInfo readerMock.On("GetNodeb", RanName).Return(nb, e2managererrors.NewRnibDbError()) @@ -124,7 +121,7 @@ func TestAssociateRanGetNodebError(t *testing.T) { func TestAssociateRanUpdateNodebError(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - mockHttpClientAssociateRan(httpClientMock, true) + mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1} readerMock.On("GetNodeb", RanName).Return(nb, nil) updatedNb := *nb @@ -143,7 +140,7 @@ func TestAssociateRanUpdateNodebError(t *testing.T) { func TestAssociateRanGetE2tInstanceError(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - mockHttpClientAssociateRan(httpClientMock, true) + mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1} readerMock.On("GetNodeb", RanName).Return(nb, nil) updatedNb := *nb @@ -164,7 +161,7 @@ func TestAssociateRanGetE2tInstanceError(t *testing.T) { func TestAssociateRanSaveE2tInstanceError(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - mockHttpClientAssociateRan(httpClientMock, true) + mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1} readerMock.On("GetNodeb", RanName).Return(nb, nil) updatedNb := *nb @@ -185,3 +182,122 @@ func TestAssociateRanSaveE2tInstanceError(t *testing.T) { writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) } + +func TestDissociateRanSuccess(t *testing.T) { + manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) + mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, true) + nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionAttempts: 1} + readerMock.On("GetNodeb", RanName).Return(nb, nil) + updatedNb := *nb + updatedNb.AssociatedE2TInstanceAddress = "" + writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil) + e2tInstance := &entities.E2TInstance{Address: E2TAddress} + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) + readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil) + updatedE2tInstance := *e2tInstance + updatedE2tInstance.AssociatedRanList = []string{} + writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil) + + err := manager.DissociateRan(E2TAddress, RanName) + + assert.Nil(t, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + httpClientMock.AssertExpectations(t) +} + +func TestDissociateRanGetNodebError(t *testing.T) { + manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) + var nb *entities.NodebInfo + readerMock.On("GetNodeb", RanName).Return(nb, e2managererrors.NewRnibDbError()) + + err := manager.DissociateRan(E2TAddress, RanName) + + assert.NotNil(t, err) + assert.IsType(t, &e2managererrors.RnibDbError{}, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + httpClientMock.AssertExpectations(t) +} + +func TestDissociateRanUpdateNodebError(t *testing.T) { + manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) + nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionAttempts: 1} + readerMock.On("GetNodeb", RanName).Return(nb, nil) + updatedNb := *nb + updatedNb.AssociatedE2TInstanceAddress = "" + writerMock.On("UpdateNodebInfo", &updatedNb).Return(e2managererrors.NewRnibDbError()) + + err := manager.DissociateRan(E2TAddress, RanName) + + assert.NotNil(t, err) + assert.IsType(t, &e2managererrors.RnibDbError{}, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + httpClientMock.AssertExpectations(t) +} + +func TestDissociateRanGetE2tInstanceError(t *testing.T) { + manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) + nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionAttempts: 1} + readerMock.On("GetNodeb", RanName).Return(nb, nil) + updatedNb := *nb + updatedNb.AssociatedE2TInstanceAddress = "" + writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil) + var e2tInstance *entities.E2TInstance + readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test")) + + err := manager.DissociateRan(E2TAddress, RanName) + + assert.NotNil(t, err) + assert.IsType(t, &e2managererrors.RnibDbError{}, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + httpClientMock.AssertExpectations(t) +} + +func TestDissociateRanSaveE2tInstanceError(t *testing.T) { + manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) + nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionAttempts: 1} + readerMock.On("GetNodeb", RanName).Return(nb, nil) + updatedNb := *nb + updatedNb.AssociatedE2TInstanceAddress = "" + writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil) + e2tInstance := &entities.E2TInstance{Address: E2TAddress} + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) + readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil) + updatedE2tInstance := *e2tInstance + updatedE2tInstance.AssociatedRanList = []string{} + writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test")) + + err := manager.DissociateRan(E2TAddress, RanName) + + assert.NotNil(t, err) + assert.IsType(t, &e2managererrors.RnibDbError{}, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + httpClientMock.AssertExpectations(t) +} + +func TestDissociateRanRoutingManagerError(t *testing.T) { + manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) + mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, false) + nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionAttempts: 1} + readerMock.On("GetNodeb", RanName).Return(nb, nil) + updatedNb := *nb + updatedNb.AssociatedE2TInstanceAddress = "" + writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil) + e2tInstance := &entities.E2TInstance{Address: E2TAddress} + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) + readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil) + updatedE2tInstance := *e2tInstance + updatedE2tInstance.AssociatedRanList = []string{} + writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil) + + err := manager.DissociateRan(E2TAddress, RanName) + + assert.Nil(t, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + httpClientMock.AssertExpectations(t) +} \ No newline at end of file diff --git a/E2Manager/managers/e2t_instances_manager.go b/E2Manager/managers/e2t_instances_manager.go index 4f4017d..0a95f5f 100644 --- a/E2Manager/managers/e2t_instances_manager.go +++ b/E2Manager/managers/e2t_instances_manager.go @@ -235,7 +235,7 @@ func (m *E2TInstancesManager) RemoveRanFromInstance(ranName string, e2tAddress s if err != nil { m.logger.Errorf("#E2TInstancesManager.RemoveRanFromInstance - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err) - return err + return e2managererrors.NewRnibDbError() } i := 0 // output index @@ -253,7 +253,7 @@ func (m *E2TInstancesManager) RemoveRanFromInstance(ranName string, e2tAddress s if err != nil { m.logger.Errorf("#E2TInstancesManager.RemoveRanFromInstance - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err) - return err + return e2managererrors.NewRnibDbError() } m.logger.Infof("#E2TInstancesManager.RemoveRanFromInstance - successfully dissociated RAN %s from E2T %s", ranName, e2tInstance.Address) diff --git a/E2Manager/managers/notificationmanager/notification_manager_test.go b/E2Manager/managers/notificationmanager/notification_manager_test.go index bd6798e..ded3f27 100644 --- a/E2Manager/managers/notificationmanager/notification_manager_test.go +++ b/E2Manager/managers/notificationmanager/notification_manager_test.go @@ -49,8 +49,9 @@ func initNotificationManagerTest(t *testing.T) (*logger.Logger, *mocks.RnibReade ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService) e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger) routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClient) + e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient) rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider() - rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager,routingManagerClient) + rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager,routingManagerClient, e2tAssociationManager) notificationManager := NewNotificationManager(logger, rmrNotificationHandlerProvider ) return logger, readerMock, notificationManager } diff --git a/E2Manager/managers/ran_reconnection_manager.go b/E2Manager/managers/ran_reconnection_manager.go index 7a1dab7..530131f 100644 --- a/E2Manager/managers/ran_reconnection_manager.go +++ b/E2Manager/managers/ran_reconnection_manager.go @@ -32,20 +32,20 @@ type IRanReconnectionManager interface { } type RanReconnectionManager struct { - logger *logger.Logger - config *configuration.Configuration - rnibDataService services.RNibDataService - ranSetupManager *RanSetupManager - e2tInstancesManager IE2TInstancesManager + 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, e2tInstancesManager IE2TInstancesManager) *RanReconnectionManager { +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, - e2tInstancesManager: e2tInstancesManager, + logger: logger, + config: config, + rnibDataService: rnibDataService, + ranSetupManager: ranSetupManager, + e2tAssociationManager: e2tAssociationManager, } } @@ -72,7 +72,7 @@ func (m *RanReconnectionManager) ReconnectRan(inventoryName string) error { } if m.isRanExceededConnectionAttempts(nodebInfo) { - return m.e2tInstancesManager.RemoveRanFromInstance(nodebInfo.RanName, e2tAddress) + return m.e2tAssociationManager.DissociateRan(e2tAddress, nodebInfo.RanName) } return nil diff --git a/E2Manager/managers/ran_reconnection_manager_test.go b/E2Manager/managers/ran_reconnection_manager_test.go index 44a3c78..e5e7ef3 100644 --- a/E2Manager/managers/ran_reconnection_manager_test.go +++ b/E2Manager/managers/ran_reconnection_manager_test.go @@ -21,6 +21,7 @@ package managers import ( + "e2mgr/clients" "e2mgr/configuration" "e2mgr/logger" "e2mgr/mocks" @@ -36,7 +37,7 @@ import ( "testing" ) -func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessengerMock, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *RanReconnectionManager) { +func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessengerMock, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *RanReconnectionManager, *mocks.HttpClientMock) { logger, err := logger.InitLogger(logger.DebugLevel) if err != nil { t.Errorf("#... - failed to initialize logger, error: %s", err) @@ -53,33 +54,15 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessenge rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock) e2tInstancesManager := NewE2TInstancesManager(rnibDataService, logger) ranSetupManager := NewRanSetupManager(logger, rmrSender, rnibDataService) - ranReconnectionManager := NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManager) - return logger, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager -} - -func initRanLostConnectionTestBasicMocks(t *testing.T) (*logger.Logger, *mocks.RmrMessengerMock, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *RanReconnectionManager, *mocks.E2TInstancesManagerMock) { - logger, err := logger.InitLogger(logger.DebugLevel) - if err != nil { - t.Errorf("#... - failed to initialize logger, error: %s", err) - } - 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) - e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{} - ranSetupManager := NewRanSetupManager(logger, rmrSender, rnibDataService) - ranReconnectionManager := NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManagerMock) - return logger, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager, e2tInstancesManagerMock + 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 } func TestRanReconnectionGetNodebFailure(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t) + _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) ranName := "test" var nodebInfo *entities.NodebInfo readerMock.On("GetNodeb", ranName).Return(nodebInfo, common.NewInternalError(errors.New("Error"))) @@ -90,7 +73,7 @@ func TestRanReconnectionGetNodebFailure(t *testing.T) { } func TestShutdownRanReconnection(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t) + _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) ranName := "test" origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN} var rnibErr error @@ -102,7 +85,7 @@ func TestShutdownRanReconnection(t *testing.T) { } func TestShuttingdownRanReconnection(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t) + _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) ranName := "test" origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN} var rnibErr error @@ -117,29 +100,29 @@ func TestShuttingdownRanReconnection(t *testing.T) { } func TestConnectingRanWithMaxAttemptsReconnectionDissociateSucceeds(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t) + _, _, readerMock, writerMock, ranReconnectionManager, httpClient:= initRanLostConnectionTest(t) ranName := "test" - e2tAddress := "10.0.2.15" - 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, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: E2TAddress} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) updatedNodebInfo := *origNodebInfo updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED updatedNodebInfo.AssociatedE2TInstanceAddress = "" writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(rnibErr) - e2tInstance := &entities.E2TInstance{Address:e2tAddress, AssociatedRanList:[]string{ranName}} - readerMock.On("GetE2TInstance",e2tAddress).Return(e2tInstance, nil) + 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, true) err := ranReconnectionManager.ReconnectRan(ranName) assert.Nil(t, err) readerMock.AssertCalled(t, "GetNodeb", ranName) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) } func TestConnectingRanWithMaxAttemptsReconnectionDissociateFails(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t) + _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) ranName := "test" e2tAddress := "10.0.2.15" origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: e2tAddress} @@ -154,12 +137,12 @@ func TestConnectingRanWithMaxAttemptsReconnectionDissociateFails(t *testing.T) { err := ranReconnectionManager.ReconnectRan(ranName) assert.NotNil(t, err) readerMock.AssertCalled(t, "GetNodeb", ranName) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) writerMock.AssertNotCalled(t, "SaveE2TInstance", ) } func TestUnconnectableRanUpdateNodebInfoFailure(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t) + _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) ranName := "test" origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN} var rnibErr error @@ -174,7 +157,7 @@ func TestUnconnectableRanUpdateNodebInfoFailure(t *testing.T) { } func TestConnectedRanExecuteSetupSuccess(t *testing.T) { - _, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t) + _, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) ranName := "test" 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 @@ -192,7 +175,7 @@ func TestConnectedRanExecuteSetupSuccess(t *testing.T) { } func TestConnectedRanExecuteSetupFailure(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t) + _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) ranName := "test" origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTED} var rnibErr error @@ -208,7 +191,7 @@ func TestConnectedRanExecuteSetupFailure(t *testing.T) { } func TestNoSetConnectionStatus(t *testing.T) { - _, _, _, _, ranReconnectionManager := initRanLostConnectionTest(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) diff --git a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go index b7002ad..3d79c28 100644 --- a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go +++ b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go @@ -58,7 +58,7 @@ func (provider *NotificationHandlerProvider) Register(msgType int, handler rmrms provider.notificationHandlers[msgType] = handler } -func (provider *NotificationHandlerProvider) Init(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, rmrSender *rmrsender.RmrSender, ranSetupManager *managers.RanSetupManager, e2tInstancesManager managers.IE2TInstancesManager, routingManagerClient clients.IRoutingManagerClient) { +func (provider *NotificationHandlerProvider) Init(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, rmrSender *rmrsender.RmrSender, ranSetupManager *managers.RanSetupManager, e2tInstancesManager managers.IE2TInstancesManager, routingManagerClient clients.IRoutingManagerClient, e2tAssociationManager *managers.E2TAssociationManager) { // Init converters x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger) @@ -69,7 +69,7 @@ func (provider *NotificationHandlerProvider) Init(logger *logger.Logger, config x2ResetResponseExtractor := converters.NewX2ResetResponseExtractor(logger) // Init managers - ranReconnectionManager := managers.NewRanReconnectionManager(logger, config, rnibDataService, ranSetupManager, e2tInstancesManager) + ranReconnectionManager := managers.NewRanReconnectionManager(logger, config, rnibDataService, ranSetupManager, e2tAssociationManager) ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender) x2SetupResponseManager := managers.NewX2SetupResponseManager(x2SetupResponseConverter) x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter) diff --git a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go index d01d7c4..5d20a5f 100644 --- a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go +++ b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go @@ -42,7 +42,7 @@ import ( * Verify support for known providers. */ -func initTestCase(t *testing.T) (*logger.Logger, *configuration.Configuration, services.RNibDataService, *rmrsender.RmrSender, *managers.RanSetupManager, managers.IE2TInstancesManager, clients.IRoutingManagerClient) { +func initTestCase(t *testing.T) (*logger.Logger, *configuration.Configuration, services.RNibDataService, *rmrsender.RmrSender, *managers.RanSetupManager, managers.IE2TInstancesManager, clients.IRoutingManagerClient, *managers.E2TAssociationManager) { logger := initLog(t) config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3} @@ -55,15 +55,16 @@ func initTestCase(t *testing.T) (*logger.Logger, *configuration.Configuration, s ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService) e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger) routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClient) + e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient) - return logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient + return logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient, e2tAssociationManager } func TestGetNotificationHandlerSuccess(t *testing.T) { - logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient := initTestCase(t) + logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient, e2tAssociationManager := initTestCase(t) - ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManager) + ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tAssociationManager) ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender) x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger) @@ -101,7 +102,7 @@ func TestGetNotificationHandlerSuccess(t *testing.T) { for _, tc := range testCases { provider := NewNotificationHandlerProvider() - provider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient) + provider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient, e2tAssociationManager) t.Run(fmt.Sprintf("%d", tc.msgType), func(t *testing.T) { handler, err := provider.GetNotificationHandler(tc.msgType) if err != nil { @@ -130,9 +131,9 @@ func TestGetNotificationHandlerFailure(t *testing.T) { } for _, tc := range testCases { - logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient := initTestCase(t) + logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient, e2tAssociationManager := initTestCase(t) provider := NewNotificationHandlerProvider() - provider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient) + provider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient, e2tAssociationManager) t.Run(fmt.Sprintf("%d", tc.msgType), func(t *testing.T) { _, err := provider.GetNotificationHandler(tc.msgType) if err == nil { diff --git a/E2Manager/services/rmrreceiver/rmr_receiver_test.go b/E2Manager/services/rmrreceiver/rmr_receiver_test.go index 5e766f7..b79c581 100644 --- a/E2Manager/services/rmrreceiver/rmr_receiver_test.go +++ b/E2Manager/services/rmrreceiver/rmr_receiver_test.go @@ -72,8 +72,9 @@ func initRmrReceiver(logger *logger.Logger) *RmrReceiver { ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService) e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger) routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClient) + e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient) rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider() - rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient) + rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager, routingManagerClient, e2tAssociationManager) notificationManager := notificationmanager.NewNotificationManager(logger, rmrNotificationHandlerProvider) return NewRmrReceiver(logger, rmrMessenger, notificationManager) } -- 2.16.6 From da07b41ecb97e56c25743729344052bda9ff5795 Mon Sep 17 00:00:00 2001 From: ss412g Date: Thu, 26 Dec 2019 14:37:06 +0200 Subject: [PATCH 03/16] update container version Change-Id: Ib99591a5c67e212672239e0c3d8fa616a0d478c4 Signed-off-by: ss412g --- E2Manager/container-tag.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/E2Manager/container-tag.yaml b/E2Manager/container-tag.yaml index d5f8e1e..f256535 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.3 +tag: 3.0.4 -- 2.16.6 From 63b5d926f439ca666378697ec81d893fc633dae5 Mon Sep 17 00:00:00 2001 From: Amichai Date: Thu, 26 Dec 2019 15:22:55 +0200 Subject: [PATCH 04/16] [RICPLT-2527] Add Automation and UTs Change-Id: I03d2047b3ddefbbd3fef518135076acba117443c Signed-off-by: Amichai --- Automation/Tests/Resource/Keywords.robot | 5 +- Automation/Tests/Resource/resource.robot | 3 +- .../Unhappy/Setup_Request_HttpResponse503.robot | 39 ++++++++++ .../httpmsghandlers/setup_request_handler_test.go | 22 ++++++ .../ran_lost_connection_handler_test.go | 88 +++++++++++++++++++++- .../managers/ran_reconnection_manager_test.go | 20 ++--- 6 files changed, 164 insertions(+), 13 deletions(-) create mode 100644 Automation/Tests/Unhappy/Setup_Request_HttpResponse503.robot diff --git a/Automation/Tests/Resource/Keywords.robot b/Automation/Tests/Resource/Keywords.robot index e2e622f..0f24653 100644 --- a/Automation/Tests/Resource/Keywords.robot +++ b/Automation/Tests/Resource/Keywords.robot @@ -83,7 +83,6 @@ Stop Simulator Run And Return Rc And Output ${stop_simu} - Prepare Simulator For Load Information Run And Return Rc And Output ${stop_simu} Run And Return Rc And Output ${docker_Remove} @@ -166,7 +165,11 @@ Restart simulator ${result}= Run And Return Rc And Output ${docker_command} Should Be Equal As Integers ${result[1]} ${docker_number} +Start RoutingManager Simulator + Run And Return Rc And Output ${start_routingmanager_sim} +Stop RoutingManager Simulator + Run And Return Rc And Output ${stop_routingmanager_sim} diff --git a/Automation/Tests/Resource/resource.robot b/Automation/Tests/Resource/resource.robot index 90c79b2..c37ebaa 100644 --- a/Automation/Tests/Resource/resource.robot +++ b/Automation/Tests/Resource/resource.robot @@ -64,7 +64,8 @@ ${stop_docker_e2} docker stop e2 ${restart_docker_sim} docker restart gnbe2_simu ${Run_Config} docker exec gnbe2_simu pkill gnbe2_simu -INT ${403_reset_message} "Activity X2_RESET rejected. RAN current state DISCONNECTED does not allow its execution " - +${stop_routingmanager_sim} docker stop rm_sim +${start_routingmanager_sim} docker start rm_sim diff --git a/Automation/Tests/Unhappy/Setup_Request_HttpResponse503.robot b/Automation/Tests/Unhappy/Setup_Request_HttpResponse503.robot new file mode 100644 index 0000000..9fe7071 --- /dev/null +++ b/Automation/Tests/Unhappy/Setup_Request_HttpResponse503.robot @@ -0,0 +1,39 @@ +############################################################################## +# +# Copyright (c) 2019 AT&T Intellectual Property. +# +# 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). +# + +*** Settings *** +Suite Setup Prepare Enviorment +Resource ../Resource/Keywords.robot +Resource ../Resource/resource.robot +Library REST ${url} +Suite Teardown Start RoutingManager Simulator + +*** Test Cases *** +ENDC-setup - 500 http - 500 RNIB error + Stop RoutingManager Simulator + Set Headers ${header} + POST /v1/nodeb/x2-setup ${json} + Integer response status 503 + Integer response body errorCode 511 + String response body errorMessage No Routing Manager Available + + diff --git a/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go b/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go index 7586791..e8a6736 100644 --- a/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go +++ b/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go @@ -416,3 +416,25 @@ func TestSetupExistingRanWithAssocE2TInstanceConnectedSuccess(t *testing.T) { e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance") e2tInstancesManagerMock.AssertNotCalled(t, "AddRanToInstance") } + +func TestSetupExistingRanWithoutAssocE2TInstanceExecuteRoutingManagerError(t *testing.T) { + readerMock, writerMock, handler, _, httpClientMock := initSetupRequestTestBasicMocks(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST) + nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST} + readerMock.On("GetNodeb", RanName).Return(nb, nil) + addresses := []string{E2TAddress} + readerMock.On("GetE2TAddresses").Return(addresses, nil) + e2tInstance := &entities.E2TInstance{Address: E2TAddress, State: entities.Active} + readerMock.On("GetE2TInstances", addresses).Return([]*entities.E2TInstance{e2tInstance}, nil) + + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)} + marshaled, _ := json.Marshal(data) + body := bytes.NewBuffer(marshaled) + respBody := ioutil.NopCloser(bytes.NewBufferString("")) + httpClientMock.On("Post", clients.AssociateRanToE2TInstanceApiSuffix, "application/json", body).Return(&http.Response{StatusCode: http.StatusBadRequest, Body: respBody}, nil) + + _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,}) + assert.IsType(t, &e2managererrors.RoutingManagerError{}, err) + writerMock.AssertExpectations(t) + readerMock.AssertExpectations(t) + httpClientMock.AssertExpectations(t) +} diff --git a/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go b/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go index 60755ab..1220c79 100644 --- a/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go +++ b/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go @@ -19,16 +19,28 @@ package rmrmsghandlers import ( + "bytes" + "e2mgr/clients" + "e2mgr/configuration" "e2mgr/logger" + "e2mgr/managers" "e2mgr/mocks" "e2mgr/models" + "e2mgr/services" + "encoding/json" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" "github.com/pkg/errors" + "io/ioutil" + "net/http" "testing" ) +const ranName = "test" +const e2tAddress = "10.10.2.15:9800" + func TestLostConnectionHandlerSuccess(t *testing.T) { logger, _ := logger.InitLogger(logger.InfoLevel) - ranName := "test" + notificationRequest := models.NotificationRequest{RanName: ranName} ranReconnectionManagerMock := &mocks.RanReconnectionManagerMock{} ranReconnectionManagerMock.On("ReconnectRan", ranName).Return(nil) @@ -39,7 +51,7 @@ func TestLostConnectionHandlerSuccess(t *testing.T) { func TestLostConnectionHandlerFailure(t *testing.T) { logger, _ := logger.InitLogger(logger.InfoLevel) - ranName := "test" + notificationRequest := models.NotificationRequest{RanName: ranName} ranReconnectionManagerMock := &mocks.RanReconnectionManagerMock{} ranReconnectionManagerMock.On("ReconnectRan", ranName).Return(errors.New("error")) @@ -47,3 +59,75 @@ func TestLostConnectionHandlerFailure(t *testing.T) { handler.Handle(¬ificationRequest) ranReconnectionManagerMock.AssertCalled(t, "ReconnectRan", ranName) } + +func setupLostConnectionHandlerTestWithRealReconnectionManager(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) + + origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: e2tAddress} + var rnibErr error + readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + updatedNodebInfo.AssociatedE2TInstanceAddress = "" + writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(rnibErr) + 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(httpClientMock, isSuccessfulHttpPost) + + return handler, readerMock, writerMock, httpClientMock +} + +func mockHttpClient(httpClientMock *mocks.HttpClientMock, isSuccessful bool) { + data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(e2tAddress, RanName)} + marshaled, _ := json.Marshal(data) + body := bytes.NewBuffer(marshaled) + respBody := ioutil.NopCloser(bytes.NewBufferString("")) + var respStatusCode int + if isSuccessful { + respStatusCode = http.StatusCreated + } else { + respStatusCode = http.StatusBadRequest + } + 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) + + notificationRequest := models.NotificationRequest{RanName: ranName} + handler.Handle(¬ificationRequest) + + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + httpClientMock.AssertExpectations(t) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) +} + +func TestLostConnectionHandlerSuccessWithRealReconnectionManager(t *testing.T) { + handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTestWithRealReconnectionManager(t, true) + + notificationRequest := models.NotificationRequest{RanName: ranName} + handler.Handle(¬ificationRequest) + + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + httpClientMock.AssertExpectations(t) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) +} diff --git a/E2Manager/managers/ran_reconnection_manager_test.go b/E2Manager/managers/ran_reconnection_manager_test.go index e5e7ef3..c4c30d6 100644 --- a/E2Manager/managers/ran_reconnection_manager_test.go +++ b/E2Manager/managers/ran_reconnection_manager_test.go @@ -37,6 +37,9 @@ import ( "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) { logger, err := logger.InitLogger(logger.DebugLevel) if err != nil { @@ -63,7 +66,7 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessenge func TestRanReconnectionGetNodebFailure(t *testing.T) { _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) - ranName := "test" + var nodebInfo *entities.NodebInfo readerMock.On("GetNodeb", ranName).Return(nodebInfo, common.NewInternalError(errors.New("Error"))) err := ranReconnectionManager.ReconnectRan(ranName) @@ -74,7 +77,7 @@ func TestRanReconnectionGetNodebFailure(t *testing.T) { func TestShutdownRanReconnection(t *testing.T) { _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) - ranName := "test" + 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) @@ -86,7 +89,7 @@ func TestShutdownRanReconnection(t *testing.T) { func TestShuttingdownRanReconnection(t *testing.T) { _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) - ranName := "test" + 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) @@ -101,7 +104,7 @@ func TestShuttingdownRanReconnection(t *testing.T) { func TestConnectingRanWithMaxAttemptsReconnectionDissociateSucceeds(t *testing.T) { _, _, readerMock, writerMock, ranReconnectionManager, httpClient:= initRanLostConnectionTest(t) - ranName := "test" + origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: E2TAddress} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) @@ -123,8 +126,7 @@ func TestConnectingRanWithMaxAttemptsReconnectionDissociateSucceeds(t *testing.T func TestConnectingRanWithMaxAttemptsReconnectionDissociateFails(t *testing.T) { _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) - ranName := "test" - e2tAddress := "10.0.2.15" + origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: e2tAddress} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) @@ -143,7 +145,7 @@ func TestConnectingRanWithMaxAttemptsReconnectionDissociateFails(t *testing.T) { func TestUnconnectableRanUpdateNodebInfoFailure(t *testing.T) { _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) - ranName := "test" + 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) @@ -158,7 +160,7 @@ func TestUnconnectableRanUpdateNodebInfoFailure(t *testing.T) { func TestConnectedRanExecuteSetupSuccess(t *testing.T) { _, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) - ranName := "test" + 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) @@ -176,7 +178,7 @@ func TestConnectedRanExecuteSetupSuccess(t *testing.T) { func TestConnectedRanExecuteSetupFailure(t *testing.T) { _, _, readerMock, writerMock, ranReconnectionManager, _ := initRanLostConnectionTest(t) - ranName := "test" + origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTED} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) -- 2.16.6 From 82900215c065938d70f2c2ad8c2abefe5c897fc7 Mon Sep 17 00:00:00 2001 From: Irina Date: Sun, 29 Dec 2019 15:33:09 +0200 Subject: [PATCH 05/16] RICPLT-2727 - E2 Initialized (Routing Manager) - UT Change-Id: I2163238f962741be7d8efa05610a10b1ef2235c7 Signed-off-by: Irina --- .../e2_term_init_notification_handler_test.go | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) 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 c930b0e..9ca2452 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go @@ -270,13 +270,11 @@ func TestE2TermInitHandlerSuccessTwoRans_RoutingManagerFailure(t *testing.T) { _, _, handler, readerMock, writerMock, rmrMessengerMock, httpClientMock:= initRanLostConnectionTestWithRealE2tInstanceManager(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_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} + 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) - - var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) + writerMock.On("UpdateNodebInfo", mock.Anything).Return(rnibErr) payload := e2pdus.PackedX2setupRequest xaction := []byte(RanName) @@ -335,15 +333,13 @@ func TestE2TermInitHandlerSuccessOneRan_RoutingManagerFailure_Error(t *testing.T } func TestE2TermInitHandlerSuccessTwoRans(t *testing.T) { - _, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, httpClientMock := initRanLostConnectionTest(t) + _, _, handler, readerMock, writerMock, rmrMessengerMock, httpClientMock:= initRanLostConnectionTestWithRealE2tInstanceManager(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_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} + 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) - - var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) + writerMock.On("UpdateNodebInfo", mock.Anything).Return(rnibErr) payload := e2pdus.PackedX2setupRequest xaction := []byte(RanName) @@ -353,7 +349,7 @@ func TestE2TermInitHandlerSuccessTwoRans(t *testing.T) { e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName, "test2") - e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) + readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} handler.Handle(notificationRequest) -- 2.16.6 From 28b8f5bdd1fa64dbb69a1fd7e8c132eb28e32cfa Mon Sep 17 00:00:00 2001 From: is005q Date: Sun, 29 Dec 2019 15:49:53 +0200 Subject: [PATCH 06/16] [RICPLT-2787] Complete automation tests for US Change-Id: I055e0efbf1c3bc29d6e776c5bdbc136700f35760 Signed-off-by: is005q --- .../Get_E2T_Instances/get_e2t_instances.robot | 18 ++++-------- Automation/Tests/Scripts/e2mdbscripts.py | 7 +++++ .../Tests/Unhappy/Get_E2T_Instances_DB_Error.robot | 32 ---------------------- 3 files changed, 13 insertions(+), 44 deletions(-) delete mode 100644 Automation/Tests/Unhappy/Get_E2T_Instances_DB_Error.robot diff --git a/Automation/Tests/Get_E2T_Instances/get_e2t_instances.robot b/Automation/Tests/Get_E2T_Instances/get_e2t_instances.robot index dbafcfc..09bc6ca 100644 --- a/Automation/Tests/Get_E2T_Instances/get_e2t_instances.robot +++ b/Automation/Tests/Get_E2T_Instances/get_e2t_instances.robot @@ -20,31 +20,25 @@ Suite Setup Prepare Enviorment Resource ../Resource/Keywords.robot Resource ../Resource/resource.robot +Resource ../Resource/scripts_variables.robot Library REST ${url} Library RequestsLibrary Library Collections Library OperatingSystem Library json +Library ../Scripts/e2mdbscripts.py *** Test Cases *** -Get E2T instances 1st call +Get E2T instances + ${result} e2mdbscripts.populate_e2t_instances_in_e2m_db_for_get_e2t_instances_tc Create Session getE2tInstances ${url} ${headers}= Create Dictionary Accept=application/json ${resp}= Get Request getE2tInstances /v1/e2t/list headers=${headers} Should Be Equal As Strings ${resp.status_code} 200 - Should Be Equal As Strings ${resp.content} [{"e2tAddress":"e2t.att.com:38000","ranNames":[]}] - -Get E2T instances after one setup - - Post Request setup node b x-2 - Integer response status 204 - Create Session getE2tInstances ${url} - ${headers}= Create Dictionary Accept=application/json - ${resp}= Get Request getE2tInstances /v1/e2t/list headers=${headers} - Should Be Equal As Strings ${resp.status_code} 200 - Should Be Equal As Strings ${resp.content} [{\"e2tAddress\":\"e2t.att.com:38000\",\"ranNames\":[\"test1\"]}] + Should Be Equal As Strings ${resp.content} [{"e2tAddress":"e2t.att.com:38000","ranNames":["test1","test2","test3"]},{"e2tAddress":"e2t.att.com:38001","ranNames":[]}] + ${flush} cleanup_db.flush diff --git a/Automation/Tests/Scripts/e2mdbscripts.py b/Automation/Tests/Scripts/e2mdbscripts.py index 7b9475b..6753f80 100644 --- a/Automation/Tests/Scripts/e2mdbscripts.py +++ b/Automation/Tests/Scripts/e2mdbscripts.py @@ -33,6 +33,13 @@ def verify_ran_is_associated_with_e2t_instance(ranName, e2tAddress): assocRanList = e2tInstanceDic.get("associatedRanList") return ranName in assocRanList +def populate_e2t_instances_in_e2m_db_for_get_e2t_instances_tc(): + r = getRedisClientDecodeResponse() + r.set("{e2Manager},E2TAddresses", "[\"e2t.att.com:38000\",\"e2t.att.com:38001\"]") + r.set("{e2Manager},E2TInstance:e2t.att.com:38000", "{\"address\":\"e2t.att.com:38000\",\"associatedRanList\":[\"test1\",\"test2\",\"test3\"],\"keepAliveTimestamp\":1577619310484022369,\"state\":\"ACTIVE\"}") + r.set("{e2Manager},E2TInstance:e2t.att.com:38001", "{\"address\":\"e2t.att.com:38001\",\"associatedRanList\":[],\"keepAliveTimestamp\":1577619310484022369,\"state\":\"ACTIVE\"}") + return True + # def dissociate_ran_from_e2tInstance(ranName, e2tAddress): # r = getRedisClientDecodeResponse() # e2tInstanceJson = r.get("{e2Manager},E2TInstance:"+e2tAddress) diff --git a/Automation/Tests/Unhappy/Get_E2T_Instances_DB_Error.robot b/Automation/Tests/Unhappy/Get_E2T_Instances_DB_Error.robot deleted file mode 100644 index 9ab940f..0000000 --- a/Automation/Tests/Unhappy/Get_E2T_Instances_DB_Error.robot +++ /dev/null @@ -1,32 +0,0 @@ -############################################################################## -# -# Copyright (c) 2019 AT&T Intellectual Property. -# -# 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. -# -############################################################################## - -*** Settings *** -Suite Setup Prepare Enviorment -Resource ../Resource/Keywords.robot -Resource ../Resource/resource.robot -Library REST ${url} -Suite Teardown Start Dbass - -*** Test Cases *** -Get All E2T Instances DB Error - 500 - Stop Dbass - GET /v1/e2t/list - Integer response status 500 - Integer response body errorCode 500 - String response body errorMessage RNIB error \ No newline at end of file -- 2.16.6 From 1f62f4c6e2746153275b6c3b1e24a705e25b90c0 Mon Sep 17 00:00:00 2001 From: Amichai Date: Sun, 29 Dec 2019 17:48:44 +0200 Subject: [PATCH 07/16] [RICPLT-2527] Fix according to acceptance comments Change-Id: I7b791a984e4cdc0d8db4d243c970038f6d75bd01 Signed-off-by: Amichai --- .../Unhappy/Setup_Request_HttpResponse503.robot | 7 +++- E2Manager/clients/routing_manager_client.go | 6 +-- .../httpmsghandlers/setup_request_handler.go | 8 ++-- .../httpmsghandlers/setup_request_handler_test.go | 48 +++++++++++++++------- .../ran_lost_connection_handler_test.go | 11 +++-- E2Manager/managers/e2t_association_manager.go | 13 ++---- E2Manager/managers/e2t_association_manager_test.go | 30 +++----------- E2Manager/managers/ran_reconnection_manager.go | 10 ++--- .../managers/ran_reconnection_manager_test.go | 22 ++++++---- 9 files changed, 79 insertions(+), 76 deletions(-) diff --git a/Automation/Tests/Unhappy/Setup_Request_HttpResponse503.robot b/Automation/Tests/Unhappy/Setup_Request_HttpResponse503.robot index 9fe7071..0e7e9c4 100644 --- a/Automation/Tests/Unhappy/Setup_Request_HttpResponse503.robot +++ b/Automation/Tests/Unhappy/Setup_Request_HttpResponse503.robot @@ -24,11 +24,12 @@ Suite Setup Prepare Enviorment Resource ../Resource/Keywords.robot Resource ../Resource/resource.robot +Library ../Scripts/e2mdbscripts.py Library REST ${url} Suite Teardown Start RoutingManager Simulator *** Test Cases *** -ENDC-setup - 500 http - 500 RNIB error +ENDC-setup - 503 http - 511 No Routing Manager Available Stop RoutingManager Simulator Set Headers ${header} POST /v1/nodeb/x2-setup ${json} @@ -36,4 +37,6 @@ ENDC-setup - 500 http - 500 RNIB error Integer response body errorCode 511 String response body errorMessage No Routing Manager Available - +Verify RAN is NOT associated with E2T instance + ${result} e2mdbscripts.verify_ran_is_associated_with_e2t_instance test1 e2t.att.com:38000 + Should Be True ${result} == False diff --git a/E2Manager/clients/routing_manager_client.go b/E2Manager/clients/routing_manager_client.go index 52e9250..5257d04 100644 --- a/E2Manager/clients/routing_manager_client.go +++ b/E2Manager/clients/routing_manager_client.go @@ -95,7 +95,7 @@ func (c *RoutingManagerClient) PostMessage(data interface{}, url string) error { } body := bytes.NewBuffer(marshaled) - c.logger.Infof("[E2M -> Routing Manager] #RoutingManagerClient.PostMessage - url: %s, request body: %+v", url, body) + c.logger.Infof("[E2 Manager -> Routing Manager] #RoutingManagerClient.PostMessage - url: %s, request body: %+v", url, body) resp, err := c.httpClient.Post(url, "application/json", body) @@ -107,11 +107,11 @@ func (c *RoutingManagerClient) PostMessage(data interface{}, url string) error { defer resp.Body.Close() if resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices { - c.logger.Infof("[Routing Manager -> E2M] #RoutingManagerClient.PostMessage - success. http status code: %d", resp.StatusCode) + c.logger.Infof("[Routing Manager -> E2 Manager] #RoutingManagerClient.PostMessage - success. http status code: %d", resp.StatusCode) return nil } - c.logger.Errorf("[Routing Manager -> E2M] #RoutingManagerClient.PostMessage - failure. http status code: %d", resp.StatusCode) + c.logger.Errorf("[Routing Manager -> E2 Manager] #RoutingManagerClient.PostMessage - failure. http status code: %d", resp.StatusCode) return e2managererrors.NewRoutingManagerError() } diff --git a/E2Manager/handlers/httpmsghandlers/setup_request_handler.go b/E2Manager/handlers/httpmsghandlers/setup_request_handler.go index c5ce648..51e579b 100644 --- a/E2Manager/handlers/httpmsghandlers/setup_request_handler.go +++ b/E2Manager/handlers/httpmsghandlers/setup_request_handler.go @@ -94,7 +94,7 @@ func (h *SetupRequestHandler) Handle(request models.Request) (models.IResponse, return nil, result } -func createInitialNodeInfo(requestDetails *models.SetupRequest, protocol entities.E2ApplicationProtocol, e2tAddress string) (*entities.NodebInfo, *entities.NbIdentity) { +func createInitialNodeInfo(requestDetails *models.SetupRequest, protocol entities.E2ApplicationProtocol) (*entities.NodebInfo, *entities.NbIdentity) { nodebInfo := &entities.NodebInfo{ Ip: requestDetails.RanIp, @@ -133,7 +133,7 @@ func (h *SetupRequestHandler) connectExistingRanWithoutAssociatedE2TAddress(node return err } - err = h.e2tAssociationManager.AssociateRan(e2tAddress, nodebInfo.RanName) + err = h.e2tAssociationManager.AssociateRan(e2tAddress, nodebInfo) if err != nil { h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - failed associating ran to e2t address %s. error: %s", nodebInfo.RanName, e2tAddress, err) @@ -174,7 +174,7 @@ func (h *SetupRequestHandler) connectNewRan(request *models.SetupRequest, protoc return err } - nodebInfo, nodebIdentity := createInitialNodeInfo(request, protocol, e2tAddress) + nodebInfo, nodebIdentity := createInitialNodeInfo(request, protocol) err = h.rNibDataService.SaveNodeb(nodebIdentity, nodebInfo) @@ -185,7 +185,7 @@ func (h *SetupRequestHandler) connectNewRan(request *models.SetupRequest, protoc h.logger.Infof("#SetupRequestHandler.connectNewRan - RAN name: %s - initial nodeb entity was saved to rNib", request.RanName) - err = h.e2tAssociationManager.AssociateRan(e2tAddress, request.RanName) + err = h.e2tAssociationManager.AssociateRan(e2tAddress, nodebInfo) if err != nil { h.logger.Errorf("#SetupRequestHandler.connectNewRan - RAN name: %s - failed associating ran to e2t address %s. error: %s", request.RanName, e2tAddress, err) diff --git a/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go b/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go index e8a6736..b27b54e 100644 --- a/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go +++ b/E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go @@ -169,10 +169,15 @@ func TestSetupNewRanAssociateRanFailure(t *testing.T) { readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, httpClientMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST) readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError("")) e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil) - nbIdentity := &entities.NbIdentity{InventoryName: RanName} + e2tInstancesManagerMock.On("AddRanToInstance", RanName, E2TAddress).Return(e2managererrors.NewRnibDbError()) + setupRequest := &models.SetupRequest{"127.0.0.1", 8080, RanName,} + nb, nbIdentity := createInitialNodeInfo(setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST) writerMock.On("SaveNodeb", nbIdentity, mock.Anything).Return(nil) - _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,}) - assert.IsType(t, &common.ResourceNotFoundError{}, err) + nb.AssociatedE2TInstanceAddress = E2TAddress + nb.ConnectionAttempts = 0 + writerMock.On("UpdateNodebInfo", nb).Return(nil) + _, err := handler.Handle(*setupRequest) + assert.IsType(t, &e2managererrors.RnibDbError{}, err) writerMock.AssertExpectations(t) readerMock.AssertExpectations(t) e2tInstancesManagerMock.AssertExpectations(t) @@ -186,7 +191,7 @@ func TestSetupNewRanSaveNodebFailure(t *testing.T) { e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil) e2tInstancesManagerMock.On("AddRanToInstance", RanName, E2TAddress).Return(nil) setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,} - nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, E2TAddress) + nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST) writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(common.NewInternalError(fmt.Errorf(""))) _, err := handler.Handle(setupRequest) assert.IsType(t, &e2managererrors.RnibDbError{}, err) @@ -197,13 +202,19 @@ func TestSetupNewRanSetupDbError(t *testing.T) { readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST) readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError("")) e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil) - e2tInstancesManagerMock.On("AddRanToInstance", RanName, E2TAddress).Return(nil) + e2tInstancesManagerMock.On("AddRanToInstance", RanName, E2TAddress).Return(e2managererrors.NewRnibDbError()) setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,} - nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, E2TAddress) + nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST) writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil) - ranSetupManagerMock.On("ExecuteSetup", nodebInfo, entities.ConnectionStatus_CONNECTING).Return(e2managererrors.NewRnibDbError()) + updatedNb := *nodebInfo + updatedNb.ConnectionAttempts = 0 + updatedNb.AssociatedE2TInstanceAddress = E2TAddress + writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil) _, err := handler.Handle(setupRequest) - assert.IsType(t, &common.ResourceNotFoundError{}, err) + assert.IsType(t, &e2managererrors.RnibDbError{}, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + ranSetupManagerMock.AssertExpectations(t) } func TestSetupNewRanSetupRmrError(t *testing.T) { @@ -212,11 +223,15 @@ func TestSetupNewRanSetupRmrError(t *testing.T) { e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil) e2tInstancesManagerMock.On("AddRanToInstance", RanName, E2TAddress).Return(nil) setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,} - nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, E2TAddress) + nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST) writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil) - ranSetupManagerMock.On("ExecuteSetup", nodebInfo, entities.ConnectionStatus_CONNECTING).Return(e2managererrors.NewRmrError()) + updatedNb := *nodebInfo + updatedNb.ConnectionAttempts = 0 + updatedNb.AssociatedE2TInstanceAddress = E2TAddress + writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil) + ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(e2managererrors.NewRmrError()) _, err := handler.Handle(setupRequest) - assert.IsType(t, /* &e2managererrors.RmrError{} */ &common.ResourceNotFoundError{}, err) + assert.IsType(t, &e2managererrors.RmrError{}, err) } func TestSetupNewRanSetupSuccess(t *testing.T) { @@ -225,12 +240,15 @@ func TestSetupNewRanSetupSuccess(t *testing.T) { e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil) e2tInstancesManagerMock.On("AddRanToInstance", RanName, E2TAddress).Return(nil) setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,} - nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, E2TAddress) + nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST) writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil) - ranSetupManagerMock.On("ExecuteSetup", nodebInfo, entities.ConnectionStatus_CONNECTING).Return(nil) + updatedNb := *nodebInfo + updatedNb.ConnectionAttempts = 0 + updatedNb.AssociatedE2TInstanceAddress = E2TAddress + writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil) + ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(nil) _, err := handler.Handle(setupRequest) - //assert.Nil(t, err) - assert.IsType(t, /* &e2managererrors.RnibDbError{} */ &common.ResourceNotFoundError{}, err) + assert.Nil(t, err) } func TestX2SetupExistingRanShuttingDown(t *testing.T) { diff --git a/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go b/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go index 1220c79..836c02a 100644 --- a/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go +++ b/E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go @@ -80,10 +80,13 @@ func setupLostConnectionHandlerTestWithRealReconnectionManager(t *testing.T, isS origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: e2tAddress} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) - updatedNodebInfo := *origNodebInfo - updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED - updatedNodebInfo.AssociatedE2TInstanceAddress = "" - writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(rnibErr) + 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, nil) e2tInstanceToSave := *e2tInstance diff --git a/E2Manager/managers/e2t_association_manager.go b/E2Manager/managers/e2t_association_manager.go index 78ae6d7..e313c19 100644 --- a/E2Manager/managers/e2t_association_manager.go +++ b/E2Manager/managers/e2t_association_manager.go @@ -23,6 +23,7 @@ import ( "e2mgr/clients" "e2mgr/logger" "e2mgr/services" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" ) type E2TAssociationManager struct { @@ -41,7 +42,8 @@ func NewE2TAssociationManager(logger *logger.Logger, rnibDataService services.RN } } -func (m *E2TAssociationManager) AssociateRan(e2tAddress string, ranName string) error { +func (m *E2TAssociationManager) AssociateRan(e2tAddress string, nodebInfo *entities.NodebInfo) error { + ranName := nodebInfo.RanName m.logger.Infof("#E2TAssociationManager.AssociateRan - Associating RAN %s to E2T Instance address: %s", ranName, e2tAddress) err := m.rmClient.AssociateRanToE2TInstance(e2tAddress, ranName) @@ -50,16 +52,9 @@ func (m *E2TAssociationManager) AssociateRan(e2tAddress string, ranName string) return err } - nodebInfo, rnibErr := m.rnibDataService.GetNodeb(ranName) - - if rnibErr != nil { - m.logger.Errorf("#E2TAssociationManager.AssociateRan - RAN name: %s - Failed fetching RAN from rNib. Error: %s", ranName, rnibErr) - return rnibErr - } - nodebInfo.AssociatedE2TInstanceAddress = e2tAddress nodebInfo.ConnectionAttempts = 0 - rnibErr = m.rnibDataService.UpdateNodebInfo(nodebInfo) + rnibErr := m.rnibDataService.UpdateNodebInfo(nodebInfo) if rnibErr != nil { m.logger.Errorf("#E2TAssociationManager.AssociateRan - RAN name: %s - Failed to update RAN.AssociatedE2TInstanceAddress in rNib. Error: %s", ranName, rnibErr) return rnibErr diff --git a/E2Manager/managers/e2t_association_manager_test.go b/E2Manager/managers/e2t_association_manager_test.go index cdaed68..fa13848 100644 --- a/E2Manager/managers/e2t_association_manager_test.go +++ b/E2Manager/managers/e2t_association_manager_test.go @@ -72,7 +72,6 @@ func TestAssociateRanSuccess(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1} - readerMock.On("GetNodeb", RanName).Return(nb, nil) updatedNb := *nb updatedNb.ConnectionAttempts = 0 updatedNb.AssociatedE2TInstanceAddress = E2TAddress @@ -83,7 +82,7 @@ func TestAssociateRanSuccess(t *testing.T) { updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName) writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil) - err := manager.AssociateRan(E2TAddress, RanName) + err := manager.AssociateRan(E2TAddress, nb) assert.Nil(t, err) readerMock.AssertExpectations(t) @@ -95,7 +94,8 @@ func TestAssociateRanRoutingManagerError(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, false) - err := manager.AssociateRan(E2TAddress, RanName) + nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1} + err := manager.AssociateRan(E2TAddress, nb) assert.NotNil(t, err) assert.IsType(t, &e2managererrors.RoutingManagerError{}, err) @@ -104,32 +104,16 @@ func TestAssociateRanRoutingManagerError(t *testing.T) { httpClientMock.AssertExpectations(t) } -func TestAssociateRanGetNodebError(t *testing.T) { - manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) - mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) - var nb *entities.NodebInfo - readerMock.On("GetNodeb", RanName).Return(nb, e2managererrors.NewRnibDbError()) - - err := manager.AssociateRan(E2TAddress, RanName) - - assert.NotNil(t, err) - assert.IsType(t, &e2managererrors.RnibDbError{}, err) - readerMock.AssertExpectations(t) - writerMock.AssertExpectations(t) - httpClientMock.AssertExpectations(t) -} - func TestAssociateRanUpdateNodebError(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1} - readerMock.On("GetNodeb", RanName).Return(nb, nil) updatedNb := *nb updatedNb.ConnectionAttempts = 0 updatedNb.AssociatedE2TInstanceAddress = E2TAddress writerMock.On("UpdateNodebInfo", &updatedNb).Return(e2managererrors.NewRnibDbError()) - err := manager.AssociateRan(E2TAddress, RanName) + err := manager.AssociateRan(E2TAddress, nb) assert.NotNil(t, err) assert.IsType(t, &e2managererrors.RnibDbError{}, err) @@ -142,7 +126,6 @@ func TestAssociateRanGetE2tInstanceError(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1} - readerMock.On("GetNodeb", RanName).Return(nb, nil) updatedNb := *nb updatedNb.ConnectionAttempts = 0 updatedNb.AssociatedE2TInstanceAddress = E2TAddress @@ -150,7 +133,7 @@ func TestAssociateRanGetE2tInstanceError(t *testing.T) { var e2tInstance *entities.E2TInstance readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test")) - err := manager.AssociateRan(E2TAddress, RanName) + err := manager.AssociateRan(E2TAddress, nb) assert.NotNil(t, err) assert.IsType(t, &e2managererrors.RnibDbError{}, err) @@ -163,7 +146,6 @@ func TestAssociateRanSaveE2tInstanceError(t *testing.T) { manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1} - readerMock.On("GetNodeb", RanName).Return(nb, nil) updatedNb := *nb updatedNb.ConnectionAttempts = 0 updatedNb.AssociatedE2TInstanceAddress = E2TAddress @@ -174,7 +156,7 @@ func TestAssociateRanSaveE2tInstanceError(t *testing.T) { updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName) writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test")) - err := manager.AssociateRan(E2TAddress, RanName) + err := manager.AssociateRan(E2TAddress, nb) assert.NotNil(t, err) assert.IsType(t, &e2managererrors.RnibDbError{}, err) diff --git a/E2Manager/managers/ran_reconnection_manager.go b/E2Manager/managers/ran_reconnection_manager.go index 530131f..b733142 100644 --- a/E2Manager/managers/ran_reconnection_manager.go +++ b/E2Manager/managers/ran_reconnection_manager.go @@ -94,14 +94,10 @@ func (m *RanReconnectionManager) canReconnectRan(nodebInfo *entities.NodebInfo) int(nodebInfo.GetConnectionAttempts()) < m.config.MaxConnectionAttempts } -func (m *RanReconnectionManager) updateNodebInfo(nodebInfo *entities.NodebInfo, connectionStatus entities.ConnectionStatus, resetE2tAddress bool) error { +func (m *RanReconnectionManager) updateNodebInfo(nodebInfo *entities.NodebInfo, connectionStatus entities.ConnectionStatus) error { nodebInfo.ConnectionStatus = connectionStatus; - if resetE2tAddress { - nodebInfo.AssociatedE2TInstanceAddress = "" - } - err := m.rnibDataService.UpdateNodebInfo(nodebInfo) if err != nil { @@ -123,12 +119,12 @@ func (m *RanReconnectionManager) updateUnconnectableRan(nodebInfo *entities.Node 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, false) + 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, true) + return m.updateNodebInfo(nodebInfo, entities.ConnectionStatus_DISCONNECTED) } return nil diff --git a/E2Manager/managers/ran_reconnection_manager_test.go b/E2Manager/managers/ran_reconnection_manager_test.go index c4c30d6..7927d0c 100644 --- a/E2Manager/managers/ran_reconnection_manager_test.go +++ b/E2Manager/managers/ran_reconnection_manager_test.go @@ -108,10 +108,13 @@ func TestConnectingRanWithMaxAttemptsReconnectionDissociateSucceeds(t *testing.T origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: E2TAddress} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) - updatedNodebInfo := *origNodebInfo - updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED - updatedNodebInfo.AssociatedE2TInstanceAddress = "" - writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(rnibErr) + 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, nil) e2tInstanceToSave := * e2tInstance @@ -130,10 +133,13 @@ func TestConnectingRanWithMaxAttemptsReconnectionDissociateFails(t *testing.T) { origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20, AssociatedE2TInstanceAddress: e2tAddress} var rnibErr error readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr) - updatedNodebInfo := *origNodebInfo - updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED - updatedNodebInfo.AssociatedE2TInstanceAddress = "" - writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(rnibErr) + 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 := ranReconnectionManager.ReconnectRan(ranName) -- 2.16.6 From 07196e9385aa8e1f47796d3eac24385c5817f46d Mon Sep 17 00:00:00 2001 From: is005q Date: Mon, 30 Dec 2019 14:04:50 +0200 Subject: [PATCH 08/16] Update RoutingManagerSimulator according to latest RM Swagger Change-Id: If4308ae55068b9575315c6bf224fcc579cbc5790 Signed-off-by: is005q --- E2Manager/resources/configuration.yaml | 2 +- tools/RoutingManagerSimulator/api/swagger.yaml | 6 +++--- tools/RoutingManagerSimulator/go/README.md | 25 +++++++++++++++++++++++++ tools/RoutingManagerSimulator/go/routers.go | 8 ++++---- 4 files changed, 33 insertions(+), 8 deletions(-) create mode 100755 tools/RoutingManagerSimulator/go/README.md diff --git a/E2Manager/resources/configuration.yaml b/E2Manager/resources/configuration.yaml index f10d275..0914b88 100644 --- a/E2Manager/resources/configuration.yaml +++ b/E2Manager/resources/configuration.yaml @@ -6,7 +6,7 @@ rmr: port: 3801 maxMsgSize: 65536 routingManager: - baseUrl: http://10.0.2.15:12020/ric/v1/handles/v1/ + baseUrl: http://10.0.2.15:12020/ric/v1/handles/ notificationResponseBuffer: 100 bigRedButtonTimeoutSec: 5 maxConnectionAttempts: 3 diff --git a/tools/RoutingManagerSimulator/api/swagger.yaml b/tools/RoutingManagerSimulator/api/swagger.yaml index db343d7..2510d78 100755 --- a/tools/RoutingManagerSimulator/api/swagger.yaml +++ b/tools/RoutingManagerSimulator/api/swagger.yaml @@ -158,7 +158,7 @@ paths: description: "Xapp list received" "400": description: "Invalid data" - /handles/v1/e2t: + /handles/e2t: post: tags: - "handle" @@ -213,7 +213,7 @@ paths: description: "new e2t instance is considered and platform routes are established" "400": description: "Invalid data" - /handles/v1/associate-ran-to-e2t: + /handles/associate-ran-to-e2t: post: tags: - "handle" @@ -239,7 +239,7 @@ paths: description: "e2t ran mapping recieved, platform routes" "400": description: "Invalid data" - /handles/v1/dissociate-ran: + /handles/dissociate-ran: post: tags: - "handle" diff --git a/tools/RoutingManagerSimulator/go/README.md b/tools/RoutingManagerSimulator/go/README.md new file mode 100755 index 0000000..f146cbf --- /dev/null +++ b/tools/RoutingManagerSimulator/go/README.md @@ -0,0 +1,25 @@ +# Go API Server for swagger + +This is the Swagger/OpenAPI 2.0 definition of Routing Manager's Northbound API. + +## Overview +This server was generated by the [swagger-codegen] +(https://github.com/swagger-api/swagger-codegen) project. +By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. +- + +To see how to make this your own, look here: + +[README](https://github.com/swagger-api/swagger-codegen/blob/master/README.md) + +- API version: 0.4.0 +- Build date: 2019-12-30T10:52:31.803Z + + +### Running the server +To run the server, follow these simple steps: + +``` +go run main.go +``` + diff --git a/tools/RoutingManagerSimulator/go/routers.go b/tools/RoutingManagerSimulator/go/routers.go index 6c34230..d37b9ae 100755 --- a/tools/RoutingManagerSimulator/go/routers.go +++ b/tools/RoutingManagerSimulator/go/routers.go @@ -77,21 +77,21 @@ var routes = Routes{ Route{ "AssociateRanToE2tHandle", strings.ToUpper("Post"), - "/ric/v1/handles/v1/associate-ran-to-e2t", + "/ric/v1/handles/associate-ran-to-e2t", AssociateRanToE2tHandle, }, Route{ "CreateNewE2tHandle", strings.ToUpper("Post"), - "/ric/v1/handles/v1/e2t", + "/ric/v1/handles/e2t", CreateNewE2tHandle, }, Route{ "DeleteE2tHandle", strings.ToUpper("Delete"), - "/ric/v1/handles/v1/e2t", + "/ric/v1/handles/e2t", DeleteE2tHandle, }, @@ -105,7 +105,7 @@ var routes = Routes{ Route{ "DissociateRan", strings.ToUpper("Post"), - "/ric/v1/handles/v1/dissociate-ran", + "/ric/v1/handles/dissociate-ran", DissociateRan, }, -- 2.16.6 From e3de46b8ef25583731f1c998d9d396d82ffcc860 Mon Sep 17 00:00:00 2001 From: is005q Date: Mon, 30 Dec 2019 16:35:19 +0200 Subject: [PATCH 09/16] Add a test log...................... Change-Id: I0b5cf2584169f718bb2ebbd7a4c38fbb2916fd2b Signed-off-by: is005q --- E2Manager/managers/e2t_association_manager.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/E2Manager/managers/e2t_association_manager.go b/E2Manager/managers/e2t_association_manager.go index e313c19..b18647b 100644 --- a/E2Manager/managers/e2t_association_manager.go +++ b/E2Manager/managers/e2t_association_manager.go @@ -54,6 +54,9 @@ func (m *E2TAssociationManager) AssociateRan(e2tAddress string, nodebInfo *entit nodebInfo.AssociatedE2TInstanceAddress = e2tAddress nodebInfo.ConnectionAttempts = 0 + + + m.logger.Infof("test test test test") rnibErr := m.rnibDataService.UpdateNodebInfo(nodebInfo) if rnibErr != nil { m.logger.Errorf("#E2TAssociationManager.AssociateRan - RAN name: %s - Failed to update RAN.AssociatedE2TInstanceAddress in rNib. Error: %s", ranName, rnibErr) -- 2.16.6 From 90d22a6de7e3321dbd90083a5d093541e5e53c75 Mon Sep 17 00:00:00 2001 From: is005q Date: Wed, 1 Jan 2020 11:55:49 +0200 Subject: [PATCH 10/16] [RICPLT-2590] Update Red Button Flow with MultiE2T support + UTs Change-Id: Ib5e27cf36b5c4051dea861fb1d25a67c4ddd8781 Signed-off-by: is005q --- .gitignore | 3 + E2Manager/app/main.go | 2 +- E2Manager/clients/routing_manager_client.go | 1 + E2Manager/controllers/e2t_controller_test.go | 2 +- E2Manager/controllers/nodeb_controller_test.go | 20 +- .../httpmsghandlers/delete_all_request_handler.go | 172 +++--- .../delete_all_request_handler_test.go | 587 +++++++++++---------- E2Manager/managers/e2t_association_manager.go | 2 - E2Manager/managers/e2t_instances_manager.go | 48 +- E2Manager/mocks/e2t_instances_manager_mock.go | 11 +- E2Manager/mocks/routing_manager_client_mock.go | 6 + .../incoming_request_handler_provider.go | 9 +- .../incoming_request_handler_provider_test.go | 2 +- .../stateMachine/delete_all_node_state_machine.go | 43 -- .../delete_all_node_state_machine_test.go | 33 -- 15 files changed, 472 insertions(+), 469 deletions(-) delete mode 100644 E2Manager/stateMachine/delete_all_node_state_machine.go delete mode 100644 E2Manager/stateMachine/delete_all_node_state_machine_test.go diff --git a/.gitignore b/.gitignore index 0baa305..e6901da 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ E2Manager/3rdparty/asn1codec/e2ap_engine/converter-example E2Manager/3rdparty/asn1codec/tests/ E2Manager/cp.out +Automation/Tests/**/*.xml __pycache__/ *.html *.log @@ -12,3 +13,5 @@ __pycache__/ .tox docs/_build/ /.gitreview +E2Manager/coverage.txt +E2Manager/e2m diff --git a/E2Manager/app/main.go b/E2Manager/app/main.go index 0678611..8eff30d 100644 --- a/E2Manager/app/main.go +++ b/E2Manager/app/main.go @@ -77,7 +77,7 @@ func main() { go rmrReceiver.ListenAndHandle() go e2tKeepAliveWorker.Execute() - httpMsgHandlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(logger, rmrSender, config, rnibDataService, ranSetupManager, e2tInstancesManager, e2tAssociationManager) + httpMsgHandlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(logger, rmrSender, config, rnibDataService, ranSetupManager, e2tInstancesManager, e2tAssociationManager, routingManagerClient) rootController := controllers.NewRootController(rnibDataService) nodebController := controllers.NewNodebController(logger, httpMsgHandlerProvider) e2tController := controllers.NewE2TController(logger, httpMsgHandlerProvider) diff --git a/E2Manager/clients/routing_manager_client.go b/E2Manager/clients/routing_manager_client.go index 5257d04..d4c9bbe 100644 --- a/E2Manager/clients/routing_manager_client.go +++ b/E2Manager/clients/routing_manager_client.go @@ -45,6 +45,7 @@ type IRoutingManagerClient interface { AddE2TInstance(e2tAddress string) error AssociateRanToE2TInstance(e2tAddress string, ranName string) error DissociateRanE2TInstance(e2tAddress string, ranName string) error + DissociateAllRans(e2tAddresses []string) error } func NewRoutingManagerClient(logger *logger.Logger, config *configuration.Configuration, httpClient HttpClient) *RoutingManagerClient { diff --git a/E2Manager/controllers/e2t_controller_test.go b/E2Manager/controllers/e2t_controller_test.go index 1ed6934..943b138 100644 --- a/E2Manager/controllers/e2t_controller_test.go +++ b/E2Manager/controllers/e2t_controller_test.go @@ -54,7 +54,7 @@ func setupE2TControllerTest(t *testing.T) (*E2TController, *mocks.RnibReaderMock rnibDataService := services.NewRnibDataService(log, config, readerMock, nil) e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, log) - handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, nil, config, rnibDataService, nil, e2tInstancesManager, &managers.E2TAssociationManager{}) + handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, nil, config, rnibDataService, nil, e2tInstancesManager, &managers.E2TAssociationManager{}, nil) controller := NewE2TController(log, handlerProvider) return controller, readerMock } diff --git a/E2Manager/controllers/nodeb_controller_test.go b/E2Manager/controllers/nodeb_controller_test.go index e0c392f..726e8c3 100644 --- a/E2Manager/controllers/nodeb_controller_test.go +++ b/E2Manager/controllers/nodeb_controller_test.go @@ -66,7 +66,7 @@ type controllerGetNodebIdListTestContext struct { expectedJsonResponse string } -func setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock) { +func setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock) { log := initLog(t) config := configuration.ParseConfiguration() @@ -82,7 +82,7 @@ func setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, httpClientMock := &mocks.HttpClientMock{} rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock) e2tAssociationManager := managers.NewE2TAssociationManager(log, rnibDataService, e2tInstancesManager, rmClient) - handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, rmrSender, config, rnibDataService, ranSetupManager, e2tInstancesManager, e2tAssociationManager) + handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, rmrSender, config, rnibDataService, ranSetupManager, e2tInstancesManager, e2tAssociationManager, rmClient) controller := NewNodebController(log, handlerProvider) return controller, readerMock, writerMock, rmrMessengerMock, e2tInstancesManager } @@ -136,7 +136,6 @@ func TestX2SetupSuccess(t *testing.T) { assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode) } - func TestEndcSetupSuccess(t *testing.T) { controller, readerMock, writerMock, rmrMessengerMock, _ := setupControllerTest(t) @@ -169,11 +168,8 @@ func TestEndcSetupSuccess(t *testing.T) { } func TestShutdownHandlerRnibError(t *testing.T) { - controller, readerMock, _, _, _ := setupControllerTest(t) - - rnibErr := &common.ResourceNotFoundError{} - var nbIdentityList []*entities.NbIdentity - readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibErr) + controller, _, _, _, e2tInstancesManagerMock:= setupControllerTest(t) + e2tInstancesManagerMock.On("GetE2TAddresses").Return([]string{}, e2managererrors.NewRnibDbError()) writer := httptest.NewRecorder() @@ -312,11 +308,9 @@ func TestHeaderValidationFailed(t *testing.T) { } func TestShutdownStatusNoContent(t *testing.T) { - controller, readerMock, _, _, _ := setupControllerTest(t) - - var rnibError error - nbIdentityList := []*entities.NbIdentity{} - readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibError) + controller, readerMock, _, _, e2tInstancesManagerMock := setupControllerTest(t) + e2tInstancesManagerMock.On("GetE2TAddresses").Return([]string{}, nil) + readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, nil) writer := httptest.NewRecorder() controller.Shutdown(writer, tests.GetHttpRequest()) diff --git a/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go b/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go index eb238cc..7edc13c 100644 --- a/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go +++ b/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go @@ -17,161 +17,163 @@ // This source code is part of the near-RT RIC (RAN Intelligent Controller) // platform project (RICP). - package httpmsghandlers import "C" import ( + "e2mgr/clients" "e2mgr/configuration" "e2mgr/e2managererrors" "e2mgr/logger" + "e2mgr/managers" "e2mgr/models" "e2mgr/rmrCgo" "e2mgr/services" "e2mgr/services/rmrsender" - "e2mgr/stateMachine" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" "time" ) type DeleteAllRequestHandler struct { - rnibDataService services.RNibDataService - rmrSender *rmrsender.RmrSender - config *configuration.Configuration - logger *logger.Logger + rnibDataService services.RNibDataService + rmrSender *rmrsender.RmrSender + config *configuration.Configuration + logger *logger.Logger + e2tInstancesManager managers.IE2TInstancesManager + rmClient clients.IRoutingManagerClient } -func NewDeleteAllRequestHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rnibDataService services.RNibDataService) *DeleteAllRequestHandler { +func NewDeleteAllRequestHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rnibDataService services.RNibDataService, e2tInstancesManager managers.IE2TInstancesManager, rmClient clients.IRoutingManagerClient) *DeleteAllRequestHandler { return &DeleteAllRequestHandler{ - logger: logger, - rnibDataService: rnibDataService, - rmrSender: rmrSender, - config: config, + logger: logger, + rnibDataService: rnibDataService, + rmrSender: rmrSender, + config: config, + e2tInstancesManager: e2tInstancesManager, + rmClient: rmClient, } } -func (handler *DeleteAllRequestHandler) Handle(request models.Request) (models.IResponse, error) { +func (h *DeleteAllRequestHandler) Handle(request models.Request) (models.IResponse, error) { + + e2tAddresses, err := h.e2tInstancesManager.GetE2TAddresses() - err, continueFlow := handler.updateNodebStates(false) if err != nil { return nil, err } - if continueFlow == false { - return nil, nil + if len(e2tAddresses) == 0 { + err, _ = h.updateNodebs(h.updateNodebInfoForceShutdown) + return nil, err } - response := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL} - if err := handler.rmrSender.Send(&response); err != nil { - handler.logger.Errorf("#DeleteAllRequestHandler.Handle - failed to send sctp clear all message to RMR: %s", err) - return nil, e2managererrors.NewRmrError() + err = h.rmClient.DissociateAllRans(e2tAddresses) + + if err != nil { + h.logger.Warnf("#DeleteAllRequestHandler.Handle - routing manager failure. continue flow.") + } + + err, allRansAreShutDown := h.updateNodebs(h.updateNodebInfoShuttingDown) + + if err != nil { + return nil, err } - time.Sleep(time.Duration(handler.config.BigRedButtonTimeoutSec) * time.Second) - handler.logger.Infof("#DeleteAllRequestHandler.Handle - timer expired") + err = h.e2tInstancesManager.ClearRansOfAllE2TInstances() - err, _ = handler.updateNodebStates(true) if err != nil { return nil, err } - return nil, nil + rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL} + + err = h.rmrSender.Send(&rmrMessage) + + if err != nil { + h.logger.Errorf("#DeleteAllRequestHandler.Handle - failed to send sctp clear all message to RMR: %s", err) + return nil, e2managererrors.NewRmrError() + } + + if allRansAreShutDown { + return nil, nil + } + + time.Sleep(time.Duration(h.config.BigRedButtonTimeoutSec) * time.Second) + h.logger.Infof("#DeleteAllRequestHandler.Handle - timer expired") + + err, _ = h.updateNodebs(h.updateNodebInfoShutDown) + return nil, err } -func (handler *DeleteAllRequestHandler) updateNodebStates(timeoutExpired bool) (error, bool) { - nbIdentityList, err := handler.rnibDataService.GetListNodebIds() +func (h *DeleteAllRequestHandler) updateNodebs(updateCb func(node *entities.NodebInfo) error) (error, bool) { + nbIdentityList, err := h.rnibDataService.GetListNodebIds() if err != nil { - handler.logger.Errorf("#DeleteAllRequestHandler.updateNodebStates - failed to get nodes list from RNIB. Error: %s", err.Error()) + h.logger.Errorf("#DeleteAllRequestHandler.updateNodebs - failed to get nodes list from rNib. Error: %s", err) return e2managererrors.NewRnibDbError(), false } - if len(nbIdentityList) == 0 { - return nil, false - } + allRansAreShutdown := true - numOfRanToShutDown := 0 for _, nbIdentity := range nbIdentityList { - - node, err := handler.rnibDataService.GetNodeb((*nbIdentity).GetInventoryName()) + node, err := h.rnibDataService.GetNodeb(nbIdentity.InventoryName) if err != nil { - handler.logger.Errorf("#DeleteAllRequestHandler.updateNodebStates - failed to get nodeB entity for ran name: %v from RNIB. Error: %s", - (*nbIdentity).GetInventoryName(), err.Error()) + h.logger.Errorf("#DeleteAllRequestHandler.updateNodebs - failed to get nodeB entity for ran name: %s from rNib. error: %s", nbIdentity.InventoryName, err) continue } - if timeoutExpired { - - if handler.saveNodebShutDownState(nbIdentity, node) { - numOfRanToShutDown++ - } - continue + if node.ConnectionStatus != entities.ConnectionStatus_SHUT_DOWN { + allRansAreShutdown = false } - if handler.saveNodebNextState(nbIdentity, node) { - numOfRanToShutDown++ - } - } - if numOfRanToShutDown > 0 { - handler.logger.Infof("#DeleteAllRequestHandler.updateNodebStates - update nodebs states in RNIB completed") - } else { - handler.logger.Infof("#DeleteAllRequestHandler.updateNodebStates - nodebs states are not updated ") - return nil, false + _ = updateCb(node) } - return nil, true -} - -func (handler *DeleteAllRequestHandler) saveNodebNextState(nbIdentity *entities.NbIdentity, node *entities.NodebInfo) bool { - - if node.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN { - return true - } - - nextStatus, res := stateMachine.NodeNextStateDeleteAll(node.ConnectionStatus) - if res == false { - return false - } + return nil, allRansAreShutdown - node.ConnectionStatus = nextStatus +} - err := handler.rnibDataService.SaveNodeb(nbIdentity, node) +func (h *DeleteAllRequestHandler) updateNodebInfoForceShutdown(node *entities.NodebInfo) error { + return h.updateNodebInfo(node, entities.ConnectionStatus_SHUT_DOWN, true) +} - if err != nil { - handler.logger.Errorf("#DeleteAllRequestHandler.saveNodebNextState - failed to save nodeB entity for inventory name: %v to RNIB. Error: %s", - (*nbIdentity).GetInventoryName(), err.Error()) - return false +func (h *DeleteAllRequestHandler) updateNodebInfoShuttingDown(node *entities.NodebInfo) error { + if node.ConnectionStatus == entities.ConnectionStatus_SHUT_DOWN { + return nil } - if handler.logger.DebugEnabled() { - handler.logger.Debugf("#DeleteAllRequestHandler.saveNodebNextState - connection status of inventory name: %v changed to %v", - (*nbIdentity).GetInventoryName(), nextStatus.String()) - } - return true + return h.updateNodebInfo(node, entities.ConnectionStatus_SHUTTING_DOWN, true) } -func (handler *DeleteAllRequestHandler) saveNodebShutDownState(nbIdentity *entities.NbIdentity, node *entities.NodebInfo) bool { - +func (h *DeleteAllRequestHandler) updateNodebInfoShutDown(node *entities.NodebInfo) error { if node.ConnectionStatus == entities.ConnectionStatus_SHUT_DOWN { - return false + return nil } if node.ConnectionStatus != entities.ConnectionStatus_SHUTTING_DOWN { - handler.logger.Errorf("#DeleteAllRequestHandler.saveNodebShutDownState - ignore, status is not Shutting Down, inventory name: %v ", (*nbIdentity).GetInventoryName()) - return false + h.logger.Warnf("#DeleteAllRequestHandler.updateNodebInfoShutDown - RAN name: %s - ignore, status is not Shutting Down", node.RanName) + return nil } - node.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + return h.updateNodebInfo(node, entities.ConnectionStatus_SHUT_DOWN, false) +} + +func (h *DeleteAllRequestHandler) updateNodebInfo(node *entities.NodebInfo, connectionStatus entities.ConnectionStatus, resetAssociatedE2TAddress bool) error { + node.ConnectionStatus = connectionStatus - err := handler.rnibDataService.SaveNodeb(nbIdentity, node) + if resetAssociatedE2TAddress { + node.AssociatedE2TInstanceAddress = "" + } + + err := h.rnibDataService.UpdateNodebInfo(node) if err != nil { - handler.logger.Errorf("#DeleteAllRequestHandler.saveNodebShutDownState - failed to save nodeB entity for inventory name: %v to RNIB. Error: %s", - (*nbIdentity).GetInventoryName(), err.Error()) - return false + h.logger.Errorf("#DeleteAllRequestHandler.updateNodebInfo - RAN name: %s - failed saving nodeB entity to rNib. error: %s", node.RanName, err) + return err } - handler.logger.Errorf("#DeleteAllRequestHandler.saveNodebShutDownState - Shut Down , inventory name: %v ", (*nbIdentity).GetInventoryName()) - return true + h.logger.Infof("#DeleteAllRequestHandler.updateNodebInfo - RAN name: %s, connection status: %s", node.RanName, connectionStatus) + return nil + } diff --git a/E2Manager/handlers/httpmsghandlers/delete_all_request_handler_test.go b/E2Manager/handlers/httpmsghandlers/delete_all_request_handler_test.go index 956a366..5332bd9 100644 --- a/E2Manager/handlers/httpmsghandlers/delete_all_request_handler_test.go +++ b/E2Manager/handlers/httpmsghandlers/delete_all_request_handler_test.go @@ -17,365 +17,392 @@ // This source code is part of the near-RT RIC (RAN Intelligent Controller) // platform project (RICP). - package httpmsghandlers import ( + "bytes" + "e2mgr/clients" "e2mgr/configuration" "e2mgr/e2managererrors" "e2mgr/logger" + "e2mgr/managers" "e2mgr/mocks" + "e2mgr/models" "e2mgr/rmrCgo" "e2mgr/services" "e2mgr/services/rmrsender" "e2mgr/tests" - "fmt" + "encoding/json" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "reflect" + "io/ioutil" + "net/http" "testing" ) -func setupTest(t *testing.T) (*logger.Logger, *configuration.Configuration, *mocks.RnibReaderMock, *mocks.RnibWriterMock, services.RNibDataService, *mocks.RmrMessengerMock) { +func setupDeleteAllRequestHandlerTest(t *testing.T) (*DeleteAllRequestHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.HttpClientMock) { log := initLog(t) config := configuration.ParseConfiguration() + config.BigRedButtonTimeoutSec = 1 + config.RoutingManager.BaseUrl = BaseRMUrl readerMock := &mocks.RnibReaderMock{} - writerMock := &mocks.RnibWriterMock{} - rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock) + rmrMessengerMock := &mocks.RmrMessengerMock{} - return log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock + rmrSender := getRmrSender(rmrMessengerMock, log) + + e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, log) + httpClientMock := &mocks.HttpClientMock{} + rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock) + handler := NewDeleteAllRequestHandler(log, rmrSender, config, rnibDataService, e2tInstancesManager, rmClient) + return handler, readerMock, writerMock, rmrMessengerMock, httpClientMock } -func TestHandleBeforeTimerGetListNodebIdsFailedFlow(t *testing.T) { - log, config, readerMock, _, rnibDataService, rmrMessengerMock := setupTest(t) +func mapE2TAddressesToE2DataList(e2tAddresses []string) models.RoutingManagerE2TDataList { + e2tDataList := make(models.RoutingManagerE2TDataList, len(e2tAddresses)) - handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService) + for i, v := range e2tAddresses { + e2tDataList[i] = models.NewRoutingManagerE2TData(v) + } - rnibErr := &common.ResourceNotFoundError{} - var nbIdentityList []*entities.NbIdentity - readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibErr) + return e2tDataList +} - expected := &e2managererrors.RnibDbError{} - _, actual := handler.Handle(nil) - if reflect.TypeOf(actual) != reflect.TypeOf(expected) { - t.Errorf("Error actual = %v, and Expected = %v.", actual, expected) +func mockHttpClientDissociateAllRans(httpClientMock *mocks.HttpClientMock, e2tAddresses []string, ok bool) { + data := mapE2TAddressesToE2DataList(e2tAddresses) + marshaled, _ := json.Marshal(data) + body := bytes.NewBuffer(marshaled) + url := BaseRMUrl + clients.DissociateRanE2TInstanceApiSuffix + respBody := ioutil.NopCloser(bytes.NewBufferString("")) + + var status int + if ok { + status = http.StatusOK + } else { + status = http.StatusBadRequest } + httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: status, Body: respBody}, nil) } -func TestHandleAfterTimerGetListNodebIdsFailedFlow(t *testing.T) { - log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t) - - config.BigRedButtonTimeoutSec = 1 - - handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService) - - rnibErr := &common.ResourceNotFoundError{} - //Before timer: Disconnected->ShutDown, ShuttingDown->Ignore, Connected->ShuttingDown - nbIdentityList := createIdentityList() - - readerMock.On("GetListNodebIds").Return(nbIdentityList, nil).Return(nbIdentityList, rnibErr) +func TestGetE2TAddressesFailure(t *testing.T) { + h, readerMock, _, _, _ := setupDeleteAllRequestHandlerTest(t) + readerMock.On("GetE2TAddresses").Return([]string{}, e2managererrors.NewRnibDbError()) + _, err := h.Handle(nil) + assert.IsType(t, &e2managererrors.RnibDbError{}, err) + readerMock.AssertExpectations(t) +} +func TestOneRanGetE2TAddressesEmptyList(t *testing.T) { + h, readerMock, writerMock, _, _ := setupDeleteAllRequestHandlerTest(t) + readerMock.On("GetE2TAddresses").Return([]string{}, nil) + nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}} + readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,} - nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,} readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) - readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil) - readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil) - updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - updatedNb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb1).Return(nil) - writerMock.On("SaveNodeb", mock.Anything, updatedNb3).Return(nil) - - expected := &e2managererrors.RnibDbError{} - _, actual := handler.Handle(nil) - - if reflect.TypeOf(actual) != reflect.TypeOf(expected) { - t.Errorf("Error actual = %v, and Expected = %v.", actual, expected) - } + writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil) + _, err := h.Handle(nil) + assert.Nil(t, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) } -func TestHandleSuccessFlow(t *testing.T) { - log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t) - - config.BigRedButtonTimeoutSec = 1 - handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService) - - //Before timer: Disconnected->ShutDown, ShuttingDown->Ignore, Connected->ShuttingDown - nbIdentityList := createIdentityList() +func TestTwoRansGetE2TAddressesEmptyListOneGetNodebFailure(t *testing.T) { + h, readerMock, writerMock, _, _ := setupDeleteAllRequestHandlerTest(t) + readerMock.On("GetE2TAddresses").Return([]string{}, nil) + nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}} readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) - nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,} - nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,} readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) - readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil) - readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil) - updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - updatedNb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb1).Return(nil) - writerMock.On("SaveNodeb", mock.Anything, updatedNb3).Return(nil) + writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil) + var nb2 *entities.NodebInfo + readerMock.On("GetNodeb", "RanName_2").Return(nb2, common.NewInternalError(errors.New("error"))) + _, err := h.Handle(nil) + assert.Nil(t, err) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) + readerMock.AssertExpectations(t) +} - //after timer: ShutDown->Ignore, ShuttingDown->ShutDown +func TestTwoRansGetE2TAddressesEmptyListOneUpdateNodebInfoFailure(t *testing.T) { + h, readerMock, writerMock, _, _ := setupDeleteAllRequestHandlerTest(t) + readerMock.On("GetE2TAddresses").Return([]string{}, nil) + nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}} readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) - nb1AfterTimer := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - nb2AfterTimer := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - nb3AfterTimer := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - readerMock.On("GetNodeb", "RanName_1").Return(nb1AfterTimer, nil) - readerMock.On("GetNodeb", "RanName_2").Return(nb2AfterTimer, nil) - readerMock.On("GetNodeb", "RanName_3").Return(nb3AfterTimer, nil) - - updatedNb2AfterTimer := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - updatedNb3AfterTimer := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb2AfterTimer).Return(nil) - writerMock.On("SaveNodeb", mock.Anything, updatedNb3AfterTimer).Return(nil) - - mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction) - rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, nil) + nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,} + readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) + updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} + writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil) - _, actual := handler.Handle(nil) + nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,} + readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil) + updatedNb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} + writerMock.On("UpdateNodebInfo", updatedNb2).Return(common.NewInternalError(errors.New("error"))) + _, err := h.Handle(nil) + assert.Nil(t, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) +} - assert.Nil(t, actual) +func TestOneRanDissociateSucceedsTryShuttingDownFailure(t *testing.T) { + h, readerMock, writerMock, _, httpClientMock := setupDeleteAllRequestHandlerTest(t) + e2tAddresses := []string{E2TAddress} + readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true) + nbIdentityList := []*entities.NbIdentity{} + readerMock.On("GetListNodebIds").Return(nbIdentityList, common.NewInternalError(errors.New("error"))) + _, err := h.Handle(nil) + assert.IsType(t, &e2managererrors.RnibDbError{}, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) } -func TestHandleSuccessGetNextStatusFlow(t *testing.T) { - log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t) +func TestOneRanDissociateFailsTryShuttingDownFailure(t *testing.T) { + h, readerMock, writerMock, _, httpClientMock := setupDeleteAllRequestHandlerTest(t) + e2tAddresses := []string{E2TAddress} - config.BigRedButtonTimeoutSec = 1 - handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService) + readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, false) + nbIdentityList := []*entities.NbIdentity{} + readerMock.On("GetListNodebIds").Return(nbIdentityList, common.NewInternalError(errors.New("error"))) + _, err := h.Handle(nil) + assert.IsType(t, &e2managererrors.RnibDbError{}, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) +} +func TestOneRanTryShuttingDownSucceedsClearFails(t *testing.T) { + h, readerMock, writerMock, _, httpClientMock := setupDeleteAllRequestHandlerTest(t) + e2tAddresses := []string{E2TAddress} + readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true) nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}} readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) - - nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED,} + nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress} readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) - updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb1).Return(nil) - - //after timer: ShutDown->Ignore, ShuttingDown->ShutDown - readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) - - nb1AfterTimer := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - readerMock.On("GetNodeb", "RanName_1").Return(nb1AfterTimer, nil) - - updatedNb1AfterTimer := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb1AfterTimer).Return(nil) - - mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction) - rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, nil) - - _, actual := handler.Handle(nil) - - assert.Nil(t, actual) + writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil) + readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil) + readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{}, common.NewInternalError(errors.New("error"))) + _, err := h.Handle(nil) + assert.IsType(t, &e2managererrors.RnibDbError{}, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) } -func TestHandleShuttingDownStatusFlow(t *testing.T) { - log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t) - - config.BigRedButtonTimeoutSec = 1 - handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService) - +func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSendFails(t *testing.T) { + h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t) + e2tAddresses := []string{E2TAddress} + readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true) nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}} readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) - - nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} + nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress} readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) - - //after timer: ShutDown->Ignore, ShuttingDown->ShutDown - readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) - - nb1AfterTimer := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - readerMock.On("GetNodeb", "RanName_1").Return(nb1AfterTimer, nil) - - updatedNb1AfterTimer := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb1AfterTimer).Return(nil) - - mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction) - rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, nil) - - _, actual := handler.Handle(nil) - - assert.Nil(t, actual) + updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} + writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil) + readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil) + e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}} + readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil) + updatedE2tInstance := e2tInstance + updatedE2tInstance.AssociatedRanList = []string{} + writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil) + + rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL} + mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction) + rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, e2managererrors.NewRmrError()) + _, err := h.Handle(nil) + assert.IsType(t, &e2managererrors.RmrError{}, err) + rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) } -func TestHandleGetNodebFailedFlow(t *testing.T) { - log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t) - - config.BigRedButtonTimeoutSec = 1 - handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService) - - //Before timer: Disconnected->ShutDown(will fail), ShuttingDown->Ignore, Connected->ShuttingDown - nbIdentityList := createIdentityList() +func TestTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdown(t *testing.T) { + h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t) + e2tAddresses := []string{E2TAddress} + readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true) + nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}} readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) - - errRnib := &common.ResourceNotFoundError{} - nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,} - nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,} - readerMock.On("GetNodeb", "RanName_1").Return(nb1, errRnib) + nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN} + nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN} + readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil) - readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil) - - updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - updatedNb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb1).Return(errRnib) - writerMock.On("SaveNodeb", mock.Anything, updatedNb3).Return(nil) - - //after timer: ShutDown->Ignore, ShuttingDown->ShutDown - readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) - - nb1AfterTimer := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - nb2AfterTimer := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - nb3AfterTimer := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - readerMock.On("GetNodeb", "RanName_1").Return(nb1AfterTimer, errRnib) - readerMock.On("GetNodeb", "RanName_2").Return(nb2AfterTimer, nil) - readerMock.On("GetNodeb", "RanName_3").Return(nb3AfterTimer, nil) - - updatedNb2AfterTimer := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - updatedNb3AfterTimer := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb2AfterTimer).Return(nil) - writerMock.On("SaveNodeb", mock.Anything, updatedNb3AfterTimer).Return(nil) - - mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction) - rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, nil) - - _, actual := handler.Handle(nil) - - assert.Nil(t, actual) + readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil) + e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1", "RanName_2"}} + readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil) + updatedE2tInstance := e2tInstance + updatedE2tInstance.AssociatedRanList = []string{} + writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil) + + rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL} + mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction) + rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil) + _, err := h.Handle(nil) + assert.Nil(t, err) + rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) } -func TestHandleSaveFailedFlow(t *testing.T) { - log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t) - - config.BigRedButtonTimeoutSec = 1 - handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService) - - //Before timer: Disconnected->ShutDown, ShuttingDown->Ignore, Connected->ShuttingDown(will fail) - nbIdentityList := createIdentityList() +//func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsAlreadyShutdown(t *testing.T) { +// h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t) +// e2tAddresses := []string{E2TAddress} + +// readerMock.On("GetE2TAddresses").Return(e2tAddresses , nil) +// mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses ,true) +// nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}} +// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) +// nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress} +// readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) +// updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} +// writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil) +// readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil) +// e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}} +// readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance }, nil) +// updatedE2tInstance := e2tInstance +// updatedE2tInstance.AssociatedRanList = []string{} +// writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil) +// +// rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL} +// mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction) +// rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil) +// +// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) +// nbAfterTimer := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} +// readerMock.On("GetNodeb", /*"RanName_1"*/mock.Anything).Return(nbAfterTimer , nil) // Since this is a second call with same arguments we send mock.Anything due to mock limitations +// _, err := h.Handle(nil) +// assert.Nil(t, err) +// rmrMessengerMock.AssertCalled(t, "SendMsg",mbuf, true) +// readerMock.AssertExpectations(t) +// writerMock.AssertExpectations(t) +// writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) +//} + +func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDown(t *testing.T) { + h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t) + e2tAddresses := []string{E2TAddress} + readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true) + nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}} readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) + //nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress} + //readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) + updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} + writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil) + readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil) + e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}} + readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil) + updatedE2tInstance := e2tInstance + updatedE2tInstance.AssociatedRanList = []string{} + writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil) + + rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL} + mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction) + rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil) - nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,} - nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,} - readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) - readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil) - readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil) - - errRnib := &common.ResourceNotFoundError{} - updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - updatedNb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb1).Return(nil) - writerMock.On("SaveNodeb", mock.Anything, updatedNb3).Return(errRnib) - - //after timer: ShutDown->Ignore, ShuttingDown->ShutDown(will fail) readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) - - nb1AfterTimer := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - nb2AfterTimer := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - nb3AfterTimer := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - readerMock.On("GetNodeb", "RanName_1").Return(nb1AfterTimer, nil) - readerMock.On("GetNodeb", "RanName_2").Return(nb2AfterTimer, nil) - readerMock.On("GetNodeb", "RanName_3").Return(nb3AfterTimer, nil) - - updatedNb2AfterTimer := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - updatedNb3AfterTimer := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb2AfterTimer).Return(nil) - writerMock.On("SaveNodeb", mock.Anything, updatedNb3AfterTimer).Return(errRnib) - - mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction) - rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, nil) - - _, actual := handler.Handle(nil) - - assert.Nil(t, actual) + readerMock.On("GetNodeb", "RanName_1").Return(updatedNb1, nil) + updatedNb2 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} + writerMock.On("UpdateNodebInfo", updatedNb2).Return(nil) + _, err := h.Handle(nil) + assert.Nil(t, err) + rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) } -func TestHandleSendRmrFailedFlow(t *testing.T) { - log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t) - - config.BigRedButtonTimeoutSec = 1 - handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService) - - //Before timer: Disconnected->ShutDown, ShuttingDown->Ignore, Connected->ShuttingDown(will fail) - nbIdentityList := createIdentityList() +func TestSuccessTwoE2TInstancesSixRans(t *testing.T) { + h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t) + e2tAddresses := []string{E2TAddress, E2TAddress2} + readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true) + nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}, {InventoryName: "RanName_3"}, {InventoryName: "RanName_4"}, {InventoryName: "RanName_5"}, {InventoryName: "RanName_6"}} readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) + //nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress} + //readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) + //nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress} + //readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil) + //nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress} + //readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil) + //nb4 := &entities.NodebInfo{RanName: "RanName_4", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress2} + //readerMock.On("GetNodeb", "RanName_4").Return(nb4, nil) + //nb5 := &entities.NodebInfo{RanName: "RanName_5", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress2} + //readerMock.On("GetNodeb", "RanName_5").Return(nb5, nil) + //nb6 := &entities.NodebInfo{RanName: "RanName_6", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress2} + //readerMock.On("GetNodeb", "RanName_6").Return(nb6, nil) - nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,} - nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,} - readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) - readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil) - readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil) - - updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} + updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} + writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil) + updatedNb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} + writerMock.On("UpdateNodebInfo", updatedNb2).Return(nil) updatedNb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb1).Return(nil) - writerMock.On("SaveNodeb", mock.Anything, updatedNb3).Return(nil) + writerMock.On("UpdateNodebInfo", updatedNb3).Return(nil) + updatedNb4 := &entities.NodebInfo{RanName: "RanName_4", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} + writerMock.On("UpdateNodebInfo", updatedNb4).Return(nil) + updatedNb5 := &entities.NodebInfo{RanName: "RanName_5", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} + writerMock.On("UpdateNodebInfo", updatedNb5).Return(nil) + updatedNb6 := &entities.NodebInfo{RanName: "RanName_6", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} + writerMock.On("UpdateNodebInfo", updatedNb6).Return(nil) + + readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1", "RanName_2", "RanName_3"}} + e2tInstance2 := entities.E2TInstance{Address: E2TAddress2, AssociatedRanList: []string{"RanName_4", "RanName_5", "RanName_6"}} + readerMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{&e2tInstance, &e2tInstance2}, nil) + updatedE2tInstance := e2tInstance + updatedE2tInstance.AssociatedRanList = []string{} + updatedE2tInstance2 := e2tInstance2 + updatedE2tInstance2.AssociatedRanList = []string{} + writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil) + writerMock.On("SaveE2TInstance", &updatedE2tInstance2).Return(nil) + + rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL} + mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction) + rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil) - //after timer: ShutDown->Ignore, ShuttingDown->ShutDown(will fail) readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) - - nb1AfterTimer := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - nb2AfterTimer := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - nb3AfterTimer := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} - readerMock.On("GetNodeb", "RanName_1").Return(nb1AfterTimer, nil) - readerMock.On("GetNodeb", "RanName_2").Return(nb2AfterTimer, nil) - readerMock.On("GetNodeb", "RanName_3").Return(nb3AfterTimer, nil) - - updatedNb2AfterTimer := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - updatedNb3AfterTimer := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} - writerMock.On("SaveNodeb", mock.Anything, updatedNb2AfterTimer).Return(nil) - writerMock.On("SaveNodeb", mock.Anything, updatedNb3AfterTimer).Return(nil) - - expected := e2managererrors.NewRmrError() - mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction) - rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), true).Return(mbuf, expected) - - _, actual := handler.Handle(nil) - - if reflect.TypeOf(actual) != reflect.TypeOf(expected) { - t.Errorf("Error actual = %v, and Expected = %v.", actual, expected) - } -} - -func TestHandleGetListEnbIdsEmptyFlow(t *testing.T) { - log, config, readerMock, _, rnibDataService, rmrMessengerMock := setupTest(t) - - handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService) - - var rnibError error - nbIdentityList := []*entities.NbIdentity{} - - readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibError) - - _, actual := handler.Handle(nil) - readerMock.AssertNumberOfCalls(t, "GetNodeb", 0) - assert.Nil(t, actual) -} - -func createIdentityList() []*entities.NbIdentity { - nbIdentity1 := entities.NbIdentity{InventoryName: "RanName_1"} - nbIdentity2 := entities.NbIdentity{InventoryName: "RanName_2"} - nbIdentity3 := entities.NbIdentity{InventoryName: "RanName_3"} - - var nbIdentityList []*entities.NbIdentity - nbIdentityList = append(nbIdentityList, &nbIdentity1) - nbIdentityList = append(nbIdentityList, &nbIdentity2) - nbIdentityList = append(nbIdentityList, &nbIdentity3) - - return nbIdentityList + readerMock.On("GetNodeb", "RanName_1").Return(updatedNb1, nil) + readerMock.On("GetNodeb", "RanName_2").Return(updatedNb2, nil) + readerMock.On("GetNodeb", "RanName_3").Return(updatedNb3, nil) + readerMock.On("GetNodeb", "RanName_4").Return(updatedNb4, nil) + readerMock.On("GetNodeb", "RanName_5").Return(updatedNb5, nil) + readerMock.On("GetNodeb", "RanName_6").Return(updatedNb6, nil) + + updatedNb1AfterTimer := *updatedNb1 + updatedNb1AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + writerMock.On("UpdateNodebInfo", &updatedNb1AfterTimer).Return(nil) + updatedNb2AfterTimer := *updatedNb2 + updatedNb2AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + writerMock.On("UpdateNodebInfo", &updatedNb2AfterTimer).Return(nil) + updatedNb3AfterTimer := *updatedNb3 + updatedNb3AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + writerMock.On("UpdateNodebInfo", &updatedNb3AfterTimer).Return(nil) + updatedNb4AfterTimer := *updatedNb4 + updatedNb4AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + writerMock.On("UpdateNodebInfo", &updatedNb4AfterTimer).Return(nil) + updatedNb5AfterTimer := *updatedNb5 + updatedNb5AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + writerMock.On("UpdateNodebInfo", &updatedNb5AfterTimer).Return(nil) + updatedNb6AfterTimer := *updatedNb6 + updatedNb6AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + writerMock.On("UpdateNodebInfo", &updatedNb6AfterTimer).Return(nil) + _, err := h.Handle(nil) + assert.Nil(t, err) + rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 12) } func initLog(t *testing.T) *logger.Logger { - log, err := logger.InitLogger(logger.InfoLevel) + log, err := logger.InitLogger(logger.DebugLevel) if err != nil { t.Errorf("#initLog test - failed to initialize logger, error: %s", err) } diff --git a/E2Manager/managers/e2t_association_manager.go b/E2Manager/managers/e2t_association_manager.go index b18647b..9b0cada 100644 --- a/E2Manager/managers/e2t_association_manager.go +++ b/E2Manager/managers/e2t_association_manager.go @@ -55,8 +55,6 @@ func (m *E2TAssociationManager) AssociateRan(e2tAddress string, nodebInfo *entit nodebInfo.AssociatedE2TInstanceAddress = e2tAddress nodebInfo.ConnectionAttempts = 0 - - m.logger.Infof("test test test test") rnibErr := m.rnibDataService.UpdateNodebInfo(nodebInfo) if rnibErr != nil { m.logger.Errorf("#E2TAssociationManager.AssociateRan - RAN name: %s - Failed to update RAN.AssociatedE2TInstanceAddress in rNib. Error: %s", ranName, rnibErr) diff --git a/E2Manager/managers/e2t_instances_manager.go b/E2Manager/managers/e2t_instances_manager.go index 0a95f5f..c970c76 100644 --- a/E2Manager/managers/e2t_instances_manager.go +++ b/E2Manager/managers/e2t_instances_manager.go @@ -38,6 +38,7 @@ type E2TInstancesManager struct { } type IE2TInstancesManager interface { + GetE2TAddresses() ([]string, error) GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error) GetE2TInstances() ([]*entities.E2TInstance, error) GetE2TInstancesNoLogs() ([]*entities.E2TInstance, error) @@ -48,6 +49,7 @@ type IE2TInstancesManager interface { RemoveRanFromInstance(ranName string, e2tAddress string) error ActivateE2TInstance(e2tInstance *entities.E2TInstance) error ResetKeepAliveTimestamp(e2tAddress string) error + ClearRansOfAllE2TInstances() error } func NewE2TInstancesManager(rnibDataService services.RNibDataService, logger *logger.Logger) *E2TInstancesManager { @@ -106,7 +108,7 @@ func (m *E2TInstancesManager) GetE2TInstancesNoLogs() ([]*entities.E2TInstance, return e2tInstances, nil } -func (m *E2TInstancesManager) GetE2TInstances() ([]*entities.E2TInstance, error) { +func (m *E2TInstancesManager) GetE2TAddresses() ([]string, error) { e2tAddresses, err := m.rnibDataService.GetE2TAddresses() if err != nil { @@ -114,12 +116,20 @@ func (m *E2TInstancesManager) GetE2TInstances() ([]*entities.E2TInstance, error) _, ok := err.(*common.ResourceNotFoundError) if !ok { - m.logger.Errorf("#E2TInstancesManager.GetE2TInstances - Failed retrieving E2T addresses. error: %s", err) + m.logger.Errorf("#E2TInstancesManager.GetE2TAddresses - Failed retrieving E2T addresses. error: %s", err) return nil, e2managererrors.NewRnibDbError() } - m.logger.Infof("#E2TInstancesManager.GetE2TInstances - Empty E2T addresses list") - return []*entities.E2TInstance{}, nil + } + + return e2tAddresses, nil +} + +func (m *E2TInstancesManager) GetE2TInstances() ([]*entities.E2TInstance, error) { + e2tAddresses, err := m.GetE2TAddresses() + + if err != nil { + return nil, e2managererrors.NewRnibDbError() } if len(e2tAddresses) == 0 { @@ -312,7 +322,7 @@ func (m *E2TInstancesManager) AddRanToInstance(ranName string, e2tAddress string return nil } -func (m E2TInstancesManager) ActivateE2TInstance(e2tInstance *entities.E2TInstance) error{ +func (m E2TInstancesManager) ActivateE2TInstance(e2tInstance *entities.E2TInstance) error { if e2tInstance == nil { m.logger.Errorf("#E2TInstancesManager.ActivateE2TInstance - e2tInstance empty") @@ -360,3 +370,31 @@ func (m *E2TInstancesManager) ResetKeepAliveTimestamp(e2tAddress string) error { return nil } + +func (m *E2TInstancesManager) ClearRansOfAllE2TInstances() error { + + m.mux.Lock() + defer m.mux.Unlock() + + e2tInstances, err := m.GetE2TInstances() + + if err != nil { + return err + } + + if len(e2tInstances) == 0 { + m.logger.Errorf("#E2TInstancesManager.ClearRansOfAllE2TInstances - No E2T instances to clear associated RANs from") + return nil + } + + for _, v := range e2tInstances { + v.AssociatedRanList = []string{} + err := m.rnibDataService.SaveE2TInstance(v) + + if err != nil { + m.logger.Errorf("#E2TInstancesManager.ClearRansOfAllE2TInstances - e2t address: %s - failed saving e2t instance. error: %s", v.Address, err) + } + } + + return nil +} diff --git a/E2Manager/mocks/e2t_instances_manager_mock.go b/E2Manager/mocks/e2t_instances_manager_mock.go index 586f396..5919f9c 100644 --- a/E2Manager/mocks/e2t_instances_manager_mock.go +++ b/E2Manager/mocks/e2t_instances_manager_mock.go @@ -82,5 +82,14 @@ func (m *E2TInstancesManagerMock) ResetKeepAliveTimestamp(e2tAddress string) err func (m *E2TInstancesManagerMock) ActivateE2TInstance(e2tInstance *entities.E2TInstance) error { args := m.Called(e2tInstance) return args.Error(0) +} + +func (m *E2TInstancesManagerMock) GetE2TAddresses() ([]string, error) { + args := m.Called() + return args.Get(0).([]string), args.Error(1) +} -} \ No newline at end of file +func (m *E2TInstancesManagerMock) ClearRansOfAllE2TInstances() error { + args := m.Called() + return args.Error(0) +} diff --git a/E2Manager/mocks/routing_manager_client_mock.go b/E2Manager/mocks/routing_manager_client_mock.go index 24edd55..fb1cafd 100644 --- a/E2Manager/mocks/routing_manager_client_mock.go +++ b/E2Manager/mocks/routing_manager_client_mock.go @@ -43,4 +43,10 @@ func (m *RoutingManagerClientMock) DissociateRanE2TInstance(e2tAddress string, r args := m.Called(e2tAddress, ranName) return args.Error(0) +} + +func (m *RoutingManagerClientMock) DissociateAllRans(e2tAddresses []string) error { + +args := m.Called(e2tAddresses) +return args.Error(0) } \ No newline at end of file diff --git a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go index 6a306e1..cfbda44 100644 --- a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go +++ b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go @@ -20,6 +20,7 @@ package httpmsghandlerprovider import ( + "e2mgr/clients" "e2mgr/configuration" "e2mgr/e2managererrors" "e2mgr/handlers/httpmsghandlers" @@ -47,18 +48,18 @@ type IncomingRequestHandlerProvider struct { logger *logger.Logger } -func NewIncomingRequestHandlerProvider(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager, e2tInstancesManager managers.IE2TInstancesManager, e2tAssociationManager *managers.E2TAssociationManager) *IncomingRequestHandlerProvider { +func NewIncomingRequestHandlerProvider(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager, e2tInstancesManager managers.IE2TInstancesManager, e2tAssociationManager *managers.E2TAssociationManager, rmClient clients.IRoutingManagerClient) *IncomingRequestHandlerProvider { return &IncomingRequestHandlerProvider{ - requestMap: initRequestHandlerMap(logger, rmrSender, config, rNibDataService, ranSetupManager, e2tInstancesManager, e2tAssociationManager), + requestMap: initRequestHandlerMap(logger, rmrSender, config, rNibDataService, ranSetupManager, e2tInstancesManager, e2tAssociationManager, rmClient), logger: logger, } } -func initRequestHandlerMap(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager, e2tInstancesManager managers.IE2TInstancesManager, e2tAssociationManager *managers.E2TAssociationManager) map[IncomingRequest]httpmsghandlers.RequestHandler { +func initRequestHandlerMap(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager, e2tInstancesManager managers.IE2TInstancesManager, e2tAssociationManager *managers.E2TAssociationManager, rmClient clients.IRoutingManagerClient) map[IncomingRequest]httpmsghandlers.RequestHandler { return map[IncomingRequest]httpmsghandlers.RequestHandler{ - ShutdownRequest: httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrSender, config, rNibDataService), //TODO change to pointer + ShutdownRequest: httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrSender, config, rNibDataService, e2tInstancesManager, rmClient), ResetRequest: httpmsghandlers.NewX2ResetRequestHandler(logger, rmrSender, rNibDataService), X2SetupRequest: httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, e2tInstancesManager, e2tAssociationManager), EndcSetupRequest: httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, e2tInstancesManager, e2tAssociationManager), diff --git a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go index 2d223b8..e06105f 100644 --- a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go +++ b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go @@ -57,7 +57,7 @@ func setupTest(t *testing.T) *IncomingRequestHandlerProvider { httpClientMock := &mocks.HttpClientMock{} rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock) e2tAssociationManager := managers.NewE2TAssociationManager(log, rnibDataService, e2tInstancesManager, rmClient) - return NewIncomingRequestHandlerProvider(log, rmrSender, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManager, e2tAssociationManager) + return NewIncomingRequestHandlerProvider(log, rmrSender, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManager, e2tAssociationManager, rmClient) } func TestNewIncomingRequestHandlerProvider(t *testing.T) { diff --git a/E2Manager/stateMachine/delete_all_node_state_machine.go b/E2Manager/stateMachine/delete_all_node_state_machine.go deleted file mode 100644 index eafd6c6..0000000 --- a/E2Manager/stateMachine/delete_all_node_state_machine.go +++ /dev/null @@ -1,43 +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 stateMachine - -import ( - "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" -) - - -var nodeStateMap = map[entities.ConnectionStatus]entities.ConnectionStatus{ - entities.ConnectionStatus_CONNECTING: entities.ConnectionStatus_SHUTTING_DOWN, - entities.ConnectionStatus_CONNECTED: entities.ConnectionStatus_SHUTTING_DOWN, - entities.ConnectionStatus_CONNECTED_SETUP_FAILED: entities.ConnectionStatus_SHUTTING_DOWN, - entities.ConnectionStatus_DISCONNECTED: entities.ConnectionStatus_SHUT_DOWN, -} - -func NodeNextStateDeleteAll(state entities.ConnectionStatus) (entities.ConnectionStatus, bool) { - nextState, error := nodeStateMap[state] - - if !error { - return state, false - } - - return nextState, true -} diff --git a/E2Manager/stateMachine/delete_all_node_state_machine_test.go b/E2Manager/stateMachine/delete_all_node_state_machine_test.go deleted file mode 100644 index 035bd35..0000000 --- a/E2Manager/stateMachine/delete_all_node_state_machine_test.go +++ /dev/null @@ -1,33 +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 stateMachine - -import ( - "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestNodeNextStateDeleteAll(t *testing.T) { - - _, result := NodeNextStateDeleteAll(entities.ConnectionStatus_UNKNOWN_CONNECTION_STATUS) - - assert.False(t, result) -} -- 2.16.6 From 32d7f427aab3ca627b8c9c5ded15b9517200cde3 Mon Sep 17 00:00:00 2001 From: is005q Date: Thu, 2 Jan 2020 16:23:06 +0200 Subject: [PATCH 11/16] [RICPLT-2590] RedButton flow changes + Automation Change-Id: I3109fc7c43576948accdaff29f825a40e9a8d193 Signed-off-by: is005q --- .../Tests/ENDC-Setup/ENDC_Setup_request_test.robot | 2 +- .../resource_status_false_start.robot | 1 + .../resource_status_true_start.robot | 1 + .../Tests/RedButton/RedButton_CONNECTED.robot | 32 +++------- .../RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot | 48 ++++---------- .../RedButton/RedButton_CONNECTION_FAILURE.robot | 28 +++------ .../Tests/RedButton/RedButton_DISCONNECTED.robot | 20 ++---- .../RedButton/RedButton_SHUTDOWN_SHUTDOWN.robot | 40 ++++-------- .../Tests/RedButton/red_button_keywords.robot | 73 ++++++++++++++++++++++ Automation/Tests/Resource/Keywords.robot | 10 +-- E2Manager/controllers/nodeb_controller_test.go | 13 ++++ .../httpmsghandlers/delete_all_request_handler.go | 32 +++++++--- .../delete_all_request_handler_test.go | 73 +++++++++++++++++++--- .../models/red_button_partial_success_response.go | 48 ++++++++++++++ 14 files changed, 271 insertions(+), 150 deletions(-) create mode 100644 Automation/Tests/RedButton/red_button_keywords.robot create mode 100644 E2Manager/models/red_button_partial_success_response.go diff --git a/Automation/Tests/ENDC-Setup/ENDC_Setup_request_test.robot b/Automation/Tests/ENDC-Setup/ENDC_Setup_request_test.robot index 13ef989..3397099 100644 --- a/Automation/Tests/ENDC-Setup/ENDC_Setup_request_test.robot +++ b/Automation/Tests/ENDC-Setup/ENDC_Setup_request_test.robot @@ -40,7 +40,7 @@ Run Endc setup request Get request gnb Sleep 1s - Get Request node b enb test2 + Get Request node b gnb test2 Integer response status 200 String response body ranName test2 String response body ip ${ip_e2adapter} diff --git a/Automation/Tests/RSM_Resource_Status/resource_status_false_start.robot b/Automation/Tests/RSM_Resource_Status/resource_status_false_start.robot index e6b969a..cf34c1f 100644 --- a/Automation/Tests/RSM_Resource_Status/resource_status_false_start.robot +++ b/Automation/Tests/RSM_Resource_Status/resource_status_false_start.robot @@ -40,6 +40,7 @@ Put Http Start Request To RSM Integer response status 204 Verify RSM RAN Info Status Is Start And True In Redis + Sleep 1s ${result}= rsmscripts.verify_rsm_ran_info_start_true Should Be Equal As Strings ${result} True diff --git a/Automation/Tests/RSM_Resource_Status/resource_status_true_start.robot b/Automation/Tests/RSM_Resource_Status/resource_status_true_start.robot index 21f9217..2e40459 100644 --- a/Automation/Tests/RSM_Resource_Status/resource_status_true_start.robot +++ b/Automation/Tests/RSM_Resource_Status/resource_status_true_start.robot @@ -38,6 +38,7 @@ Put Http Start Request To RSM Integer response status 204 Verify RSM RAN Info Status Is Start And True In Redis + Sleep 1s ${result}= rsmscripts.verify_rsm_ran_info_start_true Should Be Equal As Strings ${result} True diff --git a/Automation/Tests/RedButton/RedButton_CONNECTED.robot b/Automation/Tests/RedButton/RedButton_CONNECTED.robot index 9ef7430..ed75f4c 100644 --- a/Automation/Tests/RedButton/RedButton_CONNECTED.robot +++ b/Automation/Tests/RedButton/RedButton_CONNECTED.robot @@ -22,8 +22,9 @@ *** Settings *** Suite Setup Prepare Enviorment -Resource ../Resource/resource.robot -Resource ../Resource/Keywords.robot +Resource ../Resource/resource.robot +Resource ../Resource/Keywords.robot +Resource red_button_keywords.robot Library OperatingSystem Library Collections Library REST ${url} @@ -31,27 +32,12 @@ Library REST ${url} *** Test Cases *** -Prepare Ran in Connected connectionStatus - Post Request setup node b x-2 - Integer response status 204 - Sleep 1s - GET /v1/nodeb/test1 - Integer response status 200 - String response body ranName test1 - String response body connectionStatus CONNECTED +Execute X2 setup, verify nodeb connection status is CONNECTED and it's associated to an e2t instance + Execute setup and verify connected and associated +Execute Shutdown + Execute Shutdown -Disconnect Ran - PUT /v1/nodeb/shutdown - Integer response status 204 - - - -Verfiy Shutdown ConnectionStatus - Sleep 1s - GET /v1/nodeb/test1 - Integer response status 200 - String response body ranName test1 - String response body connectionStatus SHUT_DOWN - +Verify nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance + Verify shutdown for enb diff --git a/Automation/Tests/RedButton/RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot b/Automation/Tests/RedButton/RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot index 04dee6d..4c9c974 100644 --- a/Automation/Tests/RedButton/RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot +++ b/Automation/Tests/RedButton/RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot @@ -24,50 +24,24 @@ Suite Setup Prepare Enviorment Resource ../Resource/resource.robot Resource ../Resource/Keywords.robot +Resource red_button_keywords.robot Library OperatingSystem Library Collections Library REST ${url} - - *** Test Cases *** -Prepare Ran in Connected connectionStatus - Post Request setup node b x-2 - Integer response status 204 - Sleep 1s - GET /v1/nodeb/test1 - Integer response status 200 - String response body ranName test1 - String response body connectionStatus CONNECTED - - -Disconnect Ran - PUT /v1/nodeb/shutdown - Integer response status 204 - - - -Verfiy Shutdown ConnectionStatus - Sleep 1s - GET /v1/nodeb/test1 - Integer response status 200 - String response body ranName test1 - String response body connectionStatus SHUT_DOWN - -Restart simualtor - Restart simulator - -repare Ran in Connected connectionStatus - Post Request setup node b x-2 - Integer response status 204 - Sleep 1s - GET /v1/nodeb/test1 - Integer response status 200 - String response body ranName test1 - String response body connectionStatus CONNECTED - +Execute X2 setup, verify nodeb connection status is CONNECTED and it's associated to an e2t instance + Execute setup and verify connected and associated +Execute Shutdown + Execute Shutdown +Verify nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance + Verify shutdown for enb +Restart simulator + Restart simulator +Execute second X2 setup, verify nodeb connection status is CONNECTED and it's associated to an e2t instance + Execute setup and verify connected and associated \ No newline at end of file diff --git a/Automation/Tests/RedButton/RedButton_CONNECTION_FAILURE.robot b/Automation/Tests/RedButton/RedButton_CONNECTION_FAILURE.robot index 37865e4..0b96a94 100644 --- a/Automation/Tests/RedButton/RedButton_CONNECTION_FAILURE.robot +++ b/Automation/Tests/RedButton/RedButton_CONNECTION_FAILURE.robot @@ -24,6 +24,7 @@ Suite Setup Prepare Enviorment Resource ../Resource/resource.robot Resource ../Resource/Keywords.robot +Resource red_button_keywords.robot Library OperatingSystem Library Collections Library REST ${url} @@ -31,27 +32,12 @@ Library REST ${url} *** Test Cases *** -Prepare Ran in CONNECTION FAILURE connectionStatus - Set Headers ${header} - POST /v1/nodeb/x2-setup ${json} - Sleep 1s - POST /v1/nodeb/x2-setup ${json} - Sleep 1s - GET /v1/nodeb/test1 - Integer response status 200 - String response body connectionStatus CONNECTED_SETUP_FAILED +Execute X2 setup twice and verify its connection status is CONNECTED_SETUP_FAILED + Execute setup twice and verify connected setup failed -Disconnect Ran - PUT /v1/nodeb/shutdown - Integer response status 204 - - - -Verfiy Shutdown ConnectionStatus - Sleep 1s - GET /v1/nodeb/test1 - Integer response status 200 - String response body ranName test1 - String response body connectionStatus SHUT_DOWN +Execute Shutdown + Execute Shutdown +Verify nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance + Verify shutdown for enb diff --git a/Automation/Tests/RedButton/RedButton_DISCONNECTED.robot b/Automation/Tests/RedButton/RedButton_DISCONNECTED.robot index 547d14b..1156bd2 100644 --- a/Automation/Tests/RedButton/RedButton_DISCONNECTED.robot +++ b/Automation/Tests/RedButton/RedButton_DISCONNECTED.robot @@ -23,6 +23,7 @@ Suite Setup Prepare Enviorment Resource ../Resource/resource.robot Resource ../Resource/Keywords.robot +Resource red_button_keywords.robot Library OperatingSystem Library Collections Library REST ${url} @@ -30,8 +31,6 @@ Library REST ${url} *** Variables *** ${stop_docker_e2} docker stop e2adapter - - *** Test Cases *** Pre Condition for Connecting - no E2ADAPTER @@ -39,7 +38,6 @@ Pre Condition for Connecting - no E2ADAPTER ${result}= Run And Return Rc And Output ${docker_command} Should Be Equal As Integers ${result[1]} ${docker_number-1} - Prepare Ran in Connecting connectionStatus Post Request setup node b endc-setup Integer response status 204 @@ -49,16 +47,8 @@ Prepare Ran in Connecting connectionStatus String response body ranName test2 String response body connectionStatus DISCONNECTED -Disconnect Ran - PUT /v1/nodeb/shutdown - Integer response status 204 - - - -Verfiy Shutdown ConnectionStatus - Sleep 1s - GET /v1/nodeb/test2 - Integer response status 200 - String response body ranName test2 - String response body connectionStatus SHUT_DOWN +Execute Shutdown + Execute Shutdown +Verify nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance + Verify shutdown for gnb \ No newline at end of file diff --git a/Automation/Tests/RedButton/RedButton_SHUTDOWN_SHUTDOWN.robot b/Automation/Tests/RedButton/RedButton_SHUTDOWN_SHUTDOWN.robot index b498646..f97e384 100644 --- a/Automation/Tests/RedButton/RedButton_SHUTDOWN_SHUTDOWN.robot +++ b/Automation/Tests/RedButton/RedButton_SHUTDOWN_SHUTDOWN.robot @@ -24,42 +24,24 @@ Suite Setup Prepare Enviorment Resource ../Resource/resource.robot Resource ../Resource/Keywords.robot +Resource red_button_keywords.robot Library OperatingSystem Library Collections Library REST ${url} - *** Test Cases *** -Prepare Ran in Connected connectionStatus - Post Request setup node b x-2 - Integer response status 204 - Sleep 1s - GET /v1/nodeb/test1 - Integer response status 200 - String response body ranName test1 - String response body connectionStatus CONNECTED - -Disconnect Ran - PUT /v1/nodeb/shutdown - Integer response status 204 - -Verfiy Shutdown ConnectionStatus - Sleep 1s - GET /v1/nodeb/test1 - Integer response status 200 - String response body ranName test1 - String response body connectionStatus SHUT_DOWN +Execute X2 setup, verify nodeb connection status is CONNECTED and it's associated to an e2t instance + Execute setup and verify connected and associated -Disconnect Ran on shutdown Status - PUT /v1/nodeb/shutdown - Integer response status 204 +Execute Shutdown + Execute Shutdown -Verfiy Shutdown ConnectionStatus second time - Sleep 1s - GET /v1/nodeb/test1 - Integer response status 200 - String response body ranName test1 - String response body connectionStatus SHUT_DOWN +Verify nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance + Verify shutdown for enb +Execute second Shutdown + Execute Shutdown +Verify again nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance + Verify shutdown for enb \ No newline at end of file diff --git a/Automation/Tests/RedButton/red_button_keywords.robot b/Automation/Tests/RedButton/red_button_keywords.robot new file mode 100644 index 0000000..34bd6ef --- /dev/null +++ b/Automation/Tests/RedButton/red_button_keywords.robot @@ -0,0 +1,73 @@ +############################################################################## +# +# Copyright (c) 2019 AT&T Intellectual Property. +# +# 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. +# +############################################################################## + +*** Settings *** +Documentation Keywords file +Resource ../Resource/resource.robot +Resource ../Resource/Keywords.robot +Library ../Scripts/e2mdbscripts.py +Library Collections +Library OperatingSystem +Library json +Library REST ${url} + +*** Keywords *** +Execute setup and verify connected and associated + Post Request setup node b x-2 + Integer response status 204 + Get Request node b enb test1 + Integer response status 200 + String response body ranName test1 + String response body connectionStatus CONNECTED + String response body associatedE2tInstanceAddress e2t.att.com:38000 + +Execute setup twice and verify connected setup failed + Post Request setup node b x-2 + Sleep 1s + Post Request setup node b x-2 + Get Request node b enb test1 + String response body connectionStatus CONNECTED_SETUP_FAILED + + +Verify shutdown for enb + Get Request node b enb test1 + Integer response status 200 + String response body ranName test1 + String response body connectionStatus SHUT_DOWN + Missing response body associatedE2tInstanceAddress + ${result} e2mdbscripts.verify_ran_is_associated_with_e2t_instance test1 e2t.att.com:38000 + Should Be True ${result} == False + + +Verify shutdown for gnb + Get Request node b gnb test2 + Integer response status 200 + String response body ranName test2 + String response body connectionStatus SHUT_DOWN + Missing response body associatedE2tInstanceAddress + ${result} e2mdbscripts.verify_ran_is_associated_with_e2t_instance test2 e2t.att.com:38000 + Should Be True ${result} == False + +Execute Shutdown + PUT /v1/nodeb/shutdown + Integer response status 204 + + + + + diff --git a/Automation/Tests/Resource/Keywords.robot b/Automation/Tests/Resource/Keywords.robot index 0f24653..1022890 100644 --- a/Automation/Tests/Resource/Keywords.robot +++ b/Automation/Tests/Resource/Keywords.robot @@ -26,21 +26,15 @@ Library ../Scripts/cleanup_db.py Resource ../Resource/resource.robot Library OperatingSystem - - - - *** Keywords *** Post Request setup node b x-2 Set Headers ${header} POST /v1/nodeb/x2-setup ${json} - Put Request Resource Status Start Set Headers ${header} PUT /v1/general/resourcestatus ${resource_status_start_json} - Put Request Resource Status Stop Set Headers ${header} PUT /v1/general/resourcestatus ${resource_status_stop_json} @@ -49,12 +43,10 @@ Get Request node b enb test1 Sleep 1s GET /v1/nodeb/test1 - -Get Request node b enb test2 +Get Request node b gnb test2 Sleep 1s GET /v1/nodeb/test2 - Remove log files Remove File ${EXECDIR}/${gnb_log_filename} Remove File ${EXECDIR}/${e2mgr_log_filename} diff --git a/E2Manager/controllers/nodeb_controller_test.go b/E2Manager/controllers/nodeb_controller_test.go index 726e8c3..88983f4 100644 --- a/E2Manager/controllers/nodeb_controller_test.go +++ b/E2Manager/controllers/nodeb_controller_test.go @@ -345,6 +345,19 @@ func TestHandleCommandAlreadyInProgressError(t *testing.T) { assert.Equal(t, errorResponse.Message, err.Message) } +func TestHandleRoutingManagerError(t *testing.T) { + controller, _, _, _, _ := setupControllerTest(t) + writer := httptest.NewRecorder() + err := e2managererrors.NewRoutingManagerError() + + controller.handleErrorResponse(err, writer) + var errorResponse = parseJsonRequest(t, writer.Body) + + assert.Equal(t, http.StatusServiceUnavailable, writer.Result().StatusCode) + assert.Equal(t, errorResponse.Code, err.Code) + assert.Equal(t, errorResponse.Message, err.Message) +} + func TestHandleE2TInstanceAbsenceError(t *testing.T) { controller, _, _, _, _ := setupControllerTest(t) diff --git a/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go b/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go index 7edc13c..869890a 100644 --- a/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go +++ b/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go @@ -67,9 +67,9 @@ func (h *DeleteAllRequestHandler) Handle(request models.Request) (models.IRespon return nil, err } - err = h.rmClient.DissociateAllRans(e2tAddresses) + dissocErr := h.rmClient.DissociateAllRans(e2tAddresses) - if err != nil { + if dissocErr != nil { h.logger.Warnf("#DeleteAllRequestHandler.Handle - routing manager failure. continue flow.") } @@ -95,6 +95,11 @@ func (h *DeleteAllRequestHandler) Handle(request models.Request) (models.IRespon } if allRansAreShutDown { + + if dissocErr != nil { + return models.NewRedButtonPartialSuccessResponseModel("Operation succeeded, except Routing Manager failure"), nil + } + return nil, nil } @@ -102,7 +107,16 @@ func (h *DeleteAllRequestHandler) Handle(request models.Request) (models.IRespon h.logger.Infof("#DeleteAllRequestHandler.Handle - timer expired") err, _ = h.updateNodebs(h.updateNodebInfoShutDown) - return nil, err + + if err != nil { + return nil, err + } + + if dissocErr != nil { + return models.NewRedButtonPartialSuccessResponseModel("Operation succeeded, except Routing Manager failure"), nil + } + + return nil, nil } func (h *DeleteAllRequestHandler) updateNodebs(updateCb func(node *entities.NodebInfo) error) (error, bool) { @@ -120,14 +134,18 @@ func (h *DeleteAllRequestHandler) updateNodebs(updateCb func(node *entities.Node if err != nil { h.logger.Errorf("#DeleteAllRequestHandler.updateNodebs - failed to get nodeB entity for ran name: %s from rNib. error: %s", nbIdentity.InventoryName, err) - continue + return e2managererrors.NewRnibDbError(), false } if node.ConnectionStatus != entities.ConnectionStatus_SHUT_DOWN { allRansAreShutdown = false } - _ = updateCb(node) + err = updateCb(node) + + if err != nil { + return err, false + } } return nil, allRansAreShutdown @@ -169,8 +187,8 @@ func (h *DeleteAllRequestHandler) updateNodebInfo(node *entities.NodebInfo, conn err := h.rnibDataService.UpdateNodebInfo(node) if err != nil { - h.logger.Errorf("#DeleteAllRequestHandler.updateNodebInfo - RAN name: %s - failed saving nodeB entity to rNib. error: %s", node.RanName, err) - return err + h.logger.Errorf("#DeleteAllRequestHandler.updateNodebInfo - RAN name: %s - failed updating nodeB entity in rNib. error: %s", node.RanName, err) + return e2managererrors.NewRnibDbError() } h.logger.Infof("#DeleteAllRequestHandler.updateNodebInfo - RAN name: %s, connection status: %s", node.RanName, connectionStatus) diff --git a/E2Manager/handlers/httpmsghandlers/delete_all_request_handler_test.go b/E2Manager/handlers/httpmsghandlers/delete_all_request_handler_test.go index 5332bd9..9b8731c 100644 --- a/E2Manager/handlers/httpmsghandlers/delete_all_request_handler_test.go +++ b/E2Manager/handlers/httpmsghandlers/delete_all_request_handler_test.go @@ -90,7 +90,7 @@ func mockHttpClientDissociateAllRans(httpClientMock *mocks.HttpClientMock, e2tAd func TestGetE2TAddressesFailure(t *testing.T) { h, readerMock, _, _, _ := setupDeleteAllRequestHandlerTest(t) - readerMock.On("GetE2TAddresses").Return([]string{}, e2managererrors.NewRnibDbError()) + readerMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("error"))) _, err := h.Handle(nil) assert.IsType(t, &e2managererrors.RnibDbError{}, err) readerMock.AssertExpectations(t) @@ -123,7 +123,7 @@ func TestTwoRansGetE2TAddressesEmptyListOneGetNodebFailure(t *testing.T) { var nb2 *entities.NodebInfo readerMock.On("GetNodeb", "RanName_2").Return(nb2, common.NewInternalError(errors.New("error"))) _, err := h.Handle(nil) - assert.Nil(t, err) + assert.IsType(t,&e2managererrors.RnibDbError{}, err) writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) readerMock.AssertExpectations(t) } @@ -144,7 +144,7 @@ func TestTwoRansGetE2TAddressesEmptyListOneUpdateNodebInfoFailure(t *testing.T) updatedNb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,} writerMock.On("UpdateNodebInfo", updatedNb2).Return(common.NewInternalError(errors.New("error"))) _, err := h.Handle(nil) - assert.Nil(t, err) + assert.IsType(t,&e2managererrors.RnibDbError{}, err) readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) } @@ -223,11 +223,11 @@ func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSendFails(t *testing.T) { writerMock.AssertExpectations(t) } -func TestTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdown(t *testing.T) { +func testTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdown(t *testing.T, partial bool) { h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t) e2tAddresses := []string{E2TAddress} readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) - mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true) + mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, !partial) nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}} readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN} @@ -244,13 +244,28 @@ func TestTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdow rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL} mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction) rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil) - _, err := h.Handle(nil) + resp, err := h.Handle(nil) assert.Nil(t, err) + + if partial { + assert.IsType(t, &models.RedButtonPartialSuccessResponseModel{}, resp) + } else { + assert.Nil(t, resp) + } + rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true) readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) } +func TestTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdownSuccess(t *testing.T) { + testTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdown(t, false) +} + +func TestTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdownPartialSuccess(t *testing.T) { + testTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdown(t, true) +} + //func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsAlreadyShutdown(t *testing.T) { // h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t) // e2tAddresses := []string{E2TAddress} @@ -285,11 +300,45 @@ func TestTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdow // writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) //} -func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDown(t *testing.T) { +//func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDownUpdateFailure(t *testing.T) { +// h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t) +// e2tAddresses := []string{E2TAddress} +// readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) +// mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true) +// nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}} +// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) +// //nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress} +// //readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) +// updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,} +// writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil) +// readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil) +// e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}} +// readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil) +// updatedE2tInstance := e2tInstance +// updatedE2tInstance.AssociatedRanList = []string{} +// writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil) +// +// rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL} +// mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction) +// rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil) +// +// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) +// readerMock.On("GetNodeb", "RanName_1").Return(updatedNb1, nil) +// updatedNb2 := *updatedNb1 +// updatedNb2.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN +// writerMock.On("UpdateNodebInfo", &updatedNb2).Return(common.NewInternalError(errors.New("error"))) +// _, err := h.Handle(nil) +// assert.IsType(t,&e2managererrors.RnibDbError{}, err) +// rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true) +// readerMock.AssertExpectations(t) +// writerMock.AssertExpectations(t) +//} + +func testOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDown(t *testing.T, partial bool) { h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t) e2tAddresses := []string{E2TAddress} readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) - mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true) + mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, !partial) nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}} readerMock.On("GetListNodebIds").Return(nbIdentityList, nil) //nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress} @@ -319,6 +368,14 @@ func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttin writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) } +func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDownSuccess (t *testing.T) { + testOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDown(t, false) +} + +func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDownPartialSuccess (t *testing.T) { + testOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDown(t, true) +} + func TestSuccessTwoE2TInstancesSixRans(t *testing.T) { h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t) e2tAddresses := []string{E2TAddress, E2TAddress2} diff --git a/E2Manager/models/red_button_partial_success_response.go b/E2Manager/models/red_button_partial_success_response.go new file mode 100644 index 0000000..115bcef --- /dev/null +++ b/E2Manager/models/red_button_partial_success_response.go @@ -0,0 +1,48 @@ +// +// 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 ( + "e2mgr/e2managererrors" + "encoding/json" +) + +type RedButtonPartialSuccessResponseModel struct { + Message string `json:"message"` +} + +func NewRedButtonPartialSuccessResponseModel(message string) *RedButtonPartialSuccessResponseModel { + return &RedButtonPartialSuccessResponseModel{ + Message: message, + } +} + +func (response RedButtonPartialSuccessResponseModel) Marshal() ([]byte, error) { + + data, err := json.Marshal(response) + + if err != nil { + return nil, e2managererrors.NewInternalError() + } + + return data, nil + +} -- 2.16.6 From 5c9533257e79cc65d506df54105933bf5844e7ab Mon Sep 17 00:00:00 2001 From: is005q Date: Sun, 5 Jan 2020 16:22:47 +0200 Subject: [PATCH 12/16] [RICPLT-2590] US completion........ Change-Id: I887014d126485201f526d1e7ff03cc2e82e097b9 Signed-off-by: is005q --- .../Tests/RedButton/RedButton_CONNECTED.robot | 3 + .../RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot | 3 + .../RedButton/RedButton_CONNECTION_FAILURE.robot | 4 ++ .../Tests/RedButton/RedButton_DISCONNECTED.robot | 5 +- .../RedButton/RedButton_SHUTDOWN_SHUTDOWN.robot | 9 ++- .../Tests/RedButton/red_button_keywords.robot | 8 +-- Automation/Tests/Scripts/e2mdbscripts.py | 8 +++ E2Manager/configuration/configuration_test.go | 4 +- .../httpmsghandlers/delete_all_request_handler.go | 73 +++++++++++++++------- E2Manager/managers/e2t_instances_manager.go | 2 +- E2Manager/resources/configuration.yaml | 4 +- E2Manager/services/rnib_data_service.go | 11 +++- 12 files changed, 97 insertions(+), 37 deletions(-) diff --git a/Automation/Tests/RedButton/RedButton_CONNECTED.robot b/Automation/Tests/RedButton/RedButton_CONNECTED.robot index ed75f4c..6a0f312 100644 --- a/Automation/Tests/RedButton/RedButton_CONNECTED.robot +++ b/Automation/Tests/RedButton/RedButton_CONNECTED.robot @@ -41,3 +41,6 @@ Execute Shutdown Verify nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance Verify shutdown for enb +Verify E2T instance has no associated RANs + Verify E2T instance has no associated RANs + diff --git a/Automation/Tests/RedButton/RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot b/Automation/Tests/RedButton/RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot index 4c9c974..cbb02b4 100644 --- a/Automation/Tests/RedButton/RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot +++ b/Automation/Tests/RedButton/RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot @@ -40,6 +40,9 @@ Execute Shutdown Verify nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance Verify shutdown for enb +Verify E2T instance has no associated RANs + Verify E2T instance has no associated RANs + Restart simulator Restart simulator diff --git a/Automation/Tests/RedButton/RedButton_CONNECTION_FAILURE.robot b/Automation/Tests/RedButton/RedButton_CONNECTION_FAILURE.robot index 0b96a94..291171a 100644 --- a/Automation/Tests/RedButton/RedButton_CONNECTION_FAILURE.robot +++ b/Automation/Tests/RedButton/RedButton_CONNECTION_FAILURE.robot @@ -41,3 +41,7 @@ Execute Shutdown Verify nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance Verify shutdown for enb +Verify E2T instance has no associated RANs + Verify E2T instance has no associated RANs + + diff --git a/Automation/Tests/RedButton/RedButton_DISCONNECTED.robot b/Automation/Tests/RedButton/RedButton_DISCONNECTED.robot index 1156bd2..7bf7c82 100644 --- a/Automation/Tests/RedButton/RedButton_DISCONNECTED.robot +++ b/Automation/Tests/RedButton/RedButton_DISCONNECTED.robot @@ -51,4 +51,7 @@ Execute Shutdown Execute Shutdown Verify nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance - Verify shutdown for gnb \ No newline at end of file + Verify shutdown for gnb + +Verify E2T instance has no associated RANs + Verify E2T instance has no associated RANs diff --git a/Automation/Tests/RedButton/RedButton_SHUTDOWN_SHUTDOWN.robot b/Automation/Tests/RedButton/RedButton_SHUTDOWN_SHUTDOWN.robot index f97e384..fbab47b 100644 --- a/Automation/Tests/RedButton/RedButton_SHUTDOWN_SHUTDOWN.robot +++ b/Automation/Tests/RedButton/RedButton_SHUTDOWN_SHUTDOWN.robot @@ -40,8 +40,15 @@ Execute Shutdown Verify nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance Verify shutdown for enb +Verify E2T instance has no associated RANs + Verify E2T instance has no associated RANs + + Execute second Shutdown Execute Shutdown Verify again nodeb's connection status is SHUT_DOWN and it's NOT associated to an e2t instance - Verify shutdown for enb \ No newline at end of file + Verify shutdown for enb + +Verify again E2T instance has no associated RANs + Verify E2T instance has no associated RANs diff --git a/Automation/Tests/RedButton/red_button_keywords.robot b/Automation/Tests/RedButton/red_button_keywords.robot index 34bd6ef..c743543 100644 --- a/Automation/Tests/RedButton/red_button_keywords.robot +++ b/Automation/Tests/RedButton/red_button_keywords.robot @@ -50,8 +50,6 @@ Verify shutdown for enb String response body ranName test1 String response body connectionStatus SHUT_DOWN Missing response body associatedE2tInstanceAddress - ${result} e2mdbscripts.verify_ran_is_associated_with_e2t_instance test1 e2t.att.com:38000 - Should Be True ${result} == False Verify shutdown for gnb @@ -60,8 +58,10 @@ Verify shutdown for gnb String response body ranName test2 String response body connectionStatus SHUT_DOWN Missing response body associatedE2tInstanceAddress - ${result} e2mdbscripts.verify_ran_is_associated_with_e2t_instance test2 e2t.att.com:38000 - Should Be True ${result} == False + +Verify E2T instance has no associated RANs + ${result} e2mdbscripts.verify_e2t_instance_has_no_associated_rans e2t.att.com:38000 + Should Be True ${result} Execute Shutdown PUT /v1/nodeb/shutdown diff --git a/Automation/Tests/Scripts/e2mdbscripts.py b/Automation/Tests/Scripts/e2mdbscripts.py index 6753f80..936346b 100644 --- a/Automation/Tests/Scripts/e2mdbscripts.py +++ b/Automation/Tests/Scripts/e2mdbscripts.py @@ -33,6 +33,14 @@ def verify_ran_is_associated_with_e2t_instance(ranName, e2tAddress): assocRanList = e2tInstanceDic.get("associatedRanList") return ranName in assocRanList +def verify_e2t_instance_has_no_associated_rans(e2tAddress): + r = getRedisClientDecodeResponse() + e2tInstanceJson = r.get("{e2Manager},E2TInstance:"+e2tAddress) + e2tInstanceDic = json.loads(e2tInstanceJson) + assocRanList = e2tInstanceDic.get("associatedRanList") + return not assocRanList + + def populate_e2t_instances_in_e2m_db_for_get_e2t_instances_tc(): r = getRedisClientDecodeResponse() r.set("{e2Manager},E2TAddresses", "[\"e2t.att.com:38000\",\"e2t.att.com:38001\"]") diff --git a/E2Manager/configuration/configuration_test.go b/E2Manager/configuration/configuration_test.go index ec16c1f..b83c661 100644 --- a/E2Manager/configuration/configuration_test.go +++ b/E2Manager/configuration/configuration_test.go @@ -36,8 +36,8 @@ func TestParseConfigurationSuccess(t *testing.T) { assert.Equal(t, "info", config.Logging.LogLevel) assert.Equal(t, 100, config.NotificationResponseBuffer) assert.Equal(t, 5, config.BigRedButtonTimeoutSec) - assert.Equal(t, 1500, config.KeepAliveResponseTimeoutMs) - assert.Equal(t, 500, config.KeepAliveDelayMs) + assert.Equal(t, 4500, config.KeepAliveResponseTimeoutMs) + assert.Equal(t, 1500, config.KeepAliveDelayMs) } func TestParseConfigurationFileNotFoundFailure(t *testing.T) { diff --git a/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go b/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go index 869890a..975640a 100644 --- a/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go +++ b/E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go @@ -30,6 +30,7 @@ import ( "e2mgr/rmrCgo" "e2mgr/services" "e2mgr/services/rmrsender" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" "time" ) @@ -43,6 +44,8 @@ type DeleteAllRequestHandler struct { rmClient clients.IRoutingManagerClient } +const PartialSuccessDueToRmErrorMessage = "Operation succeeded except for routing manager outbound call" + func NewDeleteAllRequestHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rnibDataService services.RNibDataService, e2tInstancesManager managers.IE2TInstancesManager, rmClient clients.IRoutingManagerClient) *DeleteAllRequestHandler { return &DeleteAllRequestHandler{ logger: logger, @@ -55,6 +58,7 @@ func NewDeleteAllRequestHandler(logger *logger.Logger, rmrSender *rmrsender.RmrS } func (h *DeleteAllRequestHandler) Handle(request models.Request) (models.IResponse, error) { + h.logger.Infof("#DeleteAllRequestHandler.Handle - handling shutdown request") e2tAddresses, err := h.e2tInstancesManager.GetE2TAddresses() @@ -73,7 +77,7 @@ func (h *DeleteAllRequestHandler) Handle(request models.Request) (models.IRespon h.logger.Warnf("#DeleteAllRequestHandler.Handle - routing manager failure. continue flow.") } - err, allRansAreShutDown := h.updateNodebs(h.updateNodebInfoShuttingDown) + err, updatedAtLeastOnce := h.updateNodebs(h.updateNodebInfoShuttingDown) if err != nil { return nil, err @@ -94,10 +98,11 @@ func (h *DeleteAllRequestHandler) Handle(request models.Request) (models.IRespon return nil, e2managererrors.NewRmrError() } - if allRansAreShutDown { + if !updatedAtLeastOnce { + h.logger.Infof("#DeleteAllRequestHandler.Handle - DB wasn't updated, not activating timer") if dissocErr != nil { - return models.NewRedButtonPartialSuccessResponseModel("Operation succeeded, except Routing Manager failure"), nil + return models.NewRedButtonPartialSuccessResponseModel(PartialSuccessDueToRmErrorMessage), nil } return nil, nil @@ -113,13 +118,13 @@ func (h *DeleteAllRequestHandler) Handle(request models.Request) (models.IRespon } if dissocErr != nil { - return models.NewRedButtonPartialSuccessResponseModel("Operation succeeded, except Routing Manager failure"), nil + return models.NewRedButtonPartialSuccessResponseModel(PartialSuccessDueToRmErrorMessage), nil } return nil, nil } -func (h *DeleteAllRequestHandler) updateNodebs(updateCb func(node *entities.NodebInfo) error) (error, bool) { +func (h *DeleteAllRequestHandler) updateNodebs(updateCb func(node *entities.NodebInfo) (error, bool)) (error, bool) { nbIdentityList, err := h.rnibDataService.GetListNodebIds() if err != nil { @@ -127,54 +132,76 @@ func (h *DeleteAllRequestHandler) updateNodebs(updateCb func(node *entities.Node return e2managererrors.NewRnibDbError(), false } - allRansAreShutdown := true + updatedAtLeastOnce := false for _, nbIdentity := range nbIdentityList { node, err := h.rnibDataService.GetNodeb(nbIdentity.InventoryName) if err != nil { - h.logger.Errorf("#DeleteAllRequestHandler.updateNodebs - failed to get nodeB entity for ran name: %s from rNib. error: %s", nbIdentity.InventoryName, err) - return e2managererrors.NewRnibDbError(), false - } + _, ok := err.(*common.ResourceNotFoundError) - if node.ConnectionStatus != entities.ConnectionStatus_SHUT_DOWN { - allRansAreShutdown = false + if !ok { + h.logger.Errorf("#DeleteAllRequestHandler.updateNodebs - failed to get nodeB entity for ran name: %s from rNib. error: %s", nbIdentity.InventoryName, err) + return e2managererrors.NewRnibDbError(), false + } + continue } - err = updateCb(node) + err, updated := updateCb(node) if err != nil { return err, false } - } - return nil, allRansAreShutdown + if updated { + updatedAtLeastOnce = true + } + } + return nil, updatedAtLeastOnce } -func (h *DeleteAllRequestHandler) updateNodebInfoForceShutdown(node *entities.NodebInfo) error { - return h.updateNodebInfo(node, entities.ConnectionStatus_SHUT_DOWN, true) +func (h *DeleteAllRequestHandler) updateNodebInfoForceShutdown(node *entities.NodebInfo) (error, bool) { + err := h.updateNodebInfo(node, entities.ConnectionStatus_SHUT_DOWN, true) + + if err != nil { + return err, false + } + + return nil, true } -func (h *DeleteAllRequestHandler) updateNodebInfoShuttingDown(node *entities.NodebInfo) error { +func (h *DeleteAllRequestHandler) updateNodebInfoShuttingDown(node *entities.NodebInfo) (error, bool) { if node.ConnectionStatus == entities.ConnectionStatus_SHUT_DOWN { - return nil + return nil, false } - return h.updateNodebInfo(node, entities.ConnectionStatus_SHUTTING_DOWN, true) + err := h.updateNodebInfo(node, entities.ConnectionStatus_SHUTTING_DOWN, true) + + if err != nil { + return err, false + } + + return nil, true } -func (h *DeleteAllRequestHandler) updateNodebInfoShutDown(node *entities.NodebInfo) error { +func (h *DeleteAllRequestHandler) updateNodebInfoShutDown(node *entities.NodebInfo) (error, bool) { if node.ConnectionStatus == entities.ConnectionStatus_SHUT_DOWN { - return nil + return nil, false } if node.ConnectionStatus != entities.ConnectionStatus_SHUTTING_DOWN { h.logger.Warnf("#DeleteAllRequestHandler.updateNodebInfoShutDown - RAN name: %s - ignore, status is not Shutting Down", node.RanName) - return nil + return nil, false + } + + err := h.updateNodebInfo(node, entities.ConnectionStatus_SHUT_DOWN, false) + + if err != nil { + return err, false } - return h.updateNodebInfo(node, entities.ConnectionStatus_SHUT_DOWN, false) + return nil, true } func (h *DeleteAllRequestHandler) updateNodebInfo(node *entities.NodebInfo, connectionStatus entities.ConnectionStatus, resetAssociatedE2TAddress bool) error { diff --git a/E2Manager/managers/e2t_instances_manager.go b/E2Manager/managers/e2t_instances_manager.go index c970c76..1e12943 100644 --- a/E2Manager/managers/e2t_instances_manager.go +++ b/E2Manager/managers/e2t_instances_manager.go @@ -372,7 +372,7 @@ func (m *E2TInstancesManager) ResetKeepAliveTimestamp(e2tAddress string) error { } func (m *E2TInstancesManager) ClearRansOfAllE2TInstances() error { - + m.logger.Infof("#E2TInstancesManager.ClearRansOfAllE2TInstances - Going to clear associated RANs from E2T instances") m.mux.Lock() defer m.mux.Unlock() diff --git a/E2Manager/resources/configuration.yaml b/E2Manager/resources/configuration.yaml index 0914b88..b70ddfc 100644 --- a/E2Manager/resources/configuration.yaml +++ b/E2Manager/resources/configuration.yaml @@ -12,5 +12,5 @@ bigRedButtonTimeoutSec: 5 maxConnectionAttempts: 3 maxRnibConnectionAttempts: 3 rnibRetryIntervalMs: 10 -keepAliveResponseTimeoutMs: 1500 -keepAliveDelayMs: 500 +keepAliveResponseTimeoutMs: 4500 +keepAliveDelayMs: 1500 diff --git a/E2Manager/services/rnib_data_service.go b/E2Manager/services/rnib_data_service.go index 1274c53..1a5af59 100644 --- a/E2Manager/services/rnib_data_service.go +++ b/E2Manager/services/rnib_data_service.go @@ -101,7 +101,6 @@ func (w *rNibDataService) SaveRanLoadInformation(inventoryName string, ranLoadIn } func (w *rNibDataService) GetNodeb(ranName string) (*entities.NodebInfo, error) { - w.logger.Infof("#RnibDataService.GetNodeb - RAN name: %s", ranName) var nodeb *entities.NodebInfo = nil @@ -110,12 +109,14 @@ func (w *rNibDataService) GetNodeb(ranName string) (*entities.NodebInfo, error) return }) + if err == nil { + w.logger.Infof("#RnibDataService.GetNodeb - RAN name: %s, connection status: %s", nodeb.RanName, nodeb.ConnectionStatus) + } + return nodeb, err } func (w *rNibDataService) GetListNodebIds() ([]*entities.NbIdentity, error) { - w.logger.Infof("#RnibDataService.GetListNodebIds") - var nodeIds []*entities.NbIdentity = nil err := w.retry("GetListNodebIds", func() (err error) { @@ -123,6 +124,10 @@ func (w *rNibDataService) GetListNodebIds() ([]*entities.NbIdentity, error) { return }) + if err == nil { + w.logger.Infof("#RnibDataService.GetListNodebIds - RANs count: %d", len(nodeIds)) + } + return nodeIds, err } -- 2.16.6 From 31a781cfece23cf447792e9be4f7cbc4834a782c Mon Sep 17 00:00:00 2001 From: Irina Date: Mon, 6 Jan 2020 15:36:11 +0200 Subject: [PATCH 13/16] RICPLT-2966 - Free memory fix cgo Change-Id: Ie07be64ac104fe9cfbaa96faab8e69d0bf8d7206 Signed-off-by: Irina --- E2Manager/rmrCgo/rmrCgoApi.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/E2Manager/rmrCgo/rmrCgoApi.go b/E2Manager/rmrCgo/rmrCgoApi.go index f65d10d..308ab63 100644 --- a/E2Manager/rmrCgo/rmrCgoApi.go +++ b/E2Manager/rmrCgo/rmrCgoApi.go @@ -61,7 +61,6 @@ func (ctx *Context) SendMsg(msg *MBuf, printLogs bool) (*MBuf, error) { ctx.checkContextInitialized() ctx.Logger.Debugf("#rmrCgoApi.SendMsg - Going to send message. MBuf: %v", *msg) allocatedCMBuf := ctx.getAllocatedCRmrMBuf(ctx.Logger, msg, ctx.MaxMsgSize) - defer C.rmr_free_msg(allocatedCMBuf) state := allocatedCMBuf.state if state != RMR_OK { errorMessage := fmt.Sprintf("#rmrCgoApi.SendMsg - Failed to get allocated message. state: %v - %s", state, states[int(state)]) @@ -76,6 +75,8 @@ func (ctx *Context) SendMsg(msg *MBuf, printLogs bool) (*MBuf, error) { } currCMBuf := C.rmr_send_msg(ctx.RmrCtx, allocatedCMBuf) + defer C.rmr_free_msg(currCMBuf) + state = currCMBuf.state if state != RMR_OK { @@ -90,9 +91,10 @@ func (ctx *Context) RecvMsg() (*MBuf, error) { ctx.checkContextInitialized() ctx.Logger.Debugf("#rmrCgoApi.RecvMsg - Going to receive message") allocatedCMBuf := C.rmr_alloc_msg(ctx.RmrCtx, C.int(ctx.MaxMsgSize)) - defer C.rmr_free_msg(allocatedCMBuf) currCMBuf := C.rmr_rcv_msg(ctx.RmrCtx, allocatedCMBuf) + defer C.rmr_free_msg(currCMBuf) + state := currCMBuf.state if state != RMR_OK { @@ -121,4 +123,4 @@ func (ctx *Context) Close() { ctx.Logger.Debugf("#rmrCgoApi.Close - Going to close RMR context") C.rmr_close(ctx.RmrCtx) time.Sleep(100 * time.Millisecond) -} +} \ No newline at end of file -- 2.16.6 From 15d6212e659b90c698749608c91da4e0a43e49aa Mon Sep 17 00:00:00 2001 From: ss412g Date: Tue, 7 Jan 2020 15:08:23 +0200 Subject: [PATCH 14/16] [RICPLT-2947] - update SDL version to 0.5.2 Change-Id: I8648f7152f759a77f78ba9471a6789ff4edd37bf Signed-off-by: ss412g --- E2Manager/container-tag.yaml | 2 +- E2Manager/go.mod | 4 ++-- E2Manager/go.sum | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/E2Manager/container-tag.yaml b/E2Manager/container-tag.yaml index f256535..3a7663b 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.4 +tag: 3.0.5 diff --git a/E2Manager/go.mod b/E2Manager/go.mod index 7d2e125..720727f 100644 --- a/E2Manager/go.mod +++ b/E2Manager/go.mod @@ -4,7 +4,7 @@ require ( gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.28 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.28 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28 - gerrit.o-ran-sc.org/r/ric-plt/sdlgo v0.5.0 + 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 @@ -27,4 +27,4 @@ require ( gopkg.in/yaml.v2 v2.2.4 ) -replace gerrit.o-ran-sc.org/r/ric-plt/sdlgo => gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0 +replace gerrit.o-ran-sc.org/r/ric-plt/sdlgo => gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2 diff --git a/E2Manager/go.sum b/E2Manager/go.sum index 9c518c1..eef93ff 100644 --- a/E2Manager/go.sum +++ b/E2Manager/go.sum @@ -13,6 +13,8 @@ gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28 h1:AaYvK59fxDXQUV9NC gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28/go.mod h1:vZ/335+rRSQW82wcbc80fNNICSK3TiCqIxmkqeC2Pfo= gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0 h1:+P3XuWKSaMbzh5PNtrW9gkZlCN0hKrZq+Cn8JetwBys= gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc= +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= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -- 2.16.6 From 63249264955a37429a64ebfec7028c6a487bdf1e Mon Sep 17 00:00:00 2001 From: ss412g Date: Wed, 8 Jan 2020 10:35:01 +0200 Subject: [PATCH 15/16] Add RMR_VCTL_FILE in order to control RMR debug level Change-Id: Ie1f594fa031122ed229a83105c566b62f553b005 Signed-off-by: ss412g --- E2Manager/Dockerfile | 4 +++- E2Manager/container-tag.yaml | 2 +- E2Manager/resources/rmr.verbose | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 E2Manager/resources/rmr.verbose diff --git a/E2Manager/Dockerfile b/E2Manager/Dockerfile index 4f9561b..25a972a 100644 --- a/E2Manager/Dockerfile +++ b/E2Manager/Dockerfile @@ -58,12 +58,14 @@ RUN apt-get update && apt-get install -y \ 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 /opt/E2Manager/resources +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 WORKDIR /opt/E2Manager ENV LD_LIBRARY_PATH=/usr/local/lib \ port=3800 ENV RMR_SEED_RT=router.txt +ENV RMR_VCTL_FILE=/tmp/rmr.verbose EXPOSE 3800 CMD ["sh", "-c", "./main -port=$port"] diff --git a/E2Manager/container-tag.yaml b/E2Manager/container-tag.yaml index 3a7663b..1827a37 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 +tag: 3.0.4.1 diff --git a/E2Manager/resources/rmr.verbose b/E2Manager/resources/rmr.verbose new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/E2Manager/resources/rmr.verbose @@ -0,0 +1 @@ +1 \ No newline at end of file -- 2.16.6 From f846c5987cd35da745534e26ac3a22bdcf8b030a Mon Sep 17 00:00:00 2001 From: Amichai Date: Wed, 8 Jan 2020 16:45:07 +0200 Subject: [PATCH 16/16] [RICPLT-2584] Implementation of E2TShutdownManager + Automation fix Change-Id: I1dbc4a1d14566c2ca9882ba603e3cf77458f54dc Signed-off-by: Amichai --- Automation/Tests/KeepAlive/keep_alive_test.robot | 4 +- Automation/Tests/Resource/Keywords.robot | 5 +- Automation/Tests/Scripts/cleanup_db.py | 2 +- E2Manager/app/main.go | 4 +- E2Manager/clients/routing_manager_client.go | 6 + E2Manager/configuration/configuration.go | 2 + E2Manager/configuration/configuration_test.go | 1 + E2Manager/container-tag.yaml | 2 +- E2Manager/go.mod | 6 +- E2Manager/go.sum | 26 ++-- .../e2_term_init_notification_handler.go | 2 +- .../e2_term_init_notification_handler_test.go | 2 +- E2Manager/managers/e2t_association_manager.go | 30 ++++ E2Manager/managers/e2t_association_manager_test.go | 34 +++++ E2Manager/managers/e2t_instances_manager.go | 95 +++++++++--- E2Manager/managers/e2t_instances_manager_test.go | 88 ++++++++--- E2Manager/managers/e2t_shutdown_manager.go | 162 +++++++++++++++++++-- E2Manager/mocks/e2t_instances_manager_mock.go | 9 +- E2Manager/mocks/rnibWriterMock.go | 6 + E2Manager/mocks/routing_manager_client_mock.go | 6 + E2Manager/rNibWriter/rNibWriter.go | 15 ++ E2Manager/rNibWriter/rNibWriter_test.go | 33 +++++ E2Manager/resources/configuration.yaml | 1 + E2Manager/services/rnib_data_service.go | 12 ++ 24 files changed, 470 insertions(+), 83 deletions(-) diff --git a/Automation/Tests/KeepAlive/keep_alive_test.robot b/Automation/Tests/KeepAlive/keep_alive_test.robot index ac226a2..1208b23 100644 --- a/Automation/Tests/KeepAlive/keep_alive_test.robot +++ b/Automation/Tests/KeepAlive/keep_alive_test.robot @@ -1,4 +1,4 @@ -############################################################################## +robot############################################################################## # # Copyright (c) 2019 AT&T Intellectual Property. # @@ -29,7 +29,7 @@ Library Collections Stop E2T stop_e2 - Sleep 1s + Sleep 3s Prepare logs for tests Remove log files diff --git a/Automation/Tests/Resource/Keywords.robot b/Automation/Tests/Resource/Keywords.robot index 1022890..eea1ce6 100644 --- a/Automation/Tests/Resource/Keywords.robot +++ b/Automation/Tests/Resource/Keywords.robot @@ -85,6 +85,7 @@ Prepare Simulator For Load Information Should Be Equal As Integers ${result[1]} ${docker_number} Prepare Enviorment + Log To Console Starting preparations ${starting_timestamp} Evaluate datetime.datetime.now(datetime.timezone.utc).isoformat("T") modules=datetime ${e2t_log_filename} Evaluate "e2t.${SUITE NAME}.log".replace(" ","-") ${e2mgr_log_filename} Evaluate "e2mgr.${SUITE NAME}.log".replace(" ","-") @@ -114,7 +115,8 @@ Prepare Enviorment Set Suite Variable ${Save_e2e_simu_log} Set Suite Variable ${Save_rm_sim_log} Set Suite Variable ${Save_e2adapter_log} - + + Log To Console Ready to flush db ${flush} cleanup_db.flush Should Be Equal As Strings ${flush} True Run And Return Rc And Output ${stop_simu} @@ -125,6 +127,7 @@ Prepare Enviorment Run And Return Rc And Output ${run_e2e_simu_regular} Run And Return Rc And Output ${restart_e2adapter} Sleep 3s + Log To Console Validating dockers are up ${result}= Run And Return Rc And Output ${docker_command} Should Be Equal As Integers ${result[1]} ${docker_number} diff --git a/Automation/Tests/Scripts/cleanup_db.py b/Automation/Tests/Scripts/cleanup_db.py index 02c5f8f..5c8db84 100644 --- a/Automation/Tests/Scripts/cleanup_db.py +++ b/Automation/Tests/Scripts/cleanup_db.py @@ -38,7 +38,7 @@ def flush(): r.set("{e2Manager},E2TAddresses", "[\"e2t.att.com:38000\"]") - r.set("{e2Manager},E2TInstance:e2t.att.com:38000", "{\"address\":\"e2t.att.com:38000\",\"associatedRanList\":[],\"keepAliveTimestamp\":" + str(int(time.time())) + ",\"state\":\"ACTIVE\"}") + r.set("{e2Manager},E2TInstance:e2t.att.com:38000", "{\"address\":\"e2t.att.com:38000\",\"associatedRanList\":[],\"keepAliveTimestamp\":" + str(int((time.time()+2) * 1000000000)) + ",\"state\":\"ACTIVE\"}") return True diff --git a/E2Manager/app/main.go b/E2Manager/app/main.go index 8eff30d..8c4dee2 100644 --- a/E2Manager/app/main.go +++ b/E2Manager/app/main.go @@ -60,10 +60,10 @@ func main() { rmrSender := rmrsender.NewRmrSender(logger, rmrMessenger) ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService) e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger) - e2tShutdownManager := managers.NewE2TShutdownManager(logger, rnibDataService, e2tInstancesManager) - e2tKeepAliveWorker := managers.NewE2TKeepAliveWorker(logger, rmrSender, e2tInstancesManager, e2tShutdownManager, config) routingManagerClient := clients.NewRoutingManagerClient(logger, config, &http.Client{}) e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient) + e2tShutdownManager := managers.NewE2TShutdownManager(logger, config, rnibDataService, e2tInstancesManager, e2tAssociationManager, ranSetupManager) + 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/clients/routing_manager_client.go b/E2Manager/clients/routing_manager_client.go index d4c9bbe..7679cca 100644 --- a/E2Manager/clients/routing_manager_client.go +++ b/E2Manager/clients/routing_manager_client.go @@ -46,6 +46,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 } func NewRoutingManagerClient(logger *logger.Logger, config *configuration.Configuration, httpClient HttpClient) *RoutingManagerClient { @@ -88,6 +89,11 @@ func (c *RoutingManagerClient) DissociateAllRans(e2tAddresses []string) error { return c.PostMessage(data, url) } +func (c *RoutingManagerClient) DeleteE2TInstance(e2tAddress string, ransToBeDissociated []string, e2tToRansAssociations map[string][]string) error { + //TODO - here should be the call to routing-manager... + return nil +} + func (c *RoutingManagerClient) PostMessage(data interface{}, url string) error { marshaled, err := json.Marshal(data) diff --git a/E2Manager/configuration/configuration.go b/E2Manager/configuration/configuration.go index d37c497..06a8a11 100644 --- a/E2Manager/configuration/configuration.go +++ b/E2Manager/configuration/configuration.go @@ -46,6 +46,7 @@ type Configuration struct { RnibRetryIntervalMs int KeepAliveResponseTimeoutMs int KeepAliveDelayMs int + E2TInstanceDeletionTimeoutMs int } func ParseConfiguration() *Configuration { @@ -72,6 +73,7 @@ func ParseConfiguration() *Configuration { config.RnibRetryIntervalMs = viper.GetInt("rnibRetryIntervalMs") config.KeepAliveResponseTimeoutMs = viper.GetInt("keepAliveResponseTimeoutMs") config.KeepAliveDelayMs = viper.GetInt("KeepAliveDelayMs") + config.E2TInstanceDeletionTimeoutMs = viper.GetInt("e2tInstanceDeletionTimeoutMs") return &config } diff --git a/E2Manager/configuration/configuration_test.go b/E2Manager/configuration/configuration_test.go index b83c661..bbd154d 100644 --- a/E2Manager/configuration/configuration_test.go +++ b/E2Manager/configuration/configuration_test.go @@ -38,6 +38,7 @@ func TestParseConfigurationSuccess(t *testing.T) { assert.Equal(t, 5, config.BigRedButtonTimeoutSec) assert.Equal(t, 4500, config.KeepAliveResponseTimeoutMs) assert.Equal(t, 1500, config.KeepAliveDelayMs) + assert.Equal(t, 15000, config.E2TInstanceDeletionTimeoutMs) } func TestParseConfigurationFileNotFoundFailure(t *testing.T) { diff --git a/E2Manager/container-tag.yaml b/E2Manager/container-tag.yaml index 1827a37..3a7663b 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.4.1 +tag: 3.0.5 diff --git a/E2Manager/go.mod b/E2Manager/go.mod index 720727f..59a3fc9 100644 --- a/E2Manager/go.mod +++ b/E2Manager/go.mod @@ -1,9 +1,9 @@ module e2mgr require ( - gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.28 - gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.28 - gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28 + 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/sdlgo v0.5.2 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect github.com/go-ozzo/ozzo-validation v3.5.0+incompatible diff --git a/E2Manager/go.sum b/E2Manager/go.sum index eef93ff..ad692e7 100644 --- a/E2Manager/go.sum +++ b/E2Manager/go.sum @@ -1,24 +1,18 @@ 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.27 h1:frasTDcg8Q8FgYutzJ+xSLHz9YseR2BmPSSBs4GI/1M= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.27/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.28 h1:Rewapfbc30ZkBaYB/3gW3W1BEivoiPdQm5UnmUswcMA= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.28/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.27 h1:nvZDzuB/SYKDuF1It7M4/Y/iVlVrCZ0Ob8AITAyppKo= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.27/go.mod h1:Fh23KkroYw5CRBh39WzZzxpKSkpQWL3scdzGnMngLo8= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.28 h1:+8Nn+Jn/AvhwBI1LtLsNS1PtOGAOYUHdicOrMn/8mmU= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.28/go.mod h1:Fh23KkroYw5CRBh39WzZzxpKSkpQWL3scdzGnMngLo8= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.27 h1:sWjlU/wBiWIBeSixnr9etCqtNmS2LW8jv+x2JGpf2eI= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.27/go.mod h1:vZ/335+rRSQW82wcbc80fNNICSK3TiCqIxmkqeC2Pfo= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28 h1:AaYvK59fxDXQUV9NCo6WuxDOvBQbnRU3WTPyJaYhkkg= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.28/go.mod h1:vZ/335+rRSQW82wcbc80fNNICSK3TiCqIxmkqeC2Pfo= -gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0 h1:+P3XuWKSaMbzh5PNtrW9gkZlCN0hKrZq+Cn8JetwBys= -gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc= +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/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= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= @@ -110,11 +104,13 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -160,6 +156,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.11.0 h1:gSmpCfs+R47a4yQPAI4xJ0IPDLTRGXskm6UelqNXpqE= go.uber.org/zap v1.11.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -199,6 +196,7 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= diff --git a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go index 7063f57..c75140f 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go @@ -89,7 +89,7 @@ func (h E2TermInitNotificationHandler) Handle(request *models.NotificationReques } if e2tInstance.State == entities.RoutingManagerFailure { - err := h.e2tInstancesManager.ActivateE2TInstance(e2tInstance) + err := h.e2tInstancesManager.SetE2tInstanceState(e2tAddress, e2tInstance.State, entities.Active) if err != nil { return } 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 9ca2452..1b7cba6 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go @@ -321,7 +321,7 @@ func TestE2TermInitHandlerSuccessOneRan_RoutingManagerFailure_Error(t *testing.T e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName) e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) - e2tInstancesManagerMock.On("ActivateE2TInstance", e2tInstance).Return(fmt.Errorf(" Error ")) + e2tInstancesManagerMock.On("SetE2tInstanceState", e2tInstanceAddress, e2tInstance.State, entities.Active).Return(fmt.Errorf(" Error ")) writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)} diff --git a/E2Manager/managers/e2t_association_manager.go b/E2Manager/managers/e2t_association_manager.go index 9b0cada..9988d01 100644 --- a/E2Manager/managers/e2t_association_manager.go +++ b/E2Manager/managers/e2t_association_manager.go @@ -100,3 +100,33 @@ func (m *E2TAssociationManager) DissociateRan(e2tAddress string, ranName string) } return nil } + +func (m *E2TAssociationManager) RemoveE2tInstance(e2tAddress string, ransToBeDissociated []string, ranAssociationList map[string][]string) error { + + err := m.rmClient.DeleteE2TInstance(e2tAddress, ransToBeDissociated, ranAssociationList) + if err != nil { + m.logger.Errorf("#E2TAssociationManager.RemoveE2tInstance - RoutingManager failure: Failed to delete E2T %s. Error: %s", e2tAddress, err) + _ = m.setStateToRoutingManagerFailure(e2tAddress) + return err + } + + err = m.e2tInstanceManager.RemoveE2TInstance(e2tAddress) + if err != nil { + m.logger.Errorf("#E2TAssociationManager.RemoveE2tInstance - Failed to remove E2T %s. Error: %s", e2tAddress, err) + return err + } + + return nil +} + +func (m *E2TAssociationManager) setStateToRoutingManagerFailure(e2tAddress string) error { + e2tInstance, err := m.e2tInstanceManager.GetE2TInstance(e2tAddress) + if err != nil { + return err + } + err = m.e2tInstanceManager.SetE2tInstanceState(e2tAddress, 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 fa13848..e8090f1 100644 --- a/E2Manager/managers/e2t_association_manager_test.go +++ b/E2Manager/managers/e2t_association_manager_test.go @@ -282,4 +282,38 @@ func TestDissociateRanRoutingManagerError(t *testing.T) { readerMock.AssertExpectations(t) writerMock.AssertExpectations(t) httpClientMock.AssertExpectations(t) +} + +func TestRemoveE2tInstanceSuccess(t *testing.T) { + manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) + //mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) + + writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) + e2tAddresses := []string{E2TAddress, E2TAddress2} + readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + e2tAddressesNew := []string{E2TAddress2} + writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil) + + err := manager.RemoveE2tInstance(E2TAddress, []string{""}, make(map[string][]string)) + + assert.Nil(t, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + httpClientMock.AssertExpectations(t) +} + +func TestRemoveE2tInstanceFailureInE2TInstanceManager(t *testing.T) { + manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t) + //mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true) + + writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil) + var e2tAddresses []string + readerMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError()) + + err := manager.RemoveE2tInstance(E2TAddress, []string{""}, make(map[string][]string)) + + assert.NotNil(t, err) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) + httpClientMock.AssertExpectations(t) } \ No newline at end of file diff --git a/E2Manager/managers/e2t_instances_manager.go b/E2Manager/managers/e2t_instances_manager.go index 1e12943..7f7c379 100644 --- a/E2Manager/managers/e2t_instances_manager.go +++ b/E2Manager/managers/e2t_instances_manager.go @@ -43,13 +43,13 @@ type IE2TInstancesManager interface { GetE2TInstances() ([]*entities.E2TInstance, error) GetE2TInstancesNoLogs() ([]*entities.E2TInstance, error) AddE2TInstance(e2tAddress string) error - RemoveE2TInstance(e2tInstance *entities.E2TInstance) error + RemoveE2TInstance(e2tAddress string) error SelectE2TInstance() (string, error) AddRanToInstance(ranName string, e2tAddress string) error RemoveRanFromInstance(ranName string, e2tAddress string) error - ActivateE2TInstance(e2tInstance *entities.E2TInstance) error ResetKeepAliveTimestamp(e2tAddress string) error ClearRansOfAllE2TInstances() error + SetE2tInstanceState(e2tAddress string, currentState entities.E2TInstanceState, newState entities.E2TInstanceState) error } func NewE2TInstancesManager(rnibDataService services.RNibDataService, logger *logger.Logger) *E2TInstancesManager { @@ -270,9 +270,46 @@ func (m *E2TInstancesManager) RemoveRanFromInstance(ranName string, e2tAddress s return nil } -func (m *E2TInstancesManager) RemoveE2TInstance(e2tInstance *entities.E2TInstance) error { +func (m *E2TInstancesManager) RemoveE2TInstance(e2tAddress string) error { + m.mux.Lock() + defer m.mux.Unlock() + + err := m.rnibDataService.RemoveE2TInstance(e2tAddress) + if err != nil { + m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed removing E2TInstance. error: %s", e2tAddress, err) + return e2managererrors.NewRnibDbError() + } + + e2tAddresses, err := m.rnibDataService.GetE2TAddresses() + + if err != nil { + m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed retrieving E2T addresses list. error: %s", e2tAddress, err) + return e2managererrors.NewRnibDbError() + } + + e2tAddresses = m.removeAddressFromList(e2tAddresses, e2tAddress) + + err = m.rnibDataService.SaveE2TAddresses(e2tAddresses) + if err != nil { + m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed saving E2T addresses list. error: %s", e2tAddress, err) + return e2managererrors.NewRnibDbError() + } + return nil } + +func (m *E2TInstancesManager) removeAddressFromList(e2tAddresses []string, addressToRemove string) []string { + newAddressList := []string{} + + for _, address := range e2tAddresses { + if address != addressToRemove { + newAddressList = append(newAddressList, address) + } + } + + return newAddressList +} + func (m *E2TInstancesManager) SelectE2TInstance() (string, error) { e2tInstances, err := m.GetE2TInstances() @@ -322,26 +359,6 @@ func (m *E2TInstancesManager) AddRanToInstance(ranName string, e2tAddress string return nil } -func (m E2TInstancesManager) ActivateE2TInstance(e2tInstance *entities.E2TInstance) error { - - if e2tInstance == nil { - m.logger.Errorf("#E2TInstancesManager.ActivateE2TInstance - e2tInstance empty") - return e2managererrors.NewInternalError() - } - - m.logger.Infof("#E2TInstancesManager.ActivateE2TInstance - E2T Address: %s - activate E2T instance", e2tInstance.Address) - - e2tInstance.State = entities.Active - e2tInstance.KeepAliveTimestamp = time.Now().UnixNano() - - err := m.rnibDataService.SaveE2TInstance(e2tInstance) - if err != nil { - m.logger.Errorf("#E2TInstancesManager.ActivateE2TInstance - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tInstance.Address, err) - return err - } - return nil -} - func (m *E2TInstancesManager) ResetKeepAliveTimestamp(e2tAddress string) error { m.mux.Lock() @@ -371,6 +388,38 @@ func (m *E2TInstancesManager) ResetKeepAliveTimestamp(e2tAddress string) error { return nil } +func (m *E2TInstancesManager) SetE2tInstanceState(e2tAddress string, currentState entities.E2TInstanceState, newState entities.E2TInstanceState) error { + m.mux.Lock() + defer m.mux.Unlock() + + e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress) + + if err != nil { + m.logger.Errorf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err) + return e2managererrors.NewRnibDbError() + } + + if (currentState != e2tInstance.State) { + m.logger.Warnf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Current state is not: %s", e2tAddress, currentState) + return e2managererrors.NewInternalError() + } + + e2tInstance.State = newState + if (newState == entities.Active) { + e2tInstance.KeepAliveTimestamp = time.Now().UnixNano() + } + + err = m.rnibDataService.SaveE2TInstance(e2tInstance) + if err != nil { + m.logger.Errorf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tInstance.Address, err) + return err + } + + m.logger.Infof("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - State change: %s --> %s", e2tAddress, currentState, newState) + + return nil +} + func (m *E2TInstancesManager) ClearRansOfAllE2TInstances() error { m.logger.Infof("#E2TInstancesManager.ClearRansOfAllE2TInstances - Going to clear associated RANs from E2T instances") m.mux.Lock() diff --git a/E2Manager/managers/e2t_instances_manager_test.go b/E2Manager/managers/e2t_instances_manager_test.go index 5c83954..7d48940 100644 --- a/E2Manager/managers/e2t_instances_manager_test.go +++ b/E2Manager/managers/e2t_instances_manager_test.go @@ -21,6 +21,7 @@ package managers import ( "e2mgr/configuration" + "e2mgr/e2managererrors" "e2mgr/logger" "e2mgr/mocks" "e2mgr/services" @@ -296,37 +297,38 @@ func TestSelectE2TInstancesSuccess(t *testing.T) { } func TestActivateE2TInstanceSuccess(t *testing.T) { - _, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) + rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) e2tInstance1 := entities.NewE2TInstance(E2TAddress) e2tInstance1.State = entities.RoutingManagerFailure 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) - rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil) - - err := e2tInstancesManager.ActivateE2TInstance(e2tInstance1) + err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.RoutingManagerFailure, entities.Active) assert.Nil(t, err) assert.Equal(t, entities.Active, e2tInstance1.State) rnibWriterMock.AssertExpectations(t) } func TestActivateE2TInstance_RnibError(t *testing.T) { - _, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) - - e2tInstance1 := entities.NewE2TInstance(E2TAddress) - e2tInstance1.State = entities.RoutingManagerFailure - e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"} + rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) - rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error"))) + var e2tInstance1 *entities.E2TInstance + rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, common.NewInternalError(errors.New("for test"))) - err := e2tInstancesManager.ActivateE2TInstance(e2tInstance1) + err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.RoutingManagerFailure, entities.Active) assert.NotNil(t, err) + rnibWriterMock.AssertExpectations(t) } func TestActivateE2TInstance_NoInstance(t *testing.T) { - _, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) + rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) - err := e2tInstancesManager.ActivateE2TInstance(nil) + var e2tInstance1 *entities.E2TInstance + rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewResourceNotFoundError()) + + err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.RoutingManagerFailure, entities.Active) assert.NotNil(t, err) rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance") @@ -399,13 +401,6 @@ func TestResetKeepAliveTimestampRoutingManagerFailure(t *testing.T) { rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance") } -func TestRemoveE2TInstance(t *testing.T) { - _, _, e2tInstancesManager := initE2TInstancesManagerTest(t) - e2tInstance1 := entities.NewE2TInstance(E2TAddress) - err := e2tInstancesManager.RemoveE2TInstance(e2tInstance1) - assert.Nil(t, err) -} - func TestResetKeepAliveTimestampsForAllE2TInstancesGetE2TInstancesFailure(t *testing.T) { rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) rnibReaderMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("Error"))) @@ -460,3 +455,56 @@ func TestResetKeepAliveTimestampsForAllE2TInstancesSaveE2TInstanceFailure(t *tes e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances() rnibWriterMock.AssertNumberOfCalls(t, "SaveE2TInstance",1) } + +func TestRemoveE2TInstanceSuccess(t *testing.T) { + rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) + rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(nil) + e2tAddresses := []string{E2TAddress, E2TAddress2} + rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + e2tAddressesNew := []string{E2TAddress2} + rnibWriterMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil) + + err := e2tInstancesManager.RemoveE2TInstance(E2TAddress) + assert.Nil(t, err) + rnibReaderMock.AssertExpectations(t) + rnibWriterMock.AssertExpectations(t) +} + +func TestRemoveE2TInstanceRnibErrorInRemoveInstance(t *testing.T) { + rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) + rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(e2managererrors.NewRnibDbError()) + + err := e2tInstancesManager.RemoveE2TInstance(E2TAddress) + assert.NotNil(t, err) + assert.IsType(t, e2managererrors.NewRnibDbError(), err) + rnibReaderMock.AssertExpectations(t) + rnibWriterMock.AssertExpectations(t) +} + +func TestRemoveE2TInstanceRnibErrorInGetAddresses(t *testing.T) { + rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) + rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(nil) + var e2tAddresses []string + rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError()) + + err := e2tInstancesManager.RemoveE2TInstance(E2TAddress) + assert.NotNil(t, err) + assert.IsType(t, e2managererrors.NewRnibDbError(), err) + rnibReaderMock.AssertExpectations(t) + rnibWriterMock.AssertExpectations(t) +} + +func TestRemoveE2TInstanceRnibErrorInSaveAddresses(t *testing.T) { + rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t) + rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(nil) + e2tAddresses := []string{E2TAddress, E2TAddress2} + rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil) + e2tAddressesNew := []string{E2TAddress2} + rnibWriterMock.On("SaveE2TAddresses", e2tAddressesNew).Return(e2managererrors.NewRnibDbError()) + + err := e2tInstancesManager.RemoveE2TInstance(E2TAddress) + assert.NotNil(t, err) + assert.IsType(t, e2managererrors.NewRnibDbError(), err) + rnibReaderMock.AssertExpectations(t) + rnibWriterMock.AssertExpectations(t) +} diff --git a/E2Manager/managers/e2t_shutdown_manager.go b/E2Manager/managers/e2t_shutdown_manager.go index ddf3406..20e4554 100644 --- a/E2Manager/managers/e2t_shutdown_manager.go +++ b/E2Manager/managers/e2t_shutdown_manager.go @@ -21,32 +21,174 @@ package managers import ( + "e2mgr/configuration" "e2mgr/logger" "e2mgr/services" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" + "time" ) - type IE2TShutdownManager interface { Shutdown(e2tInstance *entities.E2TInstance) error } type E2TShutdownManager struct { - logger *logger.Logger - rnibDataService services.RNibDataService - e2TInstancesManager IE2TInstancesManager + logger *logger.Logger + config *configuration.Configuration + rnibDataService services.RNibDataService + e2TInstancesManager IE2TInstancesManager + e2tAssociationManager *E2TAssociationManager + ranSetupManager IRanSetupManager } -func NewE2TShutdownManager(logger *logger.Logger, rnibDataService services.RNibDataService, e2TInstancesManager IE2TInstancesManager) E2TShutdownManager { +func NewE2TShutdownManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, e2TInstancesManager IE2TInstancesManager, e2tAssociationManager *E2TAssociationManager, ranSetupManager IRanSetupManager) E2TShutdownManager { return E2TShutdownManager{ - logger: logger, - rnibDataService: rnibDataService, - e2TInstancesManager: e2TInstancesManager, + logger: logger, + config: config, + rnibDataService: rnibDataService, + e2TInstancesManager: e2TInstancesManager, + e2tAssociationManager: e2tAssociationManager, + ranSetupManager: ranSetupManager, } } -func (h E2TShutdownManager) Shutdown(e2tInstance *entities.E2TInstance) error{ - h.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s is Dead, RIP", e2tInstance.Address) +func (m E2TShutdownManager) Shutdown(e2tInstance *entities.E2TInstance) error { + m.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s is Dead, RIP", e2tInstance.Address) + + isE2tInstanceBeingDeleted := m.isE2tInstanceAlreadyBeingDeleted(e2tInstance) + if isE2tInstanceBeingDeleted { + m.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s is already being deleted", e2tInstance.Address) + return nil + } + + err := m.markE2tInstanceToBeDeleted(e2tInstance) + if err != nil { + m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to mark E2T %s as 'ToBeDeleted'.", e2tInstance.Address) + return err + } + + ranNamesToBeDissociated := []string{} + ranNamesToBeAssociated := make(map[string][]string) // e2tAddress -> associatedRanList + + for _, ranName := range e2tInstance.AssociatedRanList { + 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.Address, ranNamesToBeDissociated, ranNamesToBeAssociated) + if err != nil { + m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to remove E2T %s.", e2tInstance.Address) + return err + } + + err = m.clearNodebsAssociation(ranNamesToBeDissociated) + if err != nil { + m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to clear nodebs association to E2T %s.", e2tInstance.Address) + return err + } + + err = m.reassociateNodebs(ranNamesToBeAssociated) + if err != nil { + m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to re-associate nodebs after killing E2T %s.", e2tInstance.Address) + return err + } 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 + } + + } + return nil +} + +func (m E2TShutdownManager) clearNodebsAssociation(ranNamesToBeDissociated []string) error { + return m.associateAndSetupNodebs(ranNamesToBeDissociated, "") +} + +func (m E2TShutdownManager) associateAndSetupNodebs(ranNamesToBeUpdated []string, e2tAddress string) error { + for _, ranName := range ranNamesToBeUpdated { + nodeb, err := m.rnibDataService.GetNodeb(ranName) + if err != nil { + m.logger.Warnf("#E2TShutdownManager.associateAndSetupNodebs - Failed to get nodeb %s from db.", ranName) + _, ok := err.(*common.ResourceNotFoundError) + if !ok { + continue + } + return err + } + nodeb.AssociatedE2TInstanceAddress = e2tAddress + err = m.rnibDataService.UpdateNodebInfo(nodeb) + if err != nil { + m.logger.Errorf("#E2TShutdownManager.associateAndSetupNodebs - Failed to save nodeb %s from db.", ranName) + return err + } + + shouldSendSetup := len(e2tAddress) > 0 + if shouldSendSetup { + 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) 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 err + } + + m.logger.Errorf("#E2TShutdownManager.reAssociateRanInMemory - nodeb %s not found in db. dissociating it...", ranName) + ranNamesToBeDissociated = append(ranNamesToBeDissociated, ranName) + return nil + } + + if nodeb.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN || nodeb.ConnectionStatus == entities.ConnectionStatus_SHUT_DOWN { + m.logger.Errorf("#E2TShutdownManager.reAssociateRanInMemory - nodeb %s status is %s. dissociating it...", ranName, nodeb.ConnectionStatus) + ranNamesToBeDissociated = append(ranNamesToBeDissociated, ranName) + return 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 nil + } + + ranNamesToBeAssociated[selectedE2tAddress] = append(ranNamesToBeAssociated[selectedE2tAddress], ranName) + return nil +} + +func (m E2TShutdownManager) markE2tInstanceToBeDeleted(e2tInstance *entities.E2TInstance) error { + e2tInstance.State = entities.ToBeDeleted + e2tInstance.DeletionTimestamp = time.Now().UnixNano() + + return m.rnibDataService.SaveE2TInstance(e2tInstance) +} + +func (m E2TShutdownManager) isE2tInstanceAlreadyBeingDeleted(e2tInstance *entities.E2TInstance) bool { + delta := time.Now().UnixNano() - e2tInstance.DeletionTimestamp + timestampNanosec := int64(time.Duration(m.config.E2TInstanceDeletionTimeoutMs) * time.Millisecond) + + return delta <= timestampNanosec +} diff --git a/E2Manager/mocks/e2t_instances_manager_mock.go b/E2Manager/mocks/e2t_instances_manager_mock.go index 5919f9c..565f0bc 100644 --- a/E2Manager/mocks/e2t_instances_manager_mock.go +++ b/E2Manager/mocks/e2t_instances_manager_mock.go @@ -40,8 +40,8 @@ func (m *E2TInstancesManagerMock) AddE2TInstance(e2tInstanceAddress string) erro return args.Error(0) } -func (m *E2TInstancesManagerMock) RemoveE2TInstance(e2tInstance *entities.E2TInstance) error { - args := m.Called(e2tInstance) +func (m *E2TInstancesManagerMock) RemoveE2TInstance(e2tAddress string) error { + args := m.Called(e2tAddress) return args.Error(0) } @@ -55,6 +55,7 @@ func (m *E2TInstancesManagerMock) AddRanToInstance(ranName string, e2tAddress st return args.Error(0) } + func (m *E2TInstancesManagerMock) RemoveRanFromInstance(ranName string, e2tAddress string) error { args := m.Called(ranName, e2tAddress) return args.Error(0) @@ -79,8 +80,8 @@ func (m *E2TInstancesManagerMock) ResetKeepAliveTimestamp(e2tAddress string) err } -func (m *E2TInstancesManagerMock) ActivateE2TInstance(e2tInstance *entities.E2TInstance) error { - args := m.Called(e2tInstance) +func (m *E2TInstancesManagerMock) SetE2tInstanceState(e2tAddress string, currentState entities.E2TInstanceState, newState entities.E2TInstanceState) error { + args := m.Called(e2tAddress, currentState, newState) return args.Error(0) } diff --git a/E2Manager/mocks/rnibWriterMock.go b/E2Manager/mocks/rnibWriterMock.go index 5ca925f..9e1070e 100644 --- a/E2Manager/mocks/rnibWriterMock.go +++ b/E2Manager/mocks/rnibWriterMock.go @@ -76,3 +76,9 @@ func (rnibWriterMock *RnibWriterMock) SaveE2TAddresses(addresses []string) error return args.Error(0) } + +func (rnibWriterMock *RnibWriterMock) RemoveE2TInstance(address string) error { + args := rnibWriterMock.Called(address) + + return args.Error(0) +} diff --git a/E2Manager/mocks/routing_manager_client_mock.go b/E2Manager/mocks/routing_manager_client_mock.go index fb1cafd..0652276 100644 --- a/E2Manager/mocks/routing_manager_client_mock.go +++ b/E2Manager/mocks/routing_manager_client_mock.go @@ -49,4 +49,10 @@ func (m *RoutingManagerClientMock) DissociateAllRans(e2tAddresses []string) erro args := m.Called(e2tAddresses) return args.Error(0) +} + +func (m *RoutingManagerClientMock) DeleteE2TInstance(e2tAddress string, ransToBeDissociated []string, e2tToRansAssociations map[string][]string) error { + + args := m.Called(e2tAddress, ransToBeDissociated, e2tToRansAssociations) + return args.Error(0) } \ No newline at end of file diff --git a/E2Manager/rNibWriter/rNibWriter.go b/E2Manager/rNibWriter/rNibWriter.go index 13a31f3..a7195de 100644 --- a/E2Manager/rNibWriter/rNibWriter.go +++ b/E2Manager/rNibWriter/rNibWriter.go @@ -43,6 +43,7 @@ type RNibWriter interface { SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error SaveE2TInstance(e2tInstance *entities.E2TInstance) error SaveE2TAddresses(addresses []string) error + RemoveE2TInstance(e2tAddress string) error } /* @@ -234,6 +235,20 @@ func (w *rNibWriterInstance) SaveE2TAddresses(addresses []string) error { return nil } + +func (w *rNibWriterInstance) RemoveE2TInstance(address string) error { + key, rNibErr := common.ValidateAndBuildE2TInstanceKey(address) + if rNibErr != nil { + return rNibErr + } + err := w.sdl.Remove([]string{key}) + + if err != nil { + return common.NewInternalError(err) + } + return nil +} + /* Close the writer */ diff --git a/E2Manager/rNibWriter/rNibWriter_test.go b/E2Manager/rNibWriter/rNibWriter_test.go index 34ef4c8..6c8743e 100644 --- a/E2Manager/rNibWriter/rNibWriter_test.go +++ b/E2Manager/rNibWriter/rNibWriter_test.go @@ -577,6 +577,39 @@ func TestSaveE2TAddressesSdlFailure(t *testing.T) { assert.IsType(t, &common.InternalError{}, rNibErr) } +func TestRemoveE2TInstanceSuccess(t *testing.T) { + address := "10.10.2.15:9800" + w, sdlInstanceMock := initSdlInstanceMock(namespace) + + e2tAddresses := []string{fmt.Sprintf("E2TInstance:%s", address)} + var e error + sdlInstanceMock.On("Remove", e2tAddresses).Return(e) + + rNibErr := w.RemoveE2TInstance(address) + assert.Nil(t, rNibErr) + sdlInstanceMock.AssertExpectations(t) +} + +func TestRemoveE2TInstanceSdlFailure(t *testing.T) { + address := "10.10.2.15:9800" + w, sdlInstanceMock := initSdlInstanceMock(namespace) + + e2tAddresses := []string{fmt.Sprintf("E2TInstance:%s", address)} + expectedErr := errors.New("expected error") + sdlInstanceMock.On("Remove", e2tAddresses).Return(expectedErr) + + rNibErr := w.RemoveE2TInstance(address) + assert.IsType(t, &common.InternalError{}, rNibErr) +} + +func TestRemoveE2TInstanceEmptyAddressFailure(t *testing.T) { + w, sdlInstanceMock := initSdlInstanceMock(namespace) + + rNibErr := w.RemoveE2TInstance("") + assert.IsType(t, &common.ValidationError{}, rNibErr) + sdlInstanceMock.AssertExpectations(t) +} + //Integration tests // //func TestSaveEnbGnbInteg(t *testing.T){ diff --git a/E2Manager/resources/configuration.yaml b/E2Manager/resources/configuration.yaml index b70ddfc..6528db9 100644 --- a/E2Manager/resources/configuration.yaml +++ b/E2Manager/resources/configuration.yaml @@ -14,3 +14,4 @@ maxRnibConnectionAttempts: 3 rnibRetryIntervalMs: 10 keepAliveResponseTimeoutMs: 4500 keepAliveDelayMs: 1500 +e2tInstanceDeletionTimeoutMs: 15000 diff --git a/E2Manager/services/rnib_data_service.go b/E2Manager/services/rnib_data_service.go index 1a5af59..35b4c02 100644 --- a/E2Manager/services/rnib_data_service.go +++ b/E2Manager/services/rnib_data_service.go @@ -47,6 +47,7 @@ type RNibDataService interface { GetE2TInstancesNoLogs(addresses []string) ([]*entities.E2TInstance, error) SaveE2TInstanceNoLogs(e2tInstance *entities.E2TInstance) error GetE2TAddressesNoLogs() ([]string, error) + RemoveE2TInstance(e2tAddress string) error } type rNibDataService struct { @@ -236,6 +237,17 @@ func (w *rNibDataService) SaveE2TAddresses(addresses []string) error { return err } +func (w *rNibDataService) RemoveE2TInstance(e2tAddress string) error { + w.logger.Infof("#RnibDataService.RemoveE2TInstance - e2tAddress: %s", e2tAddress) + + err := w.retry("RemoveE2TInstance", func() (err error) { + err = w.rnibWriter.RemoveE2TInstance(e2tAddress) + return + }) + + return err +} + func (w *rNibDataService) PingRnib() bool { err := w.retry("GetListNodebIds", func() (err error) { _, err = w.rnibReader.GetListNodebIds() -- 2.16.6