From: Amichai Date: Sun, 14 Jun 2020 14:12:15 +0000 (+0300) Subject: [RIC-397] Add RanConnectStatusChangeManager + support SetAnsPublish X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F93%2F4093%2F1;p=ric-plt%2Fe2mgr.git [RIC-397] Add RanConnectStatusChangeManager + support SetAnsPublish Change-Id: Ic1bb1662b273074d8dbdff20eecaaaeaf3081835 Signed-off-by: Amichai --- diff --git a/E2Manager/configuration/configuration.go b/E2Manager/configuration/configuration.go index 791360a..f539c5d 100644 --- a/E2Manager/configuration/configuration.go +++ b/E2Manager/configuration/configuration.go @@ -53,6 +53,7 @@ type Configuration struct { Mcc string Mnc string } + StateChangeMessageChannel string } func ParseConfiguration() *Configuration { @@ -80,6 +81,7 @@ func ParseConfiguration() *Configuration { config.KeepAliveDelayMs = viper.GetInt("KeepAliveDelayMs") config.E2TInstanceDeletionTimeoutMs = viper.GetInt("e2tInstanceDeletionTimeoutMs") config.populateGlobalRicIdConfig(viper.Sub("globalRicId")) + config.StateChangeMessageChannel = viper.GetString("stateChangeMessageChannel") return &config } @@ -217,7 +219,7 @@ func (c *Configuration) String() string { return fmt.Sprintf("{logging.logLevel: %s, http.port: %d, rmr: { port: %d, maxMsgSize: %d}, routingManager.baseUrl: %s, "+ "notificationResponseBuffer: %d, bigRedButtonTimeoutSec: %d, maxRnibConnectionAttempts: %d, "+ "rnibRetryIntervalMs: %d, keepAliveResponseTimeoutMs: %d, keepAliveDelayMs: %d, e2tInstanceDeletionTimeoutMs: %d, "+ - "globalRicId: { ricId: %s, mcc: %s, mnc: %s}", + "globalRicId: { ricId: %s, mcc: %s, mnc: %s}, StateChangeMessageChannel: %s", c.Logging.LogLevel, c.Http.Port, c.Rmr.Port, @@ -233,5 +235,6 @@ func (c *Configuration) String() string { c.GlobalRicId.RicId, c.GlobalRicId.Mcc, c.GlobalRicId.Mnc, + c.StateChangeMessageChannel, ) } diff --git a/E2Manager/configuration/configuration_test.go b/E2Manager/configuration/configuration_test.go index 4a3dff3..27fd1b4 100644 --- a/E2Manager/configuration/configuration_test.go +++ b/E2Manager/configuration/configuration_test.go @@ -43,6 +43,7 @@ func TestParseConfigurationSuccess(t *testing.T) { assert.Equal(t, "AACCE", config.GlobalRicId.RicId) assert.Equal(t, "310", config.GlobalRicId.Mcc) assert.Equal(t, "411", config.GlobalRicId.Mnc) + assert.Equal(t, "RAN_CONNECTION_STATUS_CHANGE", config.StateChangeMessageChannel) } func TestStringer(t *testing.T) { diff --git a/E2Manager/go.sum b/E2Manager/go.sum index dd2ffa7..5756914 100644 --- a/E2Manager/go.sum +++ b/E2Manager/go.sum @@ -1,16 +1,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.41 h1:91VlUsqMooia8F1JvBXh8F8x3n0lj1xqCV0jmx4bm20= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.41/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.42 h1:k3Qpj1BiBPgu+HnMJl3TAi6MlcNwxgij3nY8Kw4NYW0= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.42/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.41 h1:nq2GgOIc/53lldmOe0pe6qZSxLkOrCRSNWeKTCeijDo= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.41/go.mod h1:YaQ+XEI4PcAoISxp9wUpUr2TP0J7JihpQTD0G1Lpd4A= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.42 h1:EPdPmvU3iXgB4b91lNN8wl+WSpXCLi7gDm4yJTOrl/o= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.42/go.mod h1:YaQ+XEI4PcAoISxp9wUpUr2TP0J7JihpQTD0G1Lpd4A= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.41 h1:hVl06Y+wwusyuCHgbsUI/BY63HUvkoZYS3iS0vm1XKc= -gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.41/go.mod h1:xu3UO+VN6JdiWDRxzGzdanTbH7hh7sanrWtTB7YtBBs= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.42 h1:PyAnsgqXVV3w+1utUrtvh1KfxuVMCYvUXGYOFarChto= gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.42/go.mod h1:K0P3Xh2NXHCwdIDY47IxeElCBVZdT4KqapPBpS7g3JU= gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2 h1:UK7awyRKIkVdokWvvkYvazlg3EWIfMnIqCcJxTnLlDA= diff --git a/E2Manager/managers/ran_connect_status_change_manager.go b/E2Manager/managers/ran_connect_status_change_manager.go new file mode 100644 index 0000000..8818399 --- /dev/null +++ b/E2Manager/managers/ran_connect_status_change_manager.go @@ -0,0 +1,131 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source code is part of the near-RT RIC (RAN Intelligent Controller) +// platform project (RICP). + +package managers + +import ( + "e2mgr/logger" + "e2mgr/services" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" +) + +const ( + CONNECTED_RAW_EVENT = "CONNECTED" + DISCONNECTED_RAW_EVENT = "DISCONNECTED" + NONE_RAW_EVENT = "NONE" +) + +type RanConnectStatusChangeManager struct { + logger *logger.Logger + rnibDataService services.RNibDataService + ranListManager RanListManager + ranAlarmService services.RanAlarmService +} + +func NewRanConnectStatusChangeManager(logger *logger.Logger, rnibDataService services.RNibDataService, ranListManager RanListManager, ranAlarmService services.RanAlarmService) *RanConnectStatusChangeManager { + return &RanConnectStatusChangeManager{ + logger: logger, + rnibDataService: rnibDataService, + ranListManager: ranListManager, + ranAlarmService: ranAlarmService, + } +} + +func (m *RanConnectStatusChangeManager) ChangeStatus(nodebInfo *entities.NodebInfo, nextStatus entities.ConnectionStatus) error { + m.logger.Infof("#RanConnectStatusChangeManager.ChangeStatus - RAN name: %s, currentStatus: %s, nextStatus: %s", nodebInfo.RanName, nodebInfo.GetConnectionStatus(), nextStatus) + + // set the proper event + event := m.setEvent(nodebInfo, nextStatus) + isConnectivityEvent := event != NONE_RAW_EVENT + + // only after determining event we set next status + nodebInfo.ConnectionStatus = nextStatus; + if !isConnectivityEvent { + err := m.updateNodebInfo(nodebInfo) + if err != nil { + return err + } + } else { + err := m.updateNodebConnectivityState(nodebInfo, event) + if err != nil { + return err + } + } + + // in any case, update RanListManager + m.logger.Infof("#RanConnectStatusChangeManager.ChangeStatus - RAN name: %s, updating RanListManager... status: %s", nodebInfo.RanName, nodebInfo.GetConnectionStatus()) + err := m.ranListManager.UpdateRanState(nodebInfo) + if err != nil { + m.logger.Errorf("#RanConnectStatusChangeManager.ChangeStatus - RAN name: %s - Failed updating RAN's connection status by RanListManager. Error: %v", nodebInfo.RanName, err) + // log and proceed... + } + + if isConnectivityEvent { + m.logger.Infof("#RanConnectStatusChangeManager.ChangeStatus - RAN name: %s, setting alarm at RanAlarmService... event: %s", nodebInfo.RanName, event) + err := m.ranAlarmService.SetConnectivityChangeAlarm(nodebInfo) + if err != nil { + m.logger.Errorf("#RanConnectStatusChangeManager.ChangeStatus - RAN name: %s - Failed setting an alarm by RanAlarmService. Error: %v", nodebInfo.RanName, err) + // log and proceed... + } + } + + return nil +} + +func (m *RanConnectStatusChangeManager) updateNodebConnectivityState(nodebInfo *entities.NodebInfo, event string) error { + + err := m.rnibDataService.UpdateNodebConnectivityState(nodebInfo, event) + + if err != nil { + m.logger.Errorf("#RanConnectStatusChangeManager.updateNodebConnectivityState - RAN name: %s - Failed updating RAN's connection status in rNib. Error: %v", nodebInfo.RanName, err) + return err + } + + m.logger.Infof("#RanConnectStatusChangeManager.updateNodebConnectivityState - RAN name: %s - Successfully updated rNib.", nodebInfo.RanName) + return nil +} + +func (m *RanConnectStatusChangeManager) updateNodebInfo(nodebInfo *entities.NodebInfo) error { + + err := m.rnibDataService.UpdateNodebInfo(nodebInfo) + + if err != nil { + m.logger.Errorf("#RanConnectStatusChangeManager.updateNodebInfo - RAN name: %s - Failed updating RAN's connection status in rNib. Error: %v", nodebInfo.RanName, err) + return err + } + + m.logger.Infof("#RanConnectStatusChangeManager.updateNodebInfo - RAN name: %s - Successfully updated rNib.", nodebInfo.RanName) + return nil +} + +func (m *RanConnectStatusChangeManager) setEvent(nodebInfo *entities.NodebInfo, nextState entities.ConnectionStatus) string { + currentConnectionStatus := nodebInfo.GetConnectionStatus() + + var event string + if currentConnectionStatus != entities.ConnectionStatus_CONNECTED && nextState == entities.ConnectionStatus_CONNECTED { + event = nodebInfo.RanName + "_" + CONNECTED_RAW_EVENT + } else if currentConnectionStatus == entities.ConnectionStatus_CONNECTED && nextState != entities.ConnectionStatus_CONNECTED { + event = nodebInfo.RanName + "_" + DISCONNECTED_RAW_EVENT + } else { + event = NONE_RAW_EVENT + } + + m.logger.Infof("#RanConnectStatusChangeManager.setEvent - Connectivity Event for RAN %s is: %s", nodebInfo.RanName, event) + return event +} diff --git a/E2Manager/managers/ran_connect_status_change_manager_test.go b/E2Manager/managers/ran_connect_status_change_manager_test.go new file mode 100644 index 0000000..4dc77af --- /dev/null +++ b/E2Manager/managers/ran_connect_status_change_manager_test.go @@ -0,0 +1,187 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source code is part of the near-RT RIC (RAN Intelligent Controller) +// platform project (RICP). + +package managers + +import ( + "e2mgr/configuration" + "e2mgr/logger" + "e2mgr/mocks" + "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" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "testing" +) + +const EventChannelForTest = "RAN_CONNECTION_STATUS_CHANGE" + +func initRanConnectStatusChangeManagerTest(t *testing.T) (*mocks.RnibWriterMock, *mocks.RanListManagerMock, *mocks.RanAlarmServiceMock, *RanConnectStatusChangeManager) { + log, err := logger.InitLogger(logger.DebugLevel) + if err != nil { + t.Errorf("#... - failed to initialize log, error: %s", err) + } + config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, StateChangeMessageChannel: EventChannelForTest} + + readerMock := &mocks.RnibReaderMock{} + writerMock := &mocks.RnibWriterMock{} + rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock) + ranListManagerMock := &mocks.RanListManagerMock{} + ranAlarmServiceMock := &mocks.RanAlarmServiceMock{} + ranConnectStatusChangeManager := NewRanConnectStatusChangeManager(log, rnibDataService, ranListManagerMock, ranAlarmServiceMock) + return writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager +} + +func TestChangeStatusSuccessNewRan(t *testing.T) { + writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t) + + origNodebInfo := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_UNKNOWN_CONNECTION_STATUS} + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED + writerMock.On("UpdateNodebConnectivityState", &updatedNodebInfo, EventChannelForTest, RanName + "_" + CONNECTED_RAW_EVENT).Return(nil) + ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil) + ranAlarmServiceMock.On("SetConnectivityChangeAlarm", &updatedNodebInfo).Return(nil) + err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_CONNECTED) + assert.Nil(t, err) + writerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) + ranAlarmServiceMock.AssertExpectations(t) +} + +func TestChangeStatusSuccessEventNone1(t *testing.T) { + writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t) + + origNodebInfo := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN} + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(nil) + ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil) + err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_SHUT_DOWN) + assert.Nil(t, err) + writerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) + ranAlarmServiceMock.AssertExpectations(t) +} + +func TestChangeStatusSuccessEventNone2(t *testing.T) { + writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t) + + origNodebInfo := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED} + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(nil) + ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil) + err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_SHUT_DOWN) + assert.Nil(t, err) + writerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) + ranAlarmServiceMock.AssertExpectations(t) +} + +func TestChangeStatusSuccessEventConnected(t *testing.T) { + writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t) + + origNodebInfo := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED} + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED + writerMock.On("UpdateNodebConnectivityState", &updatedNodebInfo, EventChannelForTest, RanName + "_" + CONNECTED_RAW_EVENT).Return(nil) + ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil) + ranAlarmServiceMock.On("SetConnectivityChangeAlarm", &updatedNodebInfo).Return(nil) + err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_CONNECTED) + assert.Nil(t, err) + writerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) + ranAlarmServiceMock.AssertExpectations(t) +} + +func TestChangeStatusSuccessEventDisconnected(t *testing.T) { + writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t) + + origNodebInfo := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED} + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED + writerMock.On("UpdateNodebConnectivityState", &updatedNodebInfo, EventChannelForTest, RanName + "_" + DISCONNECTED_RAW_EVENT).Return(nil) + ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil) + ranAlarmServiceMock.On("SetConnectivityChangeAlarm", &updatedNodebInfo).Return(nil) + err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_DISCONNECTED) + assert.Nil(t, err) + writerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) + ranAlarmServiceMock.AssertExpectations(t) +} + +func TestChangeStatusRnibErrorEventNone(t *testing.T) { + writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t) + + origNodebInfo := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN} + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error"))) + err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_SHUT_DOWN) + assert.NotNil(t, err) + writerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) + ranAlarmServiceMock.AssertExpectations(t) +} + +func TestChangeStatusRnibErrorEventConnected(t *testing.T) { + writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t) + + origNodebInfo := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED} + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED + writerMock.On("UpdateNodebConnectivityState", &updatedNodebInfo, EventChannelForTest, RanName + "_" + CONNECTED_RAW_EVENT).Return(common.NewInternalError(errors.New("Error"))) + err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_CONNECTED) + assert.NotNil(t, err) + writerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) + ranAlarmServiceMock.AssertExpectations(t) +} + +func TestChangeStatusRanListManagerError(t *testing.T) { + writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t) + + origNodebInfo := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN} + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN + writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(nil) + ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error"))) + err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_SHUT_DOWN) + assert.Nil(t, err) + writerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) + ranAlarmServiceMock.AssertExpectations(t) +} + +func TestChangeStatusRanAlarmServiceErrorEventConnected(t *testing.T) { + writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t) + + origNodebInfo := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED} + updatedNodebInfo := *origNodebInfo + updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED + writerMock.On("UpdateNodebConnectivityState", &updatedNodebInfo, EventChannelForTest, RanName + "_" + CONNECTED_RAW_EVENT).Return(nil) + ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil) + ranAlarmServiceMock.On("SetConnectivityChangeAlarm", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error"))) + err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_CONNECTED) + assert.Nil(t, err) + writerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) + ranAlarmServiceMock.AssertExpectations(t) +} \ No newline at end of file diff --git a/E2Manager/managers/ran_list_manager.go b/E2Manager/managers/ran_list_manager.go new file mode 100644 index 0000000..9ad10f2 --- /dev/null +++ b/E2Manager/managers/ran_list_manager.go @@ -0,0 +1,44 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source code is part of the near-RT RIC (RAN Intelligent Controller) +// platform project (RICP). + +package managers + +import ( + "e2mgr/logger" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" +) + +type ranListManagerInstance struct { + logger *logger.Logger +} + +type RanListManager interface { + UpdateRanState(nodebInfo *entities.NodebInfo) error +} + +func NewRanListManager(logger *logger.Logger) RanListManager { + return &ranListManagerInstance{ + logger: logger, + } +} + +func (m *ranListManagerInstance) UpdateRanState(nodebInfo *entities.NodebInfo) error { + m.logger.Infof("#ranListManagerInstance.UpdateRanState - RAN name: %s - Updating state...", nodebInfo.RanName) + return nil +} diff --git a/E2Manager/mocks/ran_alarm_service_mock.go b/E2Manager/mocks/ran_alarm_service_mock.go new file mode 100644 index 0000000..ed18c88 --- /dev/null +++ b/E2Manager/mocks/ran_alarm_service_mock.go @@ -0,0 +1,35 @@ +// +// 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 mocks + +import ( + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" + "github.com/stretchr/testify/mock" +) + +type RanAlarmServiceMock struct { + mock.Mock +} + +func (m *RanAlarmServiceMock) SetConnectivityChangeAlarm(nodebInfo *entities.NodebInfo) error { + + args := m.Called(nodebInfo) + return args.Error(0) +} \ No newline at end of file diff --git a/E2Manager/mocks/ran_list_manager_mock.go b/E2Manager/mocks/ran_list_manager_mock.go new file mode 100644 index 0000000..6df5c4f --- /dev/null +++ b/E2Manager/mocks/ran_list_manager_mock.go @@ -0,0 +1,35 @@ +// +// 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 mocks + +import ( + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" + "github.com/stretchr/testify/mock" +) + +type RanListManagerMock struct { + mock.Mock +} + +func (m *RanListManagerMock) UpdateRanState(nodebInfo *entities.NodebInfo) error { + + args := m.Called(nodebInfo) + return args.Error(0) +} \ No newline at end of file diff --git a/E2Manager/mocks/rnibWriterMock.go b/E2Manager/mocks/rnibWriterMock.go index 5c602bb..bf2ed53 100644 --- a/E2Manager/mocks/rnibWriterMock.go +++ b/E2Manager/mocks/rnibWriterMock.go @@ -92,3 +92,7 @@ func (rnibWriterMock *RnibWriterMock) RemoveServedNrCells(inventoryName string, return args.Error(0) } +func (rnibWriterMock *RnibWriterMock) UpdateNodebConnectivityState(nodebInfo *entities.NodebInfo, stateChangeMessageChannel string, event string) error { + args := rnibWriterMock.Called(nodebInfo, stateChangeMessageChannel, event) + return args.Error(0) +} \ No newline at end of file diff --git a/E2Manager/rNibWriter/rNibWriter.go b/E2Manager/rNibWriter/rNibWriter.go index a44f388..5bc4a68 100644 --- a/E2Manager/rNibWriter/rNibWriter.go +++ b/E2Manager/rNibWriter/rNibWriter.go @@ -45,6 +45,7 @@ type RNibWriter interface { RemoveE2TInstance(e2tAddress string) error UpdateGnbCells(nodebInfo *entities.NodebInfo, servedNrCells []*entities.ServedNRCell) error RemoveServedNrCells(inventoryName string, servedNrCells []*entities.ServedNRCell) error + UpdateNodebConnectivityState(nodebInfo *entities.NodebInfo, stateChangeMessageChannel string, event string) error } /* @@ -315,6 +316,26 @@ func (w *rNibWriterInstance) RemoveE2TInstance(address string) error { return nil } +/* +UpdateNodebConnectivityState... +*/ +func (w *rNibWriterInstance) UpdateNodebConnectivityState(nodebInfo *entities.NodebInfo, stateChangeMessageChannel string, event string) error { + + pairs, err := buildUpdateNodebInfoPairs(nodebInfo) + + if err != nil { + return err + } + + err = w.sdl.SetAndPublish([]string{stateChangeMessageChannel, event}, pairs) + + 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 dc5450b..b77e97e 100644 --- a/E2Manager/rNibWriter/rNibWriter_test.go +++ b/E2Manager/rNibWriter/rNibWriter_test.go @@ -743,6 +743,83 @@ func TestRemoveE2TInstanceEmptyAddressFailure(t *testing.T) { sdlInstanceMock.AssertExpectations(t) } +func TestUpdateNodebConnectivityStateSuccess(t *testing.T) { + inventoryName := "name" + plmnId := "02f829" + nbId := "4a952a0a" + channelName := "RAN_CONNECT_STATE_CHANGE" + eventName := inventoryName + "_" + "CONNECTED" + w, sdlInstanceMock := initSdlInstanceMock(namespace) + nodebInfo := generateNodebInfo(inventoryName, entities.Node_ENB, plmnId, nbId) + data, err := proto.Marshal(nodebInfo) + if err != nil { + t.Errorf("#rNibWriter_test.TestUpdateNodebConnectivityStateSuccess - Failed to marshal NodeB entity. Error: %v", err) + } + var e error + var setExpected []interface{} + + nodebNameKey := fmt.Sprintf("RAN:%s", inventoryName) + nodebIdKey := fmt.Sprintf("ENB:%s:%s", plmnId, nbId) + setExpected = append(setExpected, nodebNameKey, data) + setExpected = append(setExpected, nodebIdKey, data) + + sdlInstanceMock.On("SetAndPublish", []string{channelName, eventName}, []interface{}{setExpected}).Return(e) + + rNibErr := w.UpdateNodebConnectivityState(nodebInfo, channelName, eventName) + assert.Nil(t, rNibErr) +} + +func TestUpdateNodebConnectivityStateMissingInventoryNameFailure(t *testing.T) { + inventoryName := "name" + plmnId := "02f829" + nbId := "4a952a0a" + channelName := "RAN_CONNECT_STATE_CHANGE" + eventName := inventoryName + "_" + "CONNECTED" + w, sdlInstanceMock := initSdlInstanceMock(namespace) + nodebInfo := &entities.NodebInfo{} + data, err := proto.Marshal(nodebInfo) + if err != nil { + t.Errorf("#rNibWriter_test.TestUpdateNodebConnectivityStateMissingInventoryNameFailure - Failed to marshal NodeB entity. Error: %v", err) + } + var e error + var setExpected []interface{} + + nodebNameKey := fmt.Sprintf("RAN:%s", inventoryName) + nodebIdKey := fmt.Sprintf("ENB:%s:%s", plmnId, nbId) + setExpected = append(setExpected, nodebNameKey, data) + setExpected = append(setExpected, nodebIdKey, data) + + sdlInstanceMock.On("SetAndPublish", []string{channelName, eventName}, []interface{}{setExpected}).Return(e) + + rNibErr := w.UpdateNodebConnectivityState(nodebInfo, channelName, eventName) + + assert.NotNil(t, rNibErr) + assert.IsType(t, &common.ValidationError{}, rNibErr) +} + +func TestUpdateNodebConnectivityStateMissingGlobalNbId(t *testing.T) { + inventoryName := "name" + channelName := "RAN_CONNECT_STATE_CHANGE" + eventName := inventoryName + "_" + "CONNECTED" + w, sdlInstanceMock := initSdlInstanceMock(namespace) + nodebInfo := &entities.NodebInfo{} + nodebInfo.RanName = inventoryName + data, err := proto.Marshal(nodebInfo) + if err != nil { + t.Errorf("#rNibWriter_test.TestSaveEnb - Failed to marshal NodeB entity. Error: %v", err) + } + var e error + var setExpected []interface{} + + nodebNameKey := fmt.Sprintf("RAN:%s", inventoryName) + setExpected = append(setExpected, nodebNameKey, data) + sdlInstanceMock.On("SetAndPublish", []string{channelName, eventName}, []interface{}{setExpected}).Return(e) + + rNibErr := w.UpdateNodebConnectivityState(nodebInfo, channelName, eventName) + + assert.Nil(t, rNibErr) +} + //Integration tests // //func TestSaveEnbGnbInteg(t *testing.T){ diff --git a/E2Manager/resources/configuration.yaml b/E2Manager/resources/configuration.yaml index fc77022..6beba8f 100644 --- a/E2Manager/resources/configuration.yaml +++ b/E2Manager/resources/configuration.yaml @@ -17,4 +17,5 @@ e2tInstanceDeletionTimeoutMs: 15000 globalRicId: ricId: "AACCE" mcc: "310" - mnc: "411" \ No newline at end of file + mnc: "411" +stateChangeMessageChannel: RAN_CONNECTION_STATUS_CHANGE \ No newline at end of file diff --git a/E2Manager/services/ran_alarm_service.go b/E2Manager/services/ran_alarm_service.go new file mode 100644 index 0000000..046b183 --- /dev/null +++ b/E2Manager/services/ran_alarm_service.go @@ -0,0 +1,47 @@ +// +// 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 services + +import ( + "e2mgr/configuration" + "e2mgr/logger" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" +) + +type ranAlarmServiceInstance struct { + logger *logger.Logger + config *configuration.Configuration +} + +type RanAlarmService interface { + SetConnectivityChangeAlarm(nodebInfo *entities.NodebInfo) error +} + +func NewRanAlarmService(logger *logger.Logger, config *configuration.Configuration) RanAlarmService { + return &ranAlarmServiceInstance{ + logger: logger, + config: config, + } +} + +func (m *ranAlarmServiceInstance) SetConnectivityChangeAlarm(nodebInfo *entities.NodebInfo) error { + m.logger.Infof("#ranAlarmServiceInstance.SetConnectivityChangeAlarm - RAN name: %s - Connectivity state was changed to %s", nodebInfo.RanName, nodebInfo.ConnectionStatus) + return nil +} diff --git a/E2Manager/services/rnib_data_service.go b/E2Manager/services/rnib_data_service.go index 1edfa7c..3ca944a 100644 --- a/E2Manager/services/rnib_data_service.go +++ b/E2Manager/services/rnib_data_service.go @@ -50,23 +50,26 @@ type RNibDataService interface { UpdateGnbCells(nodebInfo *entities.NodebInfo, servedNrCells []*entities.ServedNRCell) error RemoveServedNrCells(inventoryName string, servedNrCells []*entities.ServedNRCell) error GetGeneralConfiguration() (*entities.GeneralConfiguration, error) + UpdateNodebConnectivityState(nodebInfo *entities.NodebInfo, event string) error } type rNibDataService struct { - logger *logger.Logger - rnibReader reader.RNibReader - rnibWriter rNibWriter.RNibWriter - maxAttempts int - retryInterval time.Duration + logger *logger.Logger + rnibReader reader.RNibReader + rnibWriter rNibWriter.RNibWriter + maxAttempts int + retryInterval time.Duration + stateChangeMessageChannel string } func NewRnibDataService(logger *logger.Logger, config *configuration.Configuration, rnibReader reader.RNibReader, rnibWriter rNibWriter.RNibWriter) *rNibDataService { return &rNibDataService{ - logger: logger, - rnibReader: rnibReader, - rnibWriter: rnibWriter, - maxAttempts: config.MaxRnibConnectionAttempts, - retryInterval: time.Duration(config.RnibRetryIntervalMs) * time.Millisecond, + logger: logger, + rnibReader: rnibReader, + rnibWriter: rnibWriter, + maxAttempts: config.MaxRnibConnectionAttempts, + retryInterval: time.Duration(config.RnibRetryIntervalMs) * time.Millisecond, + stateChangeMessageChannel: config.StateChangeMessageChannel, } } @@ -294,6 +297,17 @@ func (w *rNibDataService) PingRnib() bool { return !isRnibConnectionError(err) } +func (w *rNibDataService) UpdateNodebConnectivityState(nodebInfo *entities.NodebInfo, event string) error { + w.logger.Infof("#RnibDataService.UpdateNodebConnectivityState - nodebInfo: %s", nodebInfo) + + err := w.retry("UpdateNodebConnectivityState", func() (err error) { + err = w.rnibWriter.UpdateNodebConnectivityState(nodebInfo, w.stateChangeMessageChannel, event) + return + }) + + return err +} + func (w *rNibDataService) retry(rnibFunc string, f func() error) (err error) { attempts := w.maxAttempts diff --git a/E2Manager/services/rnib_data_service_test.go b/E2Manager/services/rnib_data_service_test.go index ab67a32..1d59846 100644 --- a/E2Manager/services/rnib_data_service_test.go +++ b/E2Manager/services/rnib_data_service_test.go @@ -33,6 +33,8 @@ import ( "testing" ) +const CHANNEL_NAME = "channel" + func setupRnibDataServiceTest(t *testing.T) (*rNibDataService, *mocks.RnibReaderMock, *mocks.RnibWriterMock) { return setupRnibDataServiceTestWithMaxAttempts(t, 3) } @@ -43,7 +45,7 @@ func setupRnibDataServiceTestWithMaxAttempts(t *testing.T, maxAttempts int) (*rN t.Errorf("#... - failed to initialize logger, error: %s", err) } - config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: maxAttempts} + config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: maxAttempts, StateChangeMessageChannel: CHANNEL_NAME} readerMock := &mocks.RnibReaderMock{} @@ -257,6 +259,29 @@ func TestPingRnibOkOtherError(t *testing.T) { assert.True(t, res) } +func TestSuccessfulUpdateNodebConnectivityState(t *testing.T) { + rnibDataService, _, writerMock := setupRnibDataServiceTest(t) + event := "event" + + nodebInfo := &entities.NodebInfo{} + writerMock.On("UpdateNodebConnectivityState", nodebInfo, CHANNEL_NAME, event).Return(nil) + + rnibDataService.UpdateNodebConnectivityState(nodebInfo, event) + writerMock.AssertNumberOfCalls(t, "UpdateNodebConnectivityState", 1) +} + +func TestConnFailureUpdateNodebConnectivityState(t *testing.T) { + rnibDataService, _, writerMock := setupRnibDataServiceTest(t) + event := "event" + + nodebInfo := &entities.NodebInfo{} + mockErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}} + writerMock.On("UpdateNodebConnectivityState", nodebInfo, CHANNEL_NAME, event).Return(mockErr) + + rnibDataService.UpdateNodebConnectivityState(nodebInfo, event) + writerMock.AssertNumberOfCalls(t, "UpdateNodebConnectivityState", 3) +} + //func TestConnFailureThenSuccessGetNodebIdList(t *testing.T) { // rnibDataService, readerMock, _ := setupRnibDataServiceTest(t) //