From: is005q Date: Tue, 26 Nov 2019 15:23:20 +0000 (+0200) Subject: [RICPLT-2585] E2Term Init - Support Multiple E2T Instances X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=5660067626f34d1fac7753ea4eb5c5c99f93192e;p=ric-plt%2Fe2mgr.git [RICPLT-2585] E2Term Init - Support Multiple E2T Instances Change-Id: I0362bd2502d233f4a680d1a49a6353659ee29fbe Signed-off-by: is005q --- diff --git a/E2Manager/go.mod b/E2Manager/go.mod index 368ce17..1207f33 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.24 - gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.24 - gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.24 + gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.25 + gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.25 + gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.25 gerrit.o-ran-sc.org/r/ric-plt/sdlgo v0.5.0 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 879eb02..4786119 100644 --- a/E2Manager/go.sum +++ b/E2Manager/go.sum @@ -3,14 +3,20 @@ gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.23 h1:JbSOhvj9fVEUF2XZg gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.23/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.24 h1:tW817tat6fSSK7NuFKEDHSoSsO3z8kr7QORfbn1Hpuc= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.24/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.25 h1:msB3b7s+KoNdzSOKZPgymoMJEpA84fSTWBDCgvbUKaE= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.25/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.23 h1:akVZc8NWJ9oPujd7cQY3Ti3se4PF1/NoC+Dwt+YzINc= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.23/go.mod h1:GXiXLz4ORBeIr0FLIbzENRykgh3Po5uPkX2jICxnRF0= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.24 h1:5ZnhEUygvN5PuTXS2bNt6KavT+Wtuh9Vra+EqZIvw+Q= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.24/go.mod h1:GXiXLz4ORBeIr0FLIbzENRykgh3Po5uPkX2jICxnRF0= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.25 h1:W9CayjJzo3r0MrgDODBg4YwIEJ/VZc4BWqfK2qWX7jg= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.25/go.mod h1:Fh23KkroYw5CRBh39WzZzxpKSkpQWL3scdzGnMngLo8= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.23 h1:TYV3HE2UNwGOWiA4C226/WhB94crwjuHKIFTgDDvo8I= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.23/go.mod h1:uZVjwZjfWV4JJzyQVO/O48Ykph57zfpfMB7nK+WGKX8= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.24 h1:Wwp36IoHwp091lXVCYLtFK6AMhoGAR4NYEgW1C42h6k= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.24/go.mod h1:Qi0e0BsGtsMdyJQS0PBtvHBDKEimjtDjQtVUxGZqTtM= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.25 h1:mxLhqHxp4yeo01sT3GrGVa7chaedOd7cj00Q2TK3xJM= +gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.25/go.mod h1:gfLVMDJ1W5uwTphc74b70SGXqBHYjo2v2ZdtroX5pFs= 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= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= diff --git a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go index 5de5e2d..fd2ec81 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go @@ -29,13 +29,15 @@ type E2TermInitNotificationHandler struct { logger *logger.Logger rnibDataService services.RNibDataService ranReconnectionManager *managers.RanReconnectionManager + e2tInstancesManager managers.IE2TInstancesManager } -func NewE2TermInitNotificationHandler(logger *logger.Logger, ranReconnectionManager *managers.RanReconnectionManager, rnibDataService services.RNibDataService) E2TermInitNotificationHandler { +func NewE2TermInitNotificationHandler(logger *logger.Logger, ranReconnectionManager *managers.RanReconnectionManager, rnibDataService services.RNibDataService, e2tInstancesManager managers.IE2TInstancesManager) E2TermInitNotificationHandler { return E2TermInitNotificationHandler{ logger: logger, rnibDataService: rnibDataService, ranReconnectionManager: ranReconnectionManager, + e2tInstancesManager: e2tInstancesManager, } } @@ -43,21 +45,31 @@ func (h E2TermInitNotificationHandler) Handle(request *models.NotificationReques h.logger.Infof("#E2TermInitNotificationHandler.Handle - Handling E2_TERM_INIT") - nbIdentityList, err := h.rnibDataService.GetListNodebIds() + e2tAddress := string(request.Payload) // TODO: make sure E2T sends this as the only value of the message + + e2tInstance, err := h.e2tInstancesManager.GetE2TInstance(e2tAddress) + if err != nil { - h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed to get nodes list from RNIB. Error: %s", err.Error()) + _, ok := err.(*common.ResourceNotFoundError) + + if !ok { + h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed retrieving E2TInstance. error: %s", err) + return + } + + _ = h.e2tInstancesManager.AddE2TInstance(e2tAddress) return } - if len(nbIdentityList) == 0 { - h.logger.Warnf("#E2TermInitNotificationHandler.Handle - The Nodes list in RNIB is empty") + if len(e2tInstance.AssociatedRanList) == 0 { + h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T Address: %s - E2T instance has no associated RANs", e2tInstance.Address) return } - for _, nbIdentity := range nbIdentityList { + for _, ranName := range e2tInstance.AssociatedRanList { - if err := h.ranReconnectionManager.ReconnectRan(nbIdentity.InventoryName); err != nil { - h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Ran name: %s - connection attempt failure, error: %s", (*nbIdentity).GetInventoryName(), err.Error()) + if err := h.ranReconnectionManager.ReconnectRan(ranName); err != nil { + h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Ran name: %s - connection attempt failure, error: %s", ranName, err) _, ok := err.(*common.ResourceNotFoundError) if !ok { break diff --git a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go index fe9b172..cccd722 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go @@ -18,7 +18,6 @@ package rmrmsghandlers import ( "e2mgr/configuration" - "e2mgr/e2pdus" "e2mgr/logger" "e2mgr/managers" "e2mgr/mocks" @@ -30,11 +29,10 @@ import ( "fmt" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" - "github.com/stretchr/testify/mock" "testing" ) -func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock) { +func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock) { logger := initLog(t) config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3} @@ -48,211 +46,245 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotifica rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock) ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService) - ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager) - handler := NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService) - return logger, handler, readerMock, writerMock, rmrMessengerMock -} - -func TestE2TerminInitHandlerSuccessOneRan(t *testing.T) { - _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t) - var rnibErr error - - ids := []*entities.NbIdentity{{InventoryName: "test1"}} - readerMock.On("GetListNodebIds").Return(ids, rnibErr) - - var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb, rnibErr) - - var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) - - payload := e2pdus.PackedX2setupRequest - xaction := []byte(ids[0].InventoryName) - msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) - - rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil) - - handler.Handle(nil) - - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) -} - -func TestE2TerminInitHandlerSuccessTwoRans(t *testing.T) { - _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t) - var rnibErr error - - ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}} - readerMock.On("GetListNodebIds").Return(ids, rnibErr) - - 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} - readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr) - readerMock.On("GetNodeb", ids[1].InventoryName).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) - - payload := e2pdus.PackedX2setupRequest - xaction := []byte(ids[0].InventoryName) - msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) - - rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil) - - handler.Handle(nil) - - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2) -} - -func TestE2TerminInitHandlerSuccessThreeRansFirstRmrFailure(t *testing.T) { - log, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t) - var rnibErr error - - ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}} - readerMock.On("GetListNodebIds").Return(ids, rnibErr) - - var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr) - readerMock.On("GetNodeb", ids[1].InventoryName).Return(initialNodeb1, rnibErr) - readerMock.On("GetNodeb", ids[2].InventoryName).Return(initialNodeb2, rnibErr) - - var argNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - var argNodeb0Fail = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 0} - writerMock.On("UpdateNodebInfo", argNodeb0).Return(rnibErr) - writerMock.On("UpdateNodebInfo", argNodeb0Fail).Return(rnibErr) - - payload := models.NewE2RequestMessage(ids[0].InventoryName /*tid*/, "", 0, ids[0].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) - xaction := []byte(ids[0].InventoryName) - msg0 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) - - // Cannot use Mock because request MBuf contains pointers - //payload =models.NewE2RequestMessage(ids[1].InventoryName /*tid*/, "", 0,ids[1].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) - //xaction = []byte(ids[1].InventoryName) - //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction) - - rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, fmt.Errorf("RMR Error")) - handler.Handle(nil) - - //test1 (before send +1, after failure +1), test2 (0) test3 (0) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) - //test1 failure (+1), test2 (0). test3 (0) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) + e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{} + ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManagerMock) + handler := NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService, e2tInstancesManagerMock) + return logger, handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock } -func TestE2TerminInitHandlerSuccessThreeRansSecondNotFoundFailure(t *testing.T) { - log, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t) - var rnibErr error - - ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}} - readerMock.On("GetListNodebIds").Return(ids, rnibErr) - - var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr) - readerMock.On("GetNodeb", ids[1].InventoryName).Return(initialNodeb1, common.NewResourceNotFoundError("not found")) - readerMock.On("GetNodeb", ids[2].InventoryName).Return(initialNodeb2, rnibErr) - - var argNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - var argNodeb0Success = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb0).Return(rnibErr) - writerMock.On("UpdateNodebInfo", argNodeb0Success).Return(rnibErr) - - var argNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - var argNodeb2Success = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb2).Return(rnibErr) - writerMock.On("UpdateNodebInfo", argNodeb2Success).Return(rnibErr) - - payload := models.NewE2RequestMessage(ids[0].InventoryName /*tid*/, "", 0, ids[0].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) - xaction := []byte(ids[0].InventoryName) - msg0 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) - - // Cannot use Mock because request MBuf contains pointers - //payload =models.NewE2RequestMessage(ids[1].InventoryName /*tid*/, "", 0,ids[1].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) - //xaction = []byte(ids[1].InventoryName) - //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction) - - rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, nil) - - handler.Handle(nil) - - readerMock.AssertNumberOfCalls(t, "GetNodeb", 3) - //test1 (+1), test2 failure (0) test3 (+1) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) - //test1 success (+1), test2 (0). test3 (+1) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2) +func TestE2TermInitGetE2TInstanceFailure(t *testing.T) { + _, handler, _, _, _, e2tInstancesManagerMock := initRanLostConnectionTest(t) + e2tInstanceAddress := "10.0.2.15" + var e2tInstance *entities.E2TInstance + e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewInternalError(fmt.Errorf("internal error"))) + notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInstanceAddress)} + handler.Handle(notificationRequest) + e2tInstancesManagerMock.AssertNotCalled(t, "AddE2TInstance") } -func TestE2TerminInitHandlerSuccessThreeRansSecondRnibInternalErrorFailure(t *testing.T) { - log, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t) - var rnibErr error - - ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}} - readerMock.On("GetListNodebIds").Return(ids, rnibErr) - - var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - var initialNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} - readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr) - readerMock.On("GetNodeb", ids[1].InventoryName).Return(initialNodeb1, common.NewInternalError(fmt.Errorf("internal error"))) - readerMock.On("GetNodeb", ids[2].InventoryName).Return(initialNodeb2, rnibErr) - - var argNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - var argNodeb0Success = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb0).Return(rnibErr) - writerMock.On("UpdateNodebInfo", argNodeb0Success).Return(rnibErr) - - var argNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - var argNodeb2Success = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} - writerMock.On("UpdateNodebInfo", argNodeb2).Return(rnibErr) - writerMock.On("UpdateNodebInfo", argNodeb2Success).Return(rnibErr) - - payload := models.NewE2RequestMessage(ids[0].InventoryName /*tid*/, "", 0, ids[0].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) - xaction := []byte(ids[0].InventoryName) - msg0 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) - - // Cannot use Mock because request MBuf contains pointers - //payload =models.NewE2RequestMessage(ids[1].InventoryName /*tid*/, "", 0,ids[1].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) - //xaction = []byte(ids[1].InventoryName) - //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction) - - rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, nil) - - handler.Handle(nil) - - readerMock.AssertNumberOfCalls(t, "GetNodeb", 2) - //test1 (+1), test2 failure (0) test3 (0) - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) - //test1 success (+1), test2 (0). test3 (+1) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) +func TestE2TermInitNewE2TInstance(t *testing.T) { + _, handler, _, _, _, e2tInstancesManagerMock := initRanLostConnectionTest(t) + e2tInstanceAddress := "10.0.2.15" + var e2tInstance *entities.E2TInstance + e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewResourceNotFoundError("not found")) + e2tInstance = entities.NewE2TInstance(e2tInstanceAddress) + e2tInstancesManagerMock.On("AddE2TInstance", e2tInstanceAddress).Return(nil) + notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInstanceAddress)} + handler.Handle(notificationRequest) + e2tInstancesManagerMock.AssertCalled(t, "AddE2TInstance", e2tInstanceAddress) } -func TestE2TerminInitHandlerSuccessZeroRans(t *testing.T) { - _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t) - var rnibErr error - - readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, rnibErr) - - handler.Handle(nil) - - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) +func TestE2TermInitExistingE2TInstanceNoAssociatedRans(t *testing.T) { + _, handler, _, _, _, e2tInstancesManagerMock := initRanLostConnectionTest(t) + e2tInstanceAddress := "10.0.2.15" + e2tInstance := entities.NewE2TInstance(e2tInstanceAddress) + e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil) + notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInstanceAddress)} + handler.Handle(notificationRequest) + e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceAddress) } -func TestE2TerminInitHandlerFailureGetListNodebIds(t *testing.T) { - _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t) - - readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, common.NewInternalError(fmt.Errorf("internal error"))) - - handler.Handle(nil) - - writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0) - rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) -} +//func TestE2TerminInitHandlerSuccessOneRan(t *testing.T) { +// _, handler, readerMock, writerMock, rmrMessengerMock, _ := initRanLostConnectionTest(t) +// var rnibErr error +// +// ids := []*entities.NbIdentity{{InventoryName: "test1"}} +// readerMock.On("GetListNodebIds").Return(ids, rnibErr) +// +// var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} +// readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb, rnibErr) +// +// var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} +// writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr) +// +// payload := e2pdus.PackedX2setupRequest +// xaction := []byte(ids[0].InventoryName) +// msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) +// +// rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil) +// +// handler.Handle(nil) +// +// writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) +// rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) +//} +// +//func TestE2TerminInitHandlerSuccessTwoRans(t *testing.T) { +// _, handler, readerMock, writerMock, rmrMessengerMock, _ := initRanLostConnectionTest(t) +// var rnibErr error +// +// ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}} +// readerMock.On("GetListNodebIds").Return(ids, rnibErr) +// +// 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} +// readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr) +// readerMock.On("GetNodeb", ids[1].InventoryName).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) +// +// payload := e2pdus.PackedX2setupRequest +// xaction := []byte(ids[0].InventoryName) +// msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) +// +// rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil) +// +// handler.Handle(nil) +// +// writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) +// rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2) +//} +// +//func TestE2TerminInitHandlerSuccessThreeRansFirstRmrFailure(t *testing.T) { +// log, handler, readerMock, writerMock, rmrMessengerMock, _ := initRanLostConnectionTest(t) +// var rnibErr error +// +// ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}} +// readerMock.On("GetListNodebIds").Return(ids, rnibErr) +// +// var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} +// var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} +// var initialNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} +// readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr) +// readerMock.On("GetNodeb", ids[1].InventoryName).Return(initialNodeb1, rnibErr) +// readerMock.On("GetNodeb", ids[2].InventoryName).Return(initialNodeb2, rnibErr) +// +// var argNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} +// var argNodeb0Fail = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 0} +// writerMock.On("UpdateNodebInfo", argNodeb0).Return(rnibErr) +// writerMock.On("UpdateNodebInfo", argNodeb0Fail).Return(rnibErr) +// +// payload := models.NewE2RequestMessage(ids[0].InventoryName /*tid*/, "", 0, ids[0].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) +// xaction := []byte(ids[0].InventoryName) +// msg0 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) +// +// // Cannot use Mock because request MBuf contains pointers +// //payload =models.NewE2RequestMessage(ids[1].InventoryName /*tid*/, "", 0,ids[1].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) +// //xaction = []byte(ids[1].InventoryName) +// //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction) +// +// rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, fmt.Errorf("RMR Error")) +// +// handler.Handle(nil) +// +// //test1 (before send +1, after failure +1), test2 (0) test3 (0) +// writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) +// //test1 failure (+1), test2 (0). test3 (0) +// rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) +//} +// +//func TestE2TerminInitHandlerSuccessThreeRansSecondNotFoundFailure(t *testing.T) { +// log, handler, readerMock, writerMock, rmrMessengerMock, _ := initRanLostConnectionTest(t) +// var rnibErr error +// +// ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}} +// readerMock.On("GetListNodebIds").Return(ids, rnibErr) +// +// var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} +// var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} +// var initialNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} +// readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr) +// readerMock.On("GetNodeb", ids[1].InventoryName).Return(initialNodeb1, common.NewResourceNotFoundError("not found")) +// readerMock.On("GetNodeb", ids[2].InventoryName).Return(initialNodeb2, rnibErr) +// +// var argNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} +// var argNodeb0Success = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} +// writerMock.On("UpdateNodebInfo", argNodeb0).Return(rnibErr) +// writerMock.On("UpdateNodebInfo", argNodeb0Success).Return(rnibErr) +// +// var argNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} +// var argNodeb2Success = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} +// writerMock.On("UpdateNodebInfo", argNodeb2).Return(rnibErr) +// writerMock.On("UpdateNodebInfo", argNodeb2Success).Return(rnibErr) +// +// payload := models.NewE2RequestMessage(ids[0].InventoryName /*tid*/, "", 0, ids[0].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) +// xaction := []byte(ids[0].InventoryName) +// msg0 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) +// +// // Cannot use Mock because request MBuf contains pointers +// //payload =models.NewE2RequestMessage(ids[1].InventoryName /*tid*/, "", 0,ids[1].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) +// //xaction = []byte(ids[1].InventoryName) +// //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction) +// +// rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, nil) +// +// handler.Handle(nil) +// +// readerMock.AssertNumberOfCalls(t, "GetNodeb", 3) +// //test1 (+1), test2 failure (0) test3 (+1) +// writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2) +// //test1 success (+1), test2 (0). test3 (+1) +// rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2) +//} +// +//func TestE2TerminInitHandlerSuccessThreeRansSecondRnibInternalErrorFailure(t *testing.T) { +// log, handler, readerMock, writerMock, rmrMessengerMock, _ := initRanLostConnectionTest(t) +// var rnibErr error +// +// ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}, {InventoryName: "test3"}} +// readerMock.On("GetListNodebIds").Return(ids, rnibErr) +// +// var initialNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} +// var initialNodeb1 = &entities.NodebInfo{RanName: ids[1].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} +// var initialNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST} +// readerMock.On("GetNodeb", ids[0].InventoryName).Return(initialNodeb0, rnibErr) +// readerMock.On("GetNodeb", ids[1].InventoryName).Return(initialNodeb1, common.NewInternalError(fmt.Errorf("internal error"))) +// readerMock.On("GetNodeb", ids[2].InventoryName).Return(initialNodeb2, rnibErr) +// +// var argNodeb0 = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} +// var argNodeb0Success = &entities.NodebInfo{RanName: ids[0].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} +// writerMock.On("UpdateNodebInfo", argNodeb0).Return(rnibErr) +// writerMock.On("UpdateNodebInfo", argNodeb0Success).Return(rnibErr) +// +// var argNodeb2 = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} +// var argNodeb2Success = &entities.NodebInfo{RanName: ids[2].InventoryName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1} +// writerMock.On("UpdateNodebInfo", argNodeb2).Return(rnibErr) +// writerMock.On("UpdateNodebInfo", argNodeb2Success).Return(rnibErr) +// +// payload := models.NewE2RequestMessage(ids[0].InventoryName /*tid*/, "", 0, ids[0].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) +// xaction := []byte(ids[0].InventoryName) +// msg0 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction) +// +// // Cannot use Mock because request MBuf contains pointers +// //payload =models.NewE2RequestMessage(ids[1].InventoryName /*tid*/, "", 0,ids[1].InventoryName, e2pdus.PackedX2setupRequest).GetMessageAsBytes(log) +// //xaction = []byte(ids[1].InventoryName) +// //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction) +// +// rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, nil) +// +// handler.Handle(nil) +// +// readerMock.AssertNumberOfCalls(t, "GetNodeb", 2) +// //test1 (+1), test2 failure (0) test3 (0) +// writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) +// //test1 success (+1), test2 (0). test3 (+1) +// rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1) +//} +// +//func TestE2TerminInitHandlerSuccessZeroRans(t *testing.T) { +// _, handler, readerMock, writerMock, rmrMessengerMock, _ := initRanLostConnectionTest(t) +// var rnibErr error +// +// readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, rnibErr) +// +// handler.Handle(nil) +// +// writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0) +// rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) +//} +// +//func TestE2TerminInitHandlerFailureGetListNodebIds(t *testing.T) { +// _, handler, readerMock, writerMock, rmrMessengerMock, _ := initRanLostConnectionTest(t) +// +// readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, common.NewInternalError(fmt.Errorf("internal error"))) +// +// handler.Handle(nil) +// +// writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0) +// rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0) +//} // TODO: extract to test_utils func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender { diff --git a/E2Manager/managers/e2t_instances_manager.go b/E2Manager/managers/e2t_instances_manager.go new file mode 100644 index 0000000..445b2be --- /dev/null +++ b/E2Manager/managers/e2t_instances_manager.go @@ -0,0 +1,190 @@ +package managers + +import ( + "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" + "sync" +) + +type E2TInstancesManager struct { + rnibDataService services.RNibDataService + logger *logger.Logger + mux sync.Mutex +} + +type IE2TInstancesManager interface { + GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error) + AddE2TInstance(e2tAddress string) error + RemoveE2TInstance(e2tInstance *entities.E2TInstance) error + SelectE2TInstance(e2tInstance *entities.E2TInstance) (string, error) + AssociateRan(ranName string, e2tAddress string) error + DeassociateRan(ranName string, e2tAddress string) error +} + +func NewE2TInstancesManager(rnibDataService services.RNibDataService, logger *logger.Logger) *E2TInstancesManager { + return &E2TInstancesManager{ + rnibDataService: rnibDataService, + logger: logger, + } +} + +func (m *E2TInstancesManager) GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error) { + e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress) + + if err != nil { + m.logger.Errorf("#GetE2TInstance - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err) + } + + return e2tInstance, err +} + +func (m *E2TInstancesManager) AddE2TInstance(e2tAddress string) error { + e2tInstance := entities.NewE2TInstance(e2tAddress) + err := m.rnibDataService.SaveE2TInstance(e2tInstance) + + if err != nil { + m.logger.Errorf("#AddE2TInstance - E2T Instance address: %s - Failed saving E2T instance. error: %s", e2tInstance.Address, err) + return err + } + + m.mux.Lock() + defer m.mux.Unlock() + + e2tInfoList, err := m.rnibDataService.GetE2TInfoList() + + if err != nil { + + _, ok := err.(*common.ResourceNotFoundError) + + if !ok { + m.logger.Errorf("#AddE2TInstance - E2T Instance address: %s - Failed retrieving E2TInfoList. error: %s", e2tInstance.Address, err) + return err + } + } + + e2tInstanceInfo := entities.NewE2TInstanceInfo(e2tInstance.Address) + e2tInfoList = append(e2tInfoList, e2tInstanceInfo) + + err = m.rnibDataService.SaveE2TInfoList(e2tInfoList) + + if err != nil { + m.logger.Errorf("#AddE2TInstance - E2T Instance address: %s - Failed saving E2TInfoList. error: %s", e2tInstance.Address, err) + return err + } + + m.logger.Infof("#AddE2TInstance - E2T Instance address: %s - successfully completed", e2tInstance.Address) + return nil +} + +func (m *E2TInstancesManager) DeassociateRan(ranName string, e2tAddress string) error { + + m.mux.Lock() + defer m.mux.Unlock() + + e2tInfoList, err := m.rnibDataService.GetE2TInfoList() + + if err != nil { + m.logger.Errorf("#DeassociateRan - E2T Instance address: %s - Failed retrieving E2TInfoList. error: %s", e2tAddress, err) + return err + } + + isE2TInstanceFound := false + + for _, e2tInfoInstance := range e2tInfoList { + if e2tInfoInstance.Address == e2tAddress { + e2tInfoInstance.AssociatedRanCount-- + isE2TInstanceFound = true + break + } + } + + if !isE2TInstanceFound { + m.logger.Warnf("#DeassociateRan - E2T Instance address: %s - E2TInstance not found in E2TInfoList.", e2tAddress) + return nil + } + + err = m.rnibDataService.SaveE2TInfoList(e2tInfoList) + + if err != nil { + m.logger.Errorf("#DeassociateRan - E2T Instance address: %s - Failed saving E2TInfoList. error: %s", e2tAddress, err) + return err + } + + e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress) + + if err != nil { + m.logger.Errorf("#DeassociateRan - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err) + return err + } + + i := 0 // output index + for _, v := range e2tInstance.AssociatedRanList { + if v != ranName { + // copy and increment index + e2tInstance.AssociatedRanList[i] = v + i++ + } + } + + e2tInstance.AssociatedRanList = e2tInstance.AssociatedRanList[:i] + + err = m.rnibDataService.SaveE2TInstance(e2tInstance) + + if err != nil { + m.logger.Errorf("#DeassociateRan - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err) + return err + } + + return nil +} + +func (m *E2TInstancesManager) RemoveE2TInstance(e2tInstance *entities.E2TInstance) error { + return nil +} +func (m *E2TInstancesManager) SelectE2TInstance(e2tInstance *entities.E2TInstance) (string, error) { + return "", nil +} + +func (m *E2TInstancesManager) AssociateRan(ranName string, e2tAddress string) error { + + e2tInfoList, err := m.rnibDataService.GetE2TInfoList() + + if err != nil { + m.logger.Errorf("#AssociateRan - E2T Instance address: %s - Failed retrieving E2TInfoList. error: %s", e2tAddress, err) + return err + } + + for _, e2tInfoInstance := range e2tInfoList { + if e2tInfoInstance.Address == e2tAddress { + e2tInfoInstance.AssociatedRanCount++ + break; + } + } + + err = m.rnibDataService.SaveE2TInfoList(e2tInfoList) + + if err != nil { + m.logger.Errorf("#AssociateRan - E2T Instance address: %s - Failed saving E2TInfoList. error: %s", e2tAddress, err) + return err + } + + e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress) + + if err != nil { + m.logger.Errorf("#AssociateRan - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err) + return err + } + + e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, ranName) + + err = m.rnibDataService.SaveE2TInstance(e2tInstance) + + if err != nil { + m.logger.Errorf("#AssociateRan - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err) + return err + } + + return nil +} diff --git a/E2Manager/managers/ran_reconnection_manager.go b/E2Manager/managers/ran_reconnection_manager.go index f27f810..16614b1 100644 --- a/E2Manager/managers/ran_reconnection_manager.go +++ b/E2Manager/managers/ran_reconnection_manager.go @@ -29,21 +29,27 @@ type IRanReconnectionManager interface { } type RanReconnectionManager struct { - logger *logger.Logger - config *configuration.Configuration - rnibDataService services.RNibDataService - ranSetupManager *RanSetupManager + logger *logger.Logger + config *configuration.Configuration + rnibDataService services.RNibDataService + ranSetupManager *RanSetupManager + e2tInstancesManager IE2TInstancesManager } -func NewRanReconnectionManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, ranSetupManager *RanSetupManager) *RanReconnectionManager { +func NewRanReconnectionManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, ranSetupManager *RanSetupManager, e2tInstancesManager IE2TInstancesManager) *RanReconnectionManager { return &RanReconnectionManager{ - logger: logger, - config: config, - rnibDataService: rnibDataService, - ranSetupManager: ranSetupManager, + logger: logger, + config: config, + rnibDataService: rnibDataService, + ranSetupManager: ranSetupManager, + e2tInstancesManager: e2tInstancesManager, } } +func (m *RanReconnectionManager) isRanExceededConnectionAttempts(nodebInfo *entities.NodebInfo) bool { + return int(nodebInfo.GetConnectionAttempts()) >= m.config.MaxConnectionAttempts +} + func (m *RanReconnectionManager) ReconnectRan(inventoryName string) error { nodebInfo, rnibErr := m.rnibDataService.GetNodeb(inventoryName) @@ -55,7 +61,17 @@ func (m *RanReconnectionManager) ReconnectRan(inventoryName string) error { m.logger.Infof("#RanReconnectionManager.ReconnectRan - RAN name: %s - RAN's connection status: %s, RAN's connection attempts: %d", nodebInfo.RanName, nodebInfo.ConnectionStatus, nodebInfo.ConnectionAttempts) if !m.canReconnectRan(nodebInfo) { - return m.setConnectionStatusOfUnconnectableRan(nodebInfo) + err := m.setConnectionStatusOfUnconnectableRan(nodebInfo) + + if err != nil { + return err + } + + if m.isRanExceededConnectionAttempts(nodebInfo) { + return m.e2tInstancesManager.DeassociateRan(nodebInfo.RanName, nodebInfo.AssociatedE2TInstanceAddress) + } + + return nil } err := m.ranSetupManager.ExecuteSetup(nodebInfo, entities.ConnectionStatus_CONNECTING) @@ -104,7 +120,7 @@ func (m *RanReconnectionManager) setConnectionStatusOfUnconnectableRan(nodebInfo return m.updateNodebInfoStatus(nodebInfo, entities.ConnectionStatus_SHUT_DOWN) } - if int(nodebInfo.GetConnectionAttempts()) >= m.config.MaxConnectionAttempts { + if m.isRanExceededConnectionAttempts(nodebInfo) { m.logger.Warnf("#RanReconnectionManager.ReconnectRan - RAN name: %s - Cannot reconnect RAN. Reason: RAN's connection attempts exceeded the limit (%d)", nodebInfo.RanName, m.config.MaxConnectionAttempts) return m.updateNodebInfoStatus(nodebInfo, entities.ConnectionStatus_DISCONNECTED) } diff --git a/E2Manager/managers/ran_reconnection_manager_test.go b/E2Manager/managers/ran_reconnection_manager_test.go index 97a9f58..57d7f4f 100644 --- a/E2Manager/managers/ran_reconnection_manager_test.go +++ b/E2Manager/managers/ran_reconnection_manager_test.go @@ -33,7 +33,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.E2TInstancesManagerMock) { logger, err := logger.InitLogger(logger.DebugLevel) if err != nil { t.Errorf("#... - failed to initialize logger, error: %s", err) @@ -48,13 +48,14 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessenge 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) - return logger, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager + ranReconnectionManager := NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManagerMock) + return logger, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager, e2tInstancesManagerMock } 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"))) @@ -65,7 +66,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 @@ -77,7 +78,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 @@ -91,23 +92,44 @@ func TestShuttingdownRanReconnection(t *testing.T) { writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) } -func TestConnectingRanWithMaxAttemptsReconnection(t *testing.T) { - _, _, readerMock, writerMock, ranReconnectionManager := initRanLostConnectionTest(t) +func TestConnectingRanWithMaxAttemptsReconnectionDeassociateSucceeds(t *testing.T) { + _, _, readerMock, writerMock, ranReconnectionManager, e2tInstancesManagerMock := initRanLostConnectionTest(t) ranName := "test" - origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 20} + 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) updatedNodebInfo := *origNodebInfo updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(rnibErr) + e2tInstancesManagerMock.On("DeassociateRan", ranName, e2tAddress).Return(nil) err := ranReconnectionManager.ReconnectRan(ranName) assert.Nil(t, err) readerMock.AssertCalled(t, "GetNodeb", ranName) writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) + e2tInstancesManagerMock.AssertCalled(t, "DeassociateRan", ranName, e2tAddress) +} + +func TestConnectingRanWithMaxAttemptsReconnectionDeassociateFails(t *testing.T) { + _, _, readerMock, writerMock, ranReconnectionManager, e2tInstancesManagerMock := 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) + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(rnibErr) + e2tInstancesManagerMock.On("DeassociateRan", ranName, e2tAddress).Return(common.NewInternalError(errors.New("Error"))) + err := ranReconnectionManager.ReconnectRan(ranName) + assert.NotNil(t, err) + readerMock.AssertCalled(t, "GetNodeb", ranName) + writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1) + e2tInstancesManagerMock.AssertCalled(t, "DeassociateRan", ranName, e2tAddress) } 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 @@ -122,7 +144,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 @@ -140,7 +162,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 @@ -156,14 +178,14 @@ func TestConnectedRanExecuteSetupFailure(t *testing.T) { } func TestUnnecessaryUpdateNodebInfoStatus(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.updateNodebInfoStatus(nodebInfo, entities.ConnectionStatus_CONNECTED) assert.Nil(t, err) } 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.setConnectionStatusOfUnconnectableRan(nodebInfo) assert.Nil(t, err) diff --git a/E2Manager/mocks/e2t_instances_manager_mock.go b/E2Manager/mocks/e2t_instances_manager_mock.go new file mode 100644 index 0000000..d7e9aba --- /dev/null +++ b/E2Manager/mocks/e2t_instances_manager_mock.go @@ -0,0 +1,58 @@ +// +// 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. +// +package mocks + +import ( + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" + "github.com/stretchr/testify/mock" +) + +type E2TInstancesManagerMock struct { + mock.Mock +} + +func (m *E2TInstancesManagerMock) GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error) { + args := m.Called(e2tAddress) + + return args.Get(0).(*entities.E2TInstance), args.Error(1) +} + +func (m *E2TInstancesManagerMock) AddE2TInstance(e2tInstanceAddress string) error { + args := m.Called(e2tInstanceAddress) + return args.Error(0) +} + +func (m *E2TInstancesManagerMock) RemoveE2TInstance(e2tInstance *entities.E2TInstance) error { + args := m.Called(e2tInstance) + return args.Error(0) +} + +func (m *E2TInstancesManagerMock) SelectE2TInstance(e2tInstance *entities.E2TInstance) (string, error) { + args := m.Called(e2tInstance) + return args.String(0), args.Error(1) +} + +func (m *E2TInstancesManagerMock) AssociateRan(ranName string, e2tAddress string) error { + args := m.Called(ranName, e2tAddress) + return args.Error(0) + +} +func (m *E2TInstancesManagerMock) DeassociateRan(ranName string, e2tAddress string) error { + args := m.Called(ranName, e2tAddress) + return args.Error(0) + +} diff --git a/E2Manager/mocks/rnibReaderMock.go b/E2Manager/mocks/rnibReaderMock.go index 5ac4b20..e9b78bb 100644 --- a/E2Manager/mocks/rnibReaderMock.go +++ b/E2Manager/mocks/rnibReaderMock.go @@ -146,3 +146,13 @@ func (m *RnibReaderMock) GetRanLoadInformation(inventoryName string) (*entities. return args.Get(0).(*entities.RanLoadInformation), nil } + +func (m *RnibReaderMock) GetE2TInstance(e2taddress string) (*entities.E2TInstance, error) { + args := m.Called(e2taddress) + return args.Get(0).(*entities.E2TInstance), args.Error(1) +} + +func (m *RnibReaderMock) GetE2TInfoList() ([]*entities.E2TInstanceInfo, error) { + args := m.Called() + return args.Get(0).([]*entities.E2TInstanceInfo), args.Error(1) +} \ No newline at end of file diff --git a/E2Manager/mocks/rnibWriterMock.go b/E2Manager/mocks/rnibWriterMock.go index d6b1ef9..08341ef 100644 --- a/E2Manager/mocks/rnibWriterMock.go +++ b/E2Manager/mocks/rnibWriterMock.go @@ -61,3 +61,15 @@ func (rnibWriterMock *RnibWriterMock) SaveRanLoadInformation(inventoryName strin return nil } + +func (rnibWriterMock *RnibWriterMock) SaveE2TInstance(e2tInstance *entities.E2TInstance) error { + args := rnibWriterMock.Called(e2tInstance) + + return args.Error(0) +} + +func (rnibWriterMock *RnibWriterMock) SaveE2TInfoList(e2tInfoList []*entities.E2TInstanceInfo) error { + args := rnibWriterMock.Called(e2tInfoList) + + return args.Error(0) +} diff --git a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go index 25c3311..ff1ea7d 100644 --- a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go +++ b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go @@ -65,7 +65,8 @@ func (provider *NotificationHandlerProvider) Init(logger *logger.Logger, config x2ResetResponseExtractor := converters.NewX2ResetResponseExtractor(logger) // Init managers - ranReconnectionManager := managers.NewRanReconnectionManager(logger, config, rnibDataService, ranSetupManager) + e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger) + ranReconnectionManager := managers.NewRanReconnectionManager(logger, config, rnibDataService, ranSetupManager, e2tInstancesManager) ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender) x2SetupResponseManager := managers.NewX2SetupResponseManager(x2SetupResponseConverter) x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter) @@ -83,7 +84,7 @@ func (provider *NotificationHandlerProvider) Init(logger *logger.Logger, config endcConfigurationUpdateHandler := rmrmsghandlers.NewEndcConfigurationUpdateHandler(logger, rmrSender) x2ResetResponseHandler := rmrmsghandlers.NewX2ResetResponseHandler(logger, rnibDataService, ranStatusChangeManager, x2ResetResponseExtractor) x2ResetRequestNotificationHandler := rmrmsghandlers.NewX2ResetRequestNotificationHandler(logger, rnibDataService, ranStatusChangeManager, rmrSender) - e2TermInitNotificationHandler := rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService) + e2TermInitNotificationHandler := rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService, e2tInstancesManager) provider.Register(rmrCgo.RIC_X2_SETUP_RESP, x2SetupResponseHandler) provider.Register(rmrCgo.RIC_X2_SETUP_FAILURE, x2SetupFailureResponseHandler) diff --git a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go index 757c0d4..5dd3eac 100644 --- a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go +++ b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go @@ -72,7 +72,8 @@ func TestGetNotificationHandlerSuccess(t *testing.T) { logger, config, rnibDataService, rmrSender, ranSetupManager := initTestCase(t) - ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager) + e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger) + ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager, e2tInstancesManager) ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender) x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger) @@ -101,7 +102,7 @@ func TestGetNotificationHandlerSuccess(t *testing.T) { {rmrCgo.RIC_ENB_LOAD_INFORMATION, rmrmsghandlers.NewEnbLoadInformationNotificationHandler(logger, rnibDataService, converters.NewEnbLoadInformationExtractor(logger))}, {rmrCgo.RIC_ENB_CONF_UPDATE, rmrmsghandlers.NewX2EnbConfigurationUpdateHandler(logger, rmrSender)}, {rmrCgo.RIC_ENDC_CONF_UPDATE, rmrmsghandlers.NewEndcConfigurationUpdateHandler(logger, rmrSender)}, - {rmrCgo.RIC_E2_TERM_INIT, rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService)}, + {rmrCgo.RIC_E2_TERM_INIT, rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService, e2tInstancesManager)}, {rmrCgo.RIC_X2_RESET_RESP, rmrmsghandlers.NewX2ResetResponseHandler(logger, rnibDataService, ranStatusChangeManager, converters.NewX2ResetResponseExtractor(logger))}, {rmrCgo.RIC_X2_RESET, rmrmsghandlers.NewX2ResetRequestNotificationHandler(logger, rnibDataService, ranStatusChangeManager, rmrSender)}, } diff --git a/E2Manager/rNibWriter/rNibWriter.go b/E2Manager/rNibWriter/rNibWriter.go index 202a273..bd3f1d2 100644 --- a/E2Manager/rNibWriter/rNibWriter.go +++ b/E2Manager/rNibWriter/rNibWriter.go @@ -18,12 +18,15 @@ package rNibWriter import ( + "encoding/json" "fmt" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" "github.com/golang/protobuf/proto" ) +const E2TInfoListKey = "E2TInfoList" + type rNibWriterInstance struct { sdl common.ISdlInstance } @@ -35,6 +38,8 @@ type RNibWriter interface { SaveNodeb(nbIdentity *entities.NbIdentity, nb *entities.NodebInfo) error UpdateNodebInfo(nodebInfo *entities.NodebInfo) error SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error + SaveE2TInstance(e2tInstance *entities.E2TInstance) error + SaveE2TInfoList(e2tInfoList []*entities.E2TInstanceInfo) error } /* @@ -180,6 +185,52 @@ func (w *rNibWriterInstance) SaveRanLoadInformation(inventoryName string, ranLoa return nil } +func (w *rNibWriterInstance) SaveE2TInstance(e2tInstance *entities.E2TInstance) error { + + key, rnibErr := common.ValidateAndBuildE2TInstanceKey(e2tInstance.Address) + + if rnibErr != nil { + return rnibErr + } + + data, err := json.Marshal(e2tInstance) + + if err != nil { + return common.NewInternalError(err) + } + + var pairs []interface{} + pairs = append(pairs, key, data) + + err = w.sdl.Set(pairs) + + if err != nil { + return common.NewInternalError(err) + } + + return nil +} + +func (w *rNibWriterInstance) SaveE2TInfoList(e2tInfoList []*entities.E2TInstanceInfo) error { + + data, err := json.Marshal(e2tInfoList) + + if err != nil { + return common.NewInternalError(err) + } + + var pairs []interface{} + pairs = append(pairs, E2TInfoListKey, data) + + err = w.sdl.Set(pairs) + + if err != nil { + return common.NewInternalError(err) + } + + return nil +} + /* Close the writer */ diff --git a/E2Manager/services/rnib_data_service.go b/E2Manager/services/rnib_data_service.go index 1e824e8..1ac2068 100644 --- a/E2Manager/services/rnib_data_service.go +++ b/E2Manager/services/rnib_data_service.go @@ -35,6 +35,10 @@ type RNibDataService interface { GetNodeb(ranName string) (*entities.NodebInfo, error) GetListNodebIds() ([]*entities.NbIdentity, error) PingRnib() bool + GetE2TInstance(address string) (*entities.E2TInstance, error) + GetE2TInfoList() ([]*entities.E2TInstanceInfo, error) + SaveE2TInstance(e2tInstance *entities.E2TInstance) error + SaveE2TInfoList(e2tInfoList []*entities.E2TInstanceInfo) error } type rNibDataService struct { @@ -114,6 +118,53 @@ func (w *rNibDataService) GetListNodebIds() ([]*entities.NbIdentity, error) { return nodeIds, err } +func (w *rNibDataService) GetE2TInstance(address string) (*entities.E2TInstance, error) { + w.logger.Infof("#RnibDataService.GetE2TInstance") + + var e2tInstance *entities.E2TInstance = nil + + err := w.retry("GetE2TInstance", func() (err error) { + e2tInstance, err = w.rnibReader.GetE2TInstance(address) + return + }) + + return e2tInstance, err +} +func (w *rNibDataService) GetE2TInfoList() ([]*entities.E2TInstanceInfo, error) { + w.logger.Infof("#RnibDataService.GetE2TInfoList") + + var e2tInfoList []*entities.E2TInstanceInfo = nil + + err := w.retry("GetE2TInfoList", func() (err error) { + e2tInfoList, err = w.rnibReader.GetE2TInfoList() + return + }) + + return e2tInfoList, err +} + +func (w *rNibDataService) SaveE2TInstance(e2tInstance *entities.E2TInstance) error { + w.logger.Infof("#RnibDataService.SaveE2TInstance") + + err := w.retry("SaveE2TInstance", func() (err error) { + err = w.rnibWriter.SaveE2TInstance(e2tInstance) + return + }) + + return err +} + +func (w *rNibDataService) SaveE2TInfoList(e2tInfoList []*entities.E2TInstanceInfo) error { + w.logger.Infof("#RnibDataService.SaveE2TInfoList") + + err := w.retry("SaveE2TInfoList", func() (err error) { + err = w.rnibWriter.SaveE2TInfoList(e2tInfoList) + return + }) + + return err +} + func (w *rNibDataService) PingRnib() bool { err := w.retry("GetListNodebIds", func() (err error) { _, err = w.rnibReader.GetListNodebIds()