[RIC-397] Add RanConnectStatusChangeManager + support SetAnsPublish 93/4093/1
authorAmichai <amichai.sichel@intl.att.com>
Sun, 14 Jun 2020 14:12:15 +0000 (17:12 +0300)
committerAmichai <amichai.sichel@intl.att.com>
Sun, 14 Jun 2020 14:22:41 +0000 (17:22 +0300)
Change-Id: Ic1bb1662b273074d8dbdff20eecaaaeaf3081835
Signed-off-by: Amichai <amichai.sichel@intl.att.com>
15 files changed:
E2Manager/configuration/configuration.go
E2Manager/configuration/configuration_test.go
E2Manager/go.sum
E2Manager/managers/ran_connect_status_change_manager.go [new file with mode: 0644]
E2Manager/managers/ran_connect_status_change_manager_test.go [new file with mode: 0644]
E2Manager/managers/ran_list_manager.go [new file with mode: 0644]
E2Manager/mocks/ran_alarm_service_mock.go [new file with mode: 0644]
E2Manager/mocks/ran_list_manager_mock.go [new file with mode: 0644]
E2Manager/mocks/rnibWriterMock.go
E2Manager/rNibWriter/rNibWriter.go
E2Manager/rNibWriter/rNibWriter_test.go
E2Manager/resources/configuration.yaml
E2Manager/services/ran_alarm_service.go [new file with mode: 0644]
E2Manager/services/rnib_data_service.go
E2Manager/services/rnib_data_service_test.go

index 791360a..f539c5d 100644 (file)
@@ -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,
        )
 }
index 4a3dff3..27fd1b4 100644 (file)
@@ -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) {
index dd2ffa7..5756914 100644 (file)
@@ -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 (file)
index 0000000..8818399
--- /dev/null
@@ -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 (file)
index 0000000..4dc77af
--- /dev/null
@@ -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 (file)
index 0000000..9ad10f2
--- /dev/null
@@ -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 (file)
index 0000000..ed18c88
--- /dev/null
@@ -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 (file)
index 0000000..6df5c4f
--- /dev/null
@@ -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
index 5c602bb..bf2ed53 100644 (file)
@@ -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
index a44f388..5bc4a68 100644 (file)
@@ -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
 */
index dc5450b..b77e97e 100644 (file)
@@ -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){
index fc77022..6beba8f 100644 (file)
@@ -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 (file)
index 0000000..046b183
--- /dev/null
@@ -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
+}
index 1edfa7c..3ca944a 100644 (file)
@@ -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
 
index ab67a32..1d59846 100644 (file)
@@ -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)
 //