First commit
This commit is contained in:
134
setup/e2mgr/E2Manager/managers/e2t_association_manager.go
Normal file
134
setup/e2mgr/E2Manager/managers/e2t_association_manager.go
Normal file
@@ -0,0 +1,134 @@
|
||||
//
|
||||
// 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/clients"
|
||||
"e2mgr/e2managererrors"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/services"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
)
|
||||
|
||||
type E2TAssociationManager struct {
|
||||
logger *logger.Logger
|
||||
rnibDataService services.RNibDataService
|
||||
e2tInstanceManager IE2TInstancesManager
|
||||
rmClient clients.IRoutingManagerClient
|
||||
}
|
||||
|
||||
func NewE2TAssociationManager(logger *logger.Logger, rnibDataService services.RNibDataService, e2tInstanceManager IE2TInstancesManager, rmClient clients.IRoutingManagerClient) *E2TAssociationManager {
|
||||
return &E2TAssociationManager{
|
||||
logger: logger,
|
||||
rnibDataService: rnibDataService,
|
||||
e2tInstanceManager: e2tInstanceManager,
|
||||
rmClient: rmClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *E2TAssociationManager) AssociateRan(e2tAddress string, nodebInfo *entities.NodebInfo) error {
|
||||
ranName := nodebInfo.RanName
|
||||
m.logger.Infof("#E2TAssociationManager.AssociateRan - Associating RAN %s to E2T Instance address: %s", ranName, e2tAddress)
|
||||
|
||||
err := m.associateRanAndUpdateNodeb(e2tAddress, nodebInfo)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TAssociationManager.AssociateRan - RoutingManager failure: Failed to associate RAN %s to E2T %s. Error: %s", nodebInfo, e2tAddress, err)
|
||||
return err
|
||||
}
|
||||
err = m.e2tInstanceManager.AddRansToInstance(e2tAddress, []string{ranName})
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TAssociationManager.AssociateRan - RAN name: %s - Failed to add RAN to E2T instance %s. Error: %s", ranName, e2tAddress, err)
|
||||
return e2managererrors.NewRnibDbError()
|
||||
}
|
||||
m.logger.Infof("#E2TAssociationManager.AssociateRan - successfully associated RAN %s with E2T %s", ranName, e2tAddress)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *E2TAssociationManager) associateRanAndUpdateNodeb(e2tAddress string, nodebInfo *entities.NodebInfo) error {
|
||||
|
||||
rmErr := m.rmClient.AssociateRanToE2TInstance(e2tAddress, nodebInfo.RanName)
|
||||
if rmErr != nil {
|
||||
nodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
} else {
|
||||
nodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED
|
||||
nodebInfo.AssociatedE2TInstanceAddress = e2tAddress
|
||||
}
|
||||
rNibErr := m.rnibDataService.UpdateNodebInfo(nodebInfo)
|
||||
if rNibErr != nil {
|
||||
m.logger.Errorf("#E2TAssociationManager.associateRanAndUpdateNodeb - RAN name: %s - Failed to update nodeb entity in rNib. Error: %s", nodebInfo.RanName, rNibErr)
|
||||
}
|
||||
var err error
|
||||
if rmErr != nil {
|
||||
err = e2managererrors.NewRoutingManagerError()
|
||||
} else if rNibErr != nil{
|
||||
err = e2managererrors.NewRnibDbError()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *E2TAssociationManager) DissociateRan(e2tAddress string, ranName string) error {
|
||||
m.logger.Infof("#E2TAssociationManager.DissociateRan - Dissociating RAN %s from E2T Instance address: %s", ranName, e2tAddress)
|
||||
|
||||
nodebInfo, rnibErr := m.rnibDataService.GetNodeb(ranName)
|
||||
if rnibErr != nil {
|
||||
m.logger.Errorf("#E2TAssociationManager.DissociateRan - RAN name: %s - Failed fetching RAN from rNib. Error: %s", ranName, rnibErr)
|
||||
return rnibErr
|
||||
}
|
||||
|
||||
nodebInfo.AssociatedE2TInstanceAddress = ""
|
||||
rnibErr = m.rnibDataService.UpdateNodebInfo(nodebInfo)
|
||||
if rnibErr != nil {
|
||||
m.logger.Errorf("#E2TAssociationManager.DissociateRan - RAN name: %s - Failed to update RAN.AssociatedE2TInstanceAddress in rNib. Error: %s", ranName, rnibErr)
|
||||
return rnibErr
|
||||
}
|
||||
|
||||
err := m.e2tInstanceManager.RemoveRanFromInstance(ranName, e2tAddress)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TAssociationManager.DissociateRan - RAN name: %s - Failed to remove RAN from E2T instance %s. Error: %s", ranName, e2tAddress, err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.rmClient.DissociateRanE2TInstance(e2tAddress, ranName)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TAssociationManager.DissociateRan - RoutingManager failure: Failed to dissociate RAN %s from E2T %s. Error: %s", ranName, e2tAddress, err)
|
||||
} else {
|
||||
m.logger.Infof("#E2TAssociationManager.DissociateRan - successfully dissociated RAN %s from E2T %s", ranName, e2tAddress)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *E2TAssociationManager) RemoveE2tInstance(e2tInstance *entities.E2TInstance) error {
|
||||
m.logger.Infof("#E2TAssociationManager.RemoveE2tInstance - Removing E2T %s and dessociating its associated RANs.", e2tInstance.Address)
|
||||
|
||||
err := m.rmClient.DeleteE2TInstance(e2tInstance.Address, e2tInstance.AssociatedRanList)
|
||||
if err != nil {
|
||||
m.logger.Warnf("#E2TAssociationManager.RemoveE2tInstance - RoutingManager failure: Failed to delete E2T %s. Error: %s", e2tInstance.Address, err)
|
||||
// log and continue
|
||||
}
|
||||
|
||||
err = m.e2tInstanceManager.RemoveE2TInstance(e2tInstance.Address)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TAssociationManager.RemoveE2tInstance - Failed to remove E2T %s. Error: %s", e2tInstance.Address, err)
|
||||
return err
|
||||
}
|
||||
|
||||
m.logger.Infof("#E2TAssociationManager.RemoveE2tInstance - E2T %s successfully removed.", e2tInstance.Address)
|
||||
return nil
|
||||
}
|
383
setup/e2mgr/E2Manager/managers/e2t_association_manager_test.go
Normal file
383
setup/e2mgr/E2Manager/managers/e2t_association_manager_test.go
Normal file
@@ -0,0 +1,383 @@
|
||||
//
|
||||
// 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 (
|
||||
"bytes"
|
||||
"e2mgr/clients"
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/e2managererrors"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/models"
|
||||
"e2mgr/services"
|
||||
"encoding/json"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const RanName = "test"
|
||||
|
||||
func initE2TAssociationManagerTest(t *testing.T) (*E2TAssociationManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
|
||||
log := initLog(t)
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
|
||||
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
|
||||
|
||||
e2tInstancesManager := NewE2TInstancesManager(rnibDataService, log)
|
||||
httpClientMock := &mocks.HttpClientMock{}
|
||||
rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
|
||||
manager := NewE2TAssociationManager(log, rnibDataService, e2tInstancesManager, rmClient)
|
||||
|
||||
return manager, readerMock, writerMock, httpClientMock
|
||||
}
|
||||
|
||||
func mockHttpClient(httpClientMock *mocks.HttpClientMock, apiSuffix string, isSuccessful bool) {
|
||||
data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)}
|
||||
marshaled, _ := json.Marshal(data)
|
||||
body := bytes.NewBuffer(marshaled)
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
var respStatusCode int
|
||||
if isSuccessful {
|
||||
respStatusCode = http.StatusCreated
|
||||
} else {
|
||||
respStatusCode = http.StatusBadRequest
|
||||
}
|
||||
httpClientMock.On("Post", apiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
|
||||
}
|
||||
|
||||
func TestAssociateRanSuccess(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
|
||||
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
|
||||
updatedNb := *nb
|
||||
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
|
||||
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
|
||||
e2tInstance := &entities.E2TInstance{Address: E2TAddress}
|
||||
readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
|
||||
updatedE2tInstance := *e2tInstance
|
||||
updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName)
|
||||
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
|
||||
|
||||
err := manager.AssociateRan(E2TAddress, nb)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestAssociateRanRoutingManagerError(t *testing.T) {
|
||||
manager, _, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, false)
|
||||
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
|
||||
writerMock.On("UpdateNodebInfo", nb).Return(nil)
|
||||
|
||||
err := manager.AssociateRan(E2TAddress, nb)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, &e2managererrors.RoutingManagerError{}, err)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestAssociateRanUpdateNodebError(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
|
||||
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
|
||||
updatedNb := *nb
|
||||
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
|
||||
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &updatedNb).Return(e2managererrors.NewRnibDbError())
|
||||
|
||||
err := manager.AssociateRan(E2TAddress, nb)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestAssociateRanGetE2tInstanceError(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
|
||||
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
|
||||
updatedNb := *nb
|
||||
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
|
||||
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
|
||||
var e2tInstance *entities.E2TInstance
|
||||
readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test"))
|
||||
|
||||
err := manager.AssociateRan(E2TAddress, nb)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestAssociateRanSaveE2tInstanceError(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
|
||||
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
|
||||
updatedNb := *nb
|
||||
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
|
||||
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
|
||||
e2tInstance := &entities.E2TInstance{Address: E2TAddress}
|
||||
readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
|
||||
updatedE2tInstance := *e2tInstance
|
||||
updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName)
|
||||
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test"))
|
||||
|
||||
err := manager.AssociateRan(E2TAddress, nb)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestDissociateRanSuccess(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, true)
|
||||
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, nil)
|
||||
updatedNb := *nb
|
||||
updatedNb.AssociatedE2TInstanceAddress = ""
|
||||
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
|
||||
e2tInstance := &entities.E2TInstance{Address: E2TAddress}
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
|
||||
readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
|
||||
updatedE2tInstance := *e2tInstance
|
||||
updatedE2tInstance.AssociatedRanList = []string{}
|
||||
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
|
||||
|
||||
err := manager.DissociateRan(E2TAddress, RanName)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestDissociateRanGetNodebError(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
var nb *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, e2managererrors.NewRnibDbError())
|
||||
|
||||
err := manager.DissociateRan(E2TAddress, RanName)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestDissociateRanUpdateNodebError(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, nil)
|
||||
updatedNb := *nb
|
||||
updatedNb.AssociatedE2TInstanceAddress = ""
|
||||
writerMock.On("UpdateNodebInfo", &updatedNb).Return(e2managererrors.NewRnibDbError())
|
||||
|
||||
err := manager.DissociateRan(E2TAddress, RanName)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestDissociateRanGetE2tInstanceError(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, nil)
|
||||
updatedNb := *nb
|
||||
updatedNb.AssociatedE2TInstanceAddress = ""
|
||||
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
|
||||
var e2tInstance *entities.E2TInstance
|
||||
readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test"))
|
||||
|
||||
err := manager.DissociateRan(E2TAddress, RanName)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestDissociateRanSaveE2tInstanceError(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, nil)
|
||||
updatedNb := *nb
|
||||
updatedNb.AssociatedE2TInstanceAddress = ""
|
||||
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
|
||||
e2tInstance := &entities.E2TInstance{Address: E2TAddress}
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
|
||||
readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
|
||||
updatedE2tInstance := *e2tInstance
|
||||
updatedE2tInstance.AssociatedRanList = []string{}
|
||||
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test"))
|
||||
|
||||
err := manager.DissociateRan(E2TAddress, RanName)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestDissociateRanRoutingManagerError(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, false)
|
||||
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, nil)
|
||||
updatedNb := *nb
|
||||
updatedNb.AssociatedE2TInstanceAddress = ""
|
||||
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
|
||||
e2tInstance := &entities.E2TInstance{Address: E2TAddress}
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
|
||||
readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
|
||||
updatedE2tInstance := *e2tInstance
|
||||
updatedE2tInstance.AssociatedRanList = []string{}
|
||||
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
|
||||
|
||||
err := manager.DissociateRan(E2TAddress, RanName)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestRemoveE2tInstanceSuccessWithOrphans(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
|
||||
ranNamesToBeDissociated := []string{RanName, "test1"}
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, ranNamesToBeDissociated, nil)
|
||||
mockHttpClientDelete(httpClientMock, data, true)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
e2tAddresses := []string{E2TAddress}
|
||||
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
|
||||
e2tAddressesNew := []string{}
|
||||
writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
|
||||
|
||||
e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:ranNamesToBeDissociated}
|
||||
err := manager.RemoveE2tInstance(e2tInstance1)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestRemoveE2tInstanceFailureRoutingManager(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
|
||||
mockHttpClientDelete(httpClientMock, data, false)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
e2tAddresses := []string{E2TAddress}
|
||||
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
|
||||
e2tAddressesNew := []string{}
|
||||
writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
|
||||
|
||||
e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:[]string{"test1"}}
|
||||
//readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewRnibDbError())
|
||||
err := manager.RemoveE2tInstance(e2tInstance1)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestRemoveE2tInstanceFailureInE2TInstanceManager(t *testing.T) {
|
||||
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
mockHttpClientDelete(httpClientMock, data, true)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
var e2tAddresses []string
|
||||
readerMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError())
|
||||
|
||||
e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:[]string{"test1"}}
|
||||
err := manager.RemoveE2tInstance(e2tInstance1)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestRemoveE2tInstanceFailureInE2tInstanceAddRansToInstance(t *testing.T) {
|
||||
manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
|
||||
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, nil)
|
||||
mockHttpClientDelete(httpClientMock, data, true)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
e2tAddresses := []string{E2TAddress, E2TAddress2, E2TAddress3}
|
||||
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
|
||||
e2tAddressesNew := []string{E2TAddress2, E2TAddress3}
|
||||
writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
|
||||
|
||||
e2tInstance1 := &entities.E2TInstance{Address: E2TAddress}
|
||||
err := manager.RemoveE2tInstance(e2tInstance1)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func mockHttpClientDelete(httpClientMock *mocks.HttpClientMock, data *models.RoutingManagerDeleteRequestModel, isSuccessful bool) {
|
||||
|
||||
marshaled, _ := json.Marshal(data)
|
||||
body := bytes.NewBuffer(marshaled)
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
var respStatusCode int
|
||||
if isSuccessful {
|
||||
respStatusCode = http.StatusCreated
|
||||
} else {
|
||||
respStatusCode = http.StatusBadRequest
|
||||
}
|
||||
httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
|
||||
}
|
449
setup/e2mgr/E2Manager/managers/e2t_instances_manager.go
Normal file
449
setup/e2mgr/E2Manager/managers/e2t_instances_manager.go
Normal file
@@ -0,0 +1,449 @@
|
||||
//
|
||||
// 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/e2managererrors"
|
||||
"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"
|
||||
"math"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type E2TInstancesManager struct {
|
||||
rnibDataService services.RNibDataService
|
||||
logger *logger.Logger
|
||||
mux sync.Mutex
|
||||
}
|
||||
|
||||
type IE2TInstancesManager interface {
|
||||
GetE2TAddresses() ([]string, error)
|
||||
GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error)
|
||||
GetE2TInstances() ([]*entities.E2TInstance, error)
|
||||
GetE2TInstancesNoLogs() ([]*entities.E2TInstance, error)
|
||||
AddE2TInstance(e2tAddress string, podName string) error
|
||||
RemoveE2TInstance(e2tAddress string) error
|
||||
SelectE2TInstance() (string, error)
|
||||
AddRansToInstance(e2tAddress string, ranNames []string) error
|
||||
RemoveRanFromInstance(ranName string, e2tAddress string) error
|
||||
ResetKeepAliveTimestamp(e2tAddress string) error
|
||||
ClearRansOfAllE2TInstances() error
|
||||
SetE2tInstanceState(e2tAddress string, currentState entities.E2TInstanceState, newState entities.E2TInstanceState) error
|
||||
}
|
||||
|
||||
func NewE2TInstancesManager(rnibDataService services.RNibDataService, logger *logger.Logger) *E2TInstancesManager {
|
||||
return &E2TInstancesManager{
|
||||
rnibDataService: rnibDataService,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error) {
|
||||
e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress)
|
||||
|
||||
if err != nil {
|
||||
|
||||
_, ok := err.(*common.ResourceNotFoundError)
|
||||
|
||||
if !ok {
|
||||
m.logger.Errorf("#E2TInstancesManager.GetE2TInstance - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err)
|
||||
} else {
|
||||
m.logger.Infof("#E2TInstancesManager.GetE2TInstance - E2T Instance address: %s not found on DB", e2tAddress)
|
||||
}
|
||||
}
|
||||
|
||||
return e2tInstance, err
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) GetE2TInstancesNoLogs() ([]*entities.E2TInstance, error) {
|
||||
e2tAddresses, err := m.rnibDataService.GetE2TAddressesNoLogs()
|
||||
|
||||
if err != nil {
|
||||
_, ok := err.(*common.ResourceNotFoundError)
|
||||
|
||||
if !ok {
|
||||
m.logger.Errorf("#E2TInstancesManager.GetE2TInstancesNoLogs - Failed retrieving E2T addresses. error: %s", err)
|
||||
return nil, e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
return []*entities.E2TInstance{}, nil
|
||||
}
|
||||
|
||||
if len(e2tAddresses) == 0 {
|
||||
return []*entities.E2TInstance{}, nil
|
||||
}
|
||||
|
||||
e2tInstances, err := m.rnibDataService.GetE2TInstancesNoLogs(e2tAddresses)
|
||||
|
||||
if err != nil {
|
||||
_, ok := err.(*common.ResourceNotFoundError)
|
||||
|
||||
if !ok {
|
||||
m.logger.Errorf("#E2TInstancesManager.GetE2TInstancesNoLogs - Failed retrieving E2T instances list. error: %s", err)
|
||||
}
|
||||
return e2tInstances, err
|
||||
}
|
||||
|
||||
return e2tInstances, nil
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) GetE2TAddresses() ([]string, error) {
|
||||
e2tAddresses, err := m.rnibDataService.GetE2TAddresses()
|
||||
|
||||
if err != nil {
|
||||
|
||||
_, ok := err.(*common.ResourceNotFoundError)
|
||||
|
||||
if !ok {
|
||||
m.logger.Errorf("#E2TInstancesManager.GetE2TAddresses - Failed retrieving E2T addresses. error: %s", err)
|
||||
return nil, e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return e2tAddresses, nil
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) GetE2TInstances() ([]*entities.E2TInstance, error) {
|
||||
e2tAddresses, err := m.GetE2TAddresses()
|
||||
|
||||
if err != nil {
|
||||
return nil, e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
if len(e2tAddresses) == 0 {
|
||||
m.logger.Infof("#E2TInstancesManager.GetE2TInstances - Empty E2T addresses list")
|
||||
return []*entities.E2TInstance{}, nil
|
||||
}
|
||||
|
||||
e2tInstances, err := m.rnibDataService.GetE2TInstances(e2tAddresses)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.GetE2TInstances - Failed retrieving E2T instances list. error: %s", err)
|
||||
return e2tInstances, e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
if len(e2tInstances) == 0 {
|
||||
m.logger.Warnf("#E2TInstancesManager.GetE2TInstances - Empty E2T instances list")
|
||||
return e2tInstances, nil
|
||||
}
|
||||
|
||||
return e2tInstances, nil
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) ResetKeepAliveTimestampsForAllE2TInstances() {
|
||||
|
||||
e2tInstances, err := m.GetE2TInstances()
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - Couldn't reset timestamps due to a DB error")
|
||||
return
|
||||
}
|
||||
|
||||
if len(e2tInstances) == 0 {
|
||||
m.logger.Infof("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - No instances, ignoring reset")
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range e2tInstances {
|
||||
|
||||
if v.State != entities.Active {
|
||||
continue
|
||||
}
|
||||
|
||||
v.KeepAliveTimestamp = time.Now().UnixNano()
|
||||
|
||||
err := m.rnibDataService.SaveE2TInstance(v)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - E2T address: %s - failed resetting e2t instance keep alive timestamp. error: %s", v.Address, err)
|
||||
}
|
||||
}
|
||||
|
||||
m.logger.Infof("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - Done with reset")
|
||||
}
|
||||
|
||||
func findActiveE2TInstanceWithMinimumAssociatedRans(e2tInstances []*entities.E2TInstance) *entities.E2TInstance {
|
||||
var minInstance *entities.E2TInstance
|
||||
minAssociatedRanCount := math.MaxInt32
|
||||
|
||||
for _, v := range e2tInstances {
|
||||
if v.State == entities.Active && len(v.AssociatedRanList) < minAssociatedRanCount {
|
||||
minAssociatedRanCount = len(v.AssociatedRanList)
|
||||
minInstance = v
|
||||
}
|
||||
}
|
||||
|
||||
return minInstance
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) AddE2TInstance(e2tAddress string, podName string) error {
|
||||
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(e2tAddress, podName)
|
||||
err := m.rnibDataService.SaveE2TInstance(e2tInstance)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - Failed saving E2T instance. error: %s", e2tInstance.Address, err)
|
||||
return err
|
||||
}
|
||||
|
||||
e2tAddresses, err := m.rnibDataService.GetE2TAddresses()
|
||||
|
||||
if err != nil {
|
||||
|
||||
_, ok := err.(*common.ResourceNotFoundError)
|
||||
|
||||
if !ok {
|
||||
m.logger.Errorf("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - Failed retrieving E2T addresses list. error: %s", e2tInstance.Address, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
e2tAddresses = append(e2tAddresses, e2tInstance.Address)
|
||||
|
||||
err = m.rnibDataService.SaveE2TAddresses(e2tAddresses)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - Failed saving E2T addresses list. error: %s", e2tInstance.Address, err)
|
||||
return err
|
||||
}
|
||||
|
||||
m.logger.Infof("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s, pod name: %s - successfully added E2T instance", e2tInstance.Address, e2tInstance.PodName)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) RemoveRanFromInstance(ranName string, e2tAddress string) error {
|
||||
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
|
||||
e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.RemoveRanFromInstance - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err)
|
||||
return e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
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("#E2TInstancesManager.RemoveRanFromInstance - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err)
|
||||
return e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
m.logger.Infof("#E2TInstancesManager.RemoveRanFromInstance - successfully dissociated RAN %s from E2T %s", ranName, e2tInstance.Address)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) RemoveE2TInstance(e2tAddress string) error {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
|
||||
err := m.rnibDataService.RemoveE2TInstance(e2tAddress)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed removing E2TInstance. error: %s", e2tAddress, err)
|
||||
return e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
e2tAddresses, err := m.rnibDataService.GetE2TAddresses()
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed retrieving E2T addresses list. error: %s", e2tAddress, err)
|
||||
return e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
e2tAddresses = m.removeAddressFromList(e2tAddresses, e2tAddress)
|
||||
|
||||
err = m.rnibDataService.SaveE2TAddresses(e2tAddresses)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed saving E2T addresses list. error: %s", e2tAddress, err)
|
||||
return e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) removeAddressFromList(e2tAddresses []string, addressToRemove string) []string {
|
||||
newAddressList := []string{}
|
||||
|
||||
for _, address := range e2tAddresses {
|
||||
if address != addressToRemove {
|
||||
newAddressList = append(newAddressList, address)
|
||||
}
|
||||
}
|
||||
|
||||
return newAddressList
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) SelectE2TInstance() (string, error) {
|
||||
|
||||
e2tInstances, err := m.GetE2TInstances()
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(e2tInstances) == 0 {
|
||||
m.logger.Errorf("#E2TInstancesManager.SelectE2TInstance - No E2T instance found")
|
||||
return "", e2managererrors.NewE2TInstanceAbsenceError()
|
||||
}
|
||||
|
||||
min := findActiveE2TInstanceWithMinimumAssociatedRans(e2tInstances)
|
||||
|
||||
if min == nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.SelectE2TInstance - No active E2T instance found")
|
||||
return "", e2managererrors.NewE2TInstanceAbsenceError()
|
||||
}
|
||||
|
||||
m.logger.Infof("#E2TInstancesManager.SelectE2TInstance - successfully selected E2T instance. address: %s", min.Address)
|
||||
return min.Address, nil
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) AddRansToInstance(e2tAddress string, ranNames []string) error {
|
||||
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
|
||||
e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.AddRansToInstance - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err)
|
||||
return e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, ranNames...)
|
||||
|
||||
err = m.rnibDataService.SaveE2TInstance(e2tInstance)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.AddRansToInstance - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err)
|
||||
return e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
m.logger.Infof("#E2TInstancesManager.AddRansToInstance - RAN %s were added successfully to E2T %s", ranNames, e2tInstance.Address)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) ResetKeepAliveTimestamp(e2tAddress string) error {
|
||||
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
|
||||
e2tInstance, err := m.rnibDataService.GetE2TInstanceNoLogs(e2tAddress)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.ResetKeepAliveTimestamp - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err)
|
||||
return err
|
||||
}
|
||||
|
||||
if e2tInstance.State == entities.ToBeDeleted {
|
||||
m.logger.Warnf("#E2TInstancesManager.ResetKeepAliveTimestamp - Ignore. This Instance is about to be deleted")
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
e2tInstance.KeepAliveTimestamp = time.Now().UnixNano()
|
||||
err = m.rnibDataService.SaveE2TInstanceNoLogs(e2tInstance)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.ResetKeepAliveTimestamp - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) SetE2tInstanceState(e2tAddress string, currentState entities.E2TInstanceState, newState entities.E2TInstanceState) error {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
|
||||
e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err)
|
||||
return e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
if (currentState != e2tInstance.State) {
|
||||
m.logger.Warnf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Current state is not: %s", e2tAddress, currentState)
|
||||
return e2managererrors.NewInternalError()
|
||||
}
|
||||
|
||||
e2tInstance.State = newState
|
||||
if (newState == entities.Active) {
|
||||
e2tInstance.KeepAliveTimestamp = time.Now().UnixNano()
|
||||
}
|
||||
|
||||
err = m.rnibDataService.SaveE2TInstance(e2tInstance)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tInstance.Address, err)
|
||||
return err
|
||||
}
|
||||
|
||||
m.logger.Infof("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - State change: %s --> %s", e2tAddress, currentState, newState)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *E2TInstancesManager) ClearRansOfAllE2TInstances() error {
|
||||
m.logger.Infof("#E2TInstancesManager.ClearRansOfAllE2TInstances - Going to clear associated RANs from E2T instances")
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
|
||||
e2tInstances, err := m.GetE2TInstances()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(e2tInstances) == 0 {
|
||||
m.logger.Errorf("#E2TInstancesManager.ClearRansOfAllE2TInstances - No E2T instances to clear associated RANs from")
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, v := range e2tInstances {
|
||||
v.AssociatedRanList = []string{}
|
||||
err := m.rnibDataService.SaveE2TInstance(v)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TInstancesManager.ClearRansOfAllE2TInstances - e2t address: %s - failed saving e2t instance. error: %s", v.Address, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
553
setup/e2mgr/E2Manager/managers/e2t_instances_manager_test.go
Normal file
553
setup/e2mgr/E2Manager/managers/e2t_instances_manager_test.go
Normal file
@@ -0,0 +1,553 @@
|
||||
//
|
||||
// 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/e2managererrors"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/services"
|
||||
"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/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const E2TAddress = "10.10.2.15:9800"
|
||||
const E2TAddress2 = "10.10.2.16:9800"
|
||||
const PodName = "som_ pod_name"
|
||||
|
||||
func initE2TInstancesManagerTest(t *testing.T) (*mocks.RnibReaderMock, *mocks.RnibWriterMock, *E2TInstancesManager) {
|
||||
logger, err := logger.InitLogger(logger.DebugLevel)
|
||||
if err != nil {
|
||||
t.Errorf("#... - failed to initialize logger, error: %s", err)
|
||||
}
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
|
||||
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
e2tInstancesManager := NewE2TInstancesManager(rnibDataService, logger)
|
||||
return readerMock, writerMock, e2tInstancesManager
|
||||
}
|
||||
|
||||
func TestAddNewE2TInstanceSaveE2TInstanceFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error")))
|
||||
err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
|
||||
assert.NotNil(t, err)
|
||||
rnibReaderMock.AssertNotCalled(t, "GetE2TAddresses")
|
||||
}
|
||||
|
||||
func TestAddNewE2TInstanceGetE2TAddressesInternalFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
e2tAddresses := []string{}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, common.NewInternalError(errors.New("Error")))
|
||||
err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
|
||||
assert.NotNil(t, err)
|
||||
rnibReaderMock.AssertNotCalled(t, "SaveE2TAddresses")
|
||||
}
|
||||
|
||||
func TestAddNewE2TInstanceSaveE2TAddressesFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
E2TAddresses := []string{}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(E2TAddresses, nil)
|
||||
E2TAddresses = append(E2TAddresses, E2TAddress)
|
||||
rnibWriterMock.On("SaveE2TAddresses", E2TAddresses).Return(common.NewResourceNotFoundError(""))
|
||||
err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestAddNewE2TInstanceNoE2TAddressesSuccess(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
e2tAddresses := []string{}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, common.NewResourceNotFoundError(""))
|
||||
e2tAddresses = append(e2tAddresses, E2TAddress)
|
||||
rnibWriterMock.On("SaveE2TAddresses", e2tAddresses).Return(nil)
|
||||
err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
|
||||
assert.Nil(t, err)
|
||||
rnibWriterMock.AssertCalled(t, "SaveE2TAddresses", e2tAddresses)
|
||||
}
|
||||
|
||||
func TestAddNewE2TInstanceEmptyE2TAddressesSuccess(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
e2tAddresses := []string{}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
|
||||
e2tAddresses = append(e2tAddresses, E2TAddress)
|
||||
rnibWriterMock.On("SaveE2TAddresses", e2tAddresses).Return(nil)
|
||||
err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
|
||||
assert.Nil(t, err)
|
||||
rnibWriterMock.AssertCalled(t, "SaveE2TAddresses", e2tAddresses)
|
||||
}
|
||||
|
||||
func TestAddNewE2TInstanceExistingE2TAddressesSuccess(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
E2TAddresses := []string{"10.0.1.15:3030"}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(E2TAddresses, nil)
|
||||
E2TAddresses = append(E2TAddresses, E2TAddress)
|
||||
rnibWriterMock.On("SaveE2TAddresses", E2TAddresses).Return(nil)
|
||||
err := e2tInstancesManager.AddE2TInstance(E2TAddress, PodName)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestGetE2TInstanceFailure(t *testing.T) {
|
||||
rnibReaderMock, _, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
var e2tInstance *entities.E2TInstance
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, common.NewInternalError(fmt.Errorf("for test")))
|
||||
res, err := e2tInstancesManager.GetE2TInstance(E2TAddress)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, res)
|
||||
}
|
||||
|
||||
func TestGetE2TInstanceSuccess(t *testing.T) {
|
||||
rnibReaderMock, _, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
address := "10.10.2.15:9800"
|
||||
e2tInstance := entities.NewE2TInstance(address, PodName)
|
||||
rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
|
||||
res, err := e2tInstancesManager.GetE2TInstance(address)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, e2tInstance, res)
|
||||
}
|
||||
|
||||
func TestAddRanToInstanceGetInstanceFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
var e2tInstance1 *entities.E2TInstance
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, common.NewInternalError(fmt.Errorf("for test")))
|
||||
|
||||
err := e2tInstancesManager.AddRansToInstance(E2TAddress, []string{"test1"})
|
||||
assert.NotNil(t, err)
|
||||
rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
|
||||
}
|
||||
|
||||
func TestAddRanToInstanceSaveInstanceFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(fmt.Errorf("for test")))
|
||||
|
||||
err := e2tInstancesManager.AddRansToInstance(E2TAddress, []string{"test1"})
|
||||
assert.NotNil(t, err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestAddRanToInstanceSuccess(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
e2tInstance := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
|
||||
|
||||
updateE2TInstance := *e2tInstance
|
||||
updateE2TInstance.AssociatedRanList = append(updateE2TInstance.AssociatedRanList, "test1")
|
||||
|
||||
rnibWriterMock.On("SaveE2TInstance", &updateE2TInstance).Return(nil)
|
||||
|
||||
err := e2tInstancesManager.AddRansToInstance(E2TAddress, []string{"test1"})
|
||||
assert.Nil(t, err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestRemoveRanFromInstanceGetInstanceFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
var e2tInstance1 *entities.E2TInstance
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, common.NewInternalError(fmt.Errorf("for test")))
|
||||
err := e2tInstancesManager.RemoveRanFromInstance("test1", E2TAddress)
|
||||
assert.NotNil(t, err)
|
||||
rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
|
||||
}
|
||||
|
||||
func TestRemoveRanFromInstanceSaveInstanceFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(fmt.Errorf("for test")))
|
||||
|
||||
err := e2tInstancesManager.RemoveRanFromInstance("test1", E2TAddress)
|
||||
assert.NotNil(t, err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestRemoveRanFromInstanceSuccess(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance.AssociatedRanList = []string{"test0", "test1"}
|
||||
updatedE2TInstance := *e2tInstance
|
||||
updatedE2TInstance.AssociatedRanList = []string{"test0"}
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
|
||||
rnibWriterMock.On("SaveE2TInstance", &updatedE2TInstance).Return(nil)
|
||||
|
||||
err := e2tInstancesManager.RemoveRanFromInstance("test1", E2TAddress)
|
||||
assert.Nil(t, err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestSelectE2TInstancesGetE2TAddressesFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
rnibReaderMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(fmt.Errorf("for test")))
|
||||
address, err := e2tInstancesManager.SelectE2TInstance()
|
||||
assert.NotNil(t, err)
|
||||
assert.Empty(t, address)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertNotCalled(t, "GetE2TInstances")
|
||||
}
|
||||
|
||||
func TestSelectE2TInstancesEmptyE2TAddressList(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
rnibReaderMock.On("GetE2TAddresses").Return([]string{}, nil)
|
||||
address, err := e2tInstancesManager.SelectE2TInstance()
|
||||
assert.NotNil(t, err)
|
||||
assert.Empty(t, address)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertNotCalled(t, "GetE2TInstances")
|
||||
}
|
||||
|
||||
func TestSelectE2TInstancesGetE2TInstancesFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
addresses := []string{E2TAddress}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil)
|
||||
rnibReaderMock.On("GetE2TInstances", addresses).Return([]*entities.E2TInstance{}, common.NewInternalError(fmt.Errorf("for test")))
|
||||
address, err := e2tInstancesManager.SelectE2TInstance()
|
||||
assert.NotNil(t, err)
|
||||
assert.Empty(t, address)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestSelectE2TInstancesEmptyE2TInstancesList(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
addresses := []string{E2TAddress}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil)
|
||||
rnibReaderMock.On("GetE2TInstances", addresses).Return([]*entities.E2TInstance{}, nil)
|
||||
address, err := e2tInstancesManager.SelectE2TInstance()
|
||||
assert.NotNil(t, err)
|
||||
assert.Empty(t, address)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestSelectE2TInstancesNoActiveE2TInstance(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
addresses := []string{E2TAddress, E2TAddress2}
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.ToBeDeleted
|
||||
e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test3"}
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.State = entities.ToBeDeleted
|
||||
e2tInstance2.AssociatedRanList = []string{"test4", "test5", "test6", "test7"}
|
||||
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil)
|
||||
rnibReaderMock.On("GetE2TInstances", addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
|
||||
address, err := e2tInstancesManager.SelectE2TInstance()
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, "", address)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestSelectE2TInstancesSuccess(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
addresses := []string{E2TAddress, E2TAddress2}
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test3"}
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.AssociatedRanList = []string{"test4", "test5", "test6", "test7"}
|
||||
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil)
|
||||
rnibReaderMock.On("GetE2TInstances", addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
|
||||
address, err := e2tInstancesManager.SelectE2TInstance()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, E2TAddress, address)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestActivateE2TInstanceSuccess(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.ToBeDeleted
|
||||
e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, nil)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.State == entities.Active })).Return(nil)
|
||||
|
||||
err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.ToBeDeleted, entities.Active)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, entities.Active, e2tInstance1.State)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestActivateE2TInstance_RnibError(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
var e2tInstance1 *entities.E2TInstance
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, common.NewInternalError(errors.New("for test")))
|
||||
|
||||
err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.ToBeDeleted, entities.Active)
|
||||
assert.NotNil(t, err)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestActivateE2TInstance_NoInstance(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
var e2tInstance1 *entities.E2TInstance
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewResourceNotFoundError())
|
||||
|
||||
err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.ToBeDeleted, entities.Active)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
|
||||
}
|
||||
|
||||
func TestResetKeepAliveTimestampGetInternalFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
address := "10.10.2.15:9800"
|
||||
e2tInstance := entities.NewE2TInstance(address, PodName)
|
||||
rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, common.NewInternalError(errors.New("Error")))
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
|
||||
err := e2tInstancesManager.ResetKeepAliveTimestamp(address)
|
||||
assert.NotNil(t, err)
|
||||
rnibReaderMock.AssertNotCalled(t, "SaveE2TInstance")
|
||||
}
|
||||
|
||||
func TestAResetKeepAliveTimestampSaveInternalFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
address := "10.10.2.15:9800"
|
||||
e2tInstance := entities.NewE2TInstance(address, PodName)
|
||||
rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error")))
|
||||
|
||||
err := e2tInstancesManager.ResetKeepAliveTimestamp(address)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestResetKeepAliveTimestampSuccess(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
address := "10.10.2.15:9800"
|
||||
e2tInstance := entities.NewE2TInstance(address, PodName)
|
||||
rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
|
||||
err := e2tInstancesManager.ResetKeepAliveTimestamp(address)
|
||||
assert.Nil(t, err)
|
||||
rnibReaderMock.AssertCalled(t, "GetE2TInstance", address)
|
||||
rnibWriterMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1)
|
||||
}
|
||||
|
||||
func TestResetKeepAliveTimestampToBeDeleted(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
address := "10.10.2.15:9800"
|
||||
e2tInstance := entities.NewE2TInstance(address, PodName)
|
||||
e2tInstance.State = entities.ToBeDeleted
|
||||
rnibReaderMock.On("GetE2TInstance", address).Return(e2tInstance, nil)
|
||||
|
||||
err := e2tInstancesManager.ResetKeepAliveTimestamp(address)
|
||||
assert.Nil(t, err)
|
||||
rnibReaderMock.AssertCalled(t, "GetE2TInstance", address)
|
||||
rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
|
||||
}
|
||||
|
||||
func TestResetKeepAliveTimestampsForAllE2TInstancesGetE2TInstancesFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibReaderMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("Error")))
|
||||
e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
|
||||
rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
|
||||
}
|
||||
|
||||
func TestResetKeepAliveTimestampsForAllE2TInstancesNoInstances(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibReaderMock.On("GetE2TAddresses").Return([]string{}, nil)
|
||||
e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
|
||||
rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
|
||||
}
|
||||
|
||||
func TestResetKeepAliveTimestampsForAllE2TInstancesNoActiveInstances(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
e2tAddresses := []string{E2TAddress, E2TAddress2}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.ToBeDeleted
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.State = entities.ToBeDeleted
|
||||
rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
|
||||
e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
|
||||
rnibWriterMock.AssertNotCalled(t, "SaveE2TInstance")
|
||||
}
|
||||
|
||||
func TestResetKeepAliveTimestampsForAllE2TInstancesOneActiveInstance(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
e2tAddresses := []string{E2TAddress, E2TAddress2}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.State = entities.ToBeDeleted
|
||||
rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
|
||||
rnibWriterMock.AssertNumberOfCalls(t, "SaveE2TInstance",1)
|
||||
}
|
||||
|
||||
func TestResetKeepAliveTimestampsForAllE2TInstancesSaveE2TInstanceFailure(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
e2tAddresses := []string{E2TAddress, E2TAddress2}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.State = entities.ToBeDeleted
|
||||
rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(errors.New("Error")))
|
||||
e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances()
|
||||
rnibWriterMock.AssertNumberOfCalls(t, "SaveE2TInstance",1)
|
||||
}
|
||||
|
||||
func TestRemoveE2TInstanceSuccess(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
e2tAddresses := []string{E2TAddress, E2TAddress2}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
|
||||
e2tAddressesNew := []string{E2TAddress2}
|
||||
rnibWriterMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
|
||||
|
||||
err := e2tInstancesManager.RemoveE2TInstance(E2TAddress)
|
||||
assert.Nil(t, err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestRemoveE2TInstanceRnibErrorInRemoveInstance(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(e2managererrors.NewRnibDbError())
|
||||
|
||||
err := e2tInstancesManager.RemoveE2TInstance(E2TAddress)
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, e2managererrors.NewRnibDbError(), err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestRemoveE2TInstanceRnibErrorInGetAddresses(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
var e2tAddresses []string
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError())
|
||||
|
||||
err := e2tInstancesManager.RemoveE2TInstance(E2TAddress)
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, e2managererrors.NewRnibDbError(), err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestRemoveE2TInstanceRnibErrorInSaveAddresses(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
rnibWriterMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
e2tAddresses := []string{E2TAddress, E2TAddress2}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
|
||||
e2tAddressesNew := []string{E2TAddress2}
|
||||
rnibWriterMock.On("SaveE2TAddresses", e2tAddressesNew).Return(e2managererrors.NewRnibDbError())
|
||||
|
||||
err := e2tInstancesManager.RemoveE2TInstance(E2TAddress)
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, e2managererrors.NewRnibDbError(), err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestSetE2tInstanceStateCurrentStateHasChanged(t *testing.T) {
|
||||
rnibReaderMock, _, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance.State = entities.Active
|
||||
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
|
||||
|
||||
err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.ToBeDeleted, entities.Active)
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, e2managererrors.NewInternalError(), err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestSetE2tInstanceStateErrorInSaveE2TInstance(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance.State = entities.ToBeDeleted
|
||||
rnibReaderMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.Anything).Return(common.NewInternalError(fmt.Errorf("for testing")))
|
||||
|
||||
err := e2tInstancesManager.SetE2tInstanceState(E2TAddress, entities.ToBeDeleted, entities.Active)
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, &common.InternalError{}, err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestClearRansOfAllE2TInstancesEmptyList(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
E2TAddresses := []string{}
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(E2TAddresses, nil)
|
||||
err := e2tInstancesManager.ClearRansOfAllE2TInstances()
|
||||
assert.Nil(t, err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestClearRansOfAllE2TInstancesErrorInSaveE2TInstance(t *testing.T) {
|
||||
rnibReaderMock, rnibWriterMock, e2tInstancesManager := initE2TInstancesManagerTest(t)
|
||||
addresses := []string{E2TAddress, E2TAddress2}
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test3"}
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.AssociatedRanList = []string{"test4", "test5", "test6", "test7"}
|
||||
|
||||
rnibReaderMock.On("GetE2TAddresses").Return(addresses, nil)
|
||||
rnibReaderMock.On("GetE2TInstances", addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress})).Return(common.NewInternalError(fmt.Errorf("for testing")))
|
||||
rnibWriterMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress2})).Return(nil)
|
||||
err := e2tInstancesManager.ClearRansOfAllE2TInstances()
|
||||
assert.Nil(t, err)
|
||||
rnibReaderMock.AssertExpectations(t)
|
||||
rnibWriterMock.AssertExpectations(t)
|
||||
}
|
89
setup/e2mgr/E2Manager/managers/e2t_keep_alive_worker.go
Normal file
89
setup/e2mgr/E2Manager/managers/e2t_keep_alive_worker.go
Normal file
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// 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/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services/rmrsender"
|
||||
"time"
|
||||
)
|
||||
|
||||
type E2TKeepAliveWorker struct {
|
||||
logger *logger.Logger
|
||||
e2tShutdownManager IE2TShutdownManager
|
||||
e2TInstancesManager IE2TInstancesManager
|
||||
rmrSender *rmrsender.RmrSender
|
||||
config *configuration.Configuration
|
||||
}
|
||||
|
||||
func NewE2TKeepAliveWorker(logger *logger.Logger, rmrSender *rmrsender.RmrSender, e2TInstancesManager IE2TInstancesManager, e2tShutdownManager IE2TShutdownManager, config *configuration.Configuration) E2TKeepAliveWorker {
|
||||
return E2TKeepAliveWorker{
|
||||
logger: logger,
|
||||
e2tShutdownManager: e2tShutdownManager,
|
||||
e2TInstancesManager: e2TInstancesManager,
|
||||
rmrSender: rmrSender,
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
func (h E2TKeepAliveWorker) Execute() {
|
||||
|
||||
h.logger.Infof("#E2TKeepAliveWorker.Execute - keep alive started")
|
||||
|
||||
ticker := time.NewTicker(time.Duration(h.config.KeepAliveDelayMs) * time.Millisecond)
|
||||
|
||||
for _ = range ticker.C {
|
||||
|
||||
h.SendKeepAliveRequest()
|
||||
h.E2TKeepAliveExpired()
|
||||
}
|
||||
}
|
||||
|
||||
func (h E2TKeepAliveWorker) E2TKeepAliveExpired() {
|
||||
|
||||
e2tInstances, err := h.e2TInstancesManager.GetE2TInstancesNoLogs()
|
||||
|
||||
if err != nil || len(e2tInstances) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for _, e2tInstance := range e2tInstances {
|
||||
|
||||
delta := int64(time.Now().UnixNano()) - e2tInstance.KeepAliveTimestamp
|
||||
timestampNanosec := int64(time.Duration(h.config.KeepAliveResponseTimeoutMs) * time.Millisecond)
|
||||
|
||||
if delta > timestampNanosec {
|
||||
|
||||
h.logger.Warnf("#E2TKeepAliveWorker.E2TKeepAliveExpired - e2t address: %s time expired, shutdown e2 instance", e2tInstance.Address)
|
||||
|
||||
h.e2tShutdownManager.Shutdown(e2tInstance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h E2TKeepAliveWorker) SendKeepAliveRequest() {
|
||||
|
||||
rmrMessage := models.RmrMessage{MsgType: rmrCgo.E2_TERM_KEEP_ALIVE_REQ}
|
||||
h.rmrSender.SendWithoutLogs(&rmrMessage)
|
||||
}
|
205
setup/e2mgr/E2Manager/managers/e2t_keep_alive_worker_test.go
Normal file
205
setup/e2mgr/E2Manager/managers/e2t_keep_alive_worker_test.go
Normal file
@@ -0,0 +1,205 @@
|
||||
//
|
||||
// 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/rmrCgo"
|
||||
"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/mock"
|
||||
"testing"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func initE2TKeepAliveTest(t *testing.T) (*mocks.RmrMessengerMock, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.E2TShutdownManagerMock, *E2TKeepAliveWorker) {
|
||||
logger, err := logger.InitLogger(logger.DebugLevel)
|
||||
if err != nil {
|
||||
t.Errorf("#... - failed to initialize logger, error: %s", err)
|
||||
}
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, KeepAliveResponseTimeoutMs: 400, KeepAliveDelayMs: 100}
|
||||
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
e2tShutdownManagerMock := &mocks.E2TShutdownManagerMock{}
|
||||
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
e2tInstancesManager := NewE2TInstancesManager(rnibDataService, logger)
|
||||
|
||||
rmrMessengerMock := &mocks.RmrMessengerMock{}
|
||||
rmrSender := initRmrSender(rmrMessengerMock, logger)
|
||||
|
||||
e2tKeepAliveWorker := NewE2TKeepAliveWorker(logger, rmrSender, e2tInstancesManager, e2tShutdownManagerMock, config)
|
||||
|
||||
return rmrMessengerMock, readerMock, writerMock, e2tShutdownManagerMock, &e2tKeepAliveWorker
|
||||
}
|
||||
|
||||
func TestSendKeepAliveRequest(t *testing.T) {
|
||||
rmrMessengerMock, _, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
|
||||
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, false).Return(&rmrCgo.MBuf{}, nil)
|
||||
|
||||
e2tKeepAliveWorker.SendKeepAliveRequest()
|
||||
|
||||
var payload, xAction []byte
|
||||
var msgSrc unsafe.Pointer
|
||||
req := rmrCgo.NewMBuf(rmrCgo.E2_TERM_KEEP_ALIVE_REQ, 0, "", &payload, &xAction, msgSrc)
|
||||
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", req, false)
|
||||
}
|
||||
|
||||
func TestShutdownExpiredE2T_InternalError(t *testing.T) {
|
||||
rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
|
||||
|
||||
readerMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")))
|
||||
|
||||
e2tKeepAliveWorker.E2TKeepAliveExpired()
|
||||
|
||||
rmrMessengerMock.AssertNotCalled(t, "Shutdown")
|
||||
}
|
||||
|
||||
func TestShutdownExpiredE2T_NoAddresses(t *testing.T) {
|
||||
rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
|
||||
|
||||
addresses := []string{}
|
||||
|
||||
readerMock.On("GetE2TAddresses").Return(addresses, nil)
|
||||
|
||||
e2tKeepAliveWorker.E2TKeepAliveExpired()
|
||||
|
||||
rmrMessengerMock.AssertNotCalled(t, "Shutdown")
|
||||
}
|
||||
|
||||
func TestShutdownExpiredE2T_NotExpired_InternalError(t *testing.T) {
|
||||
rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
|
||||
|
||||
addresses := []string{E2TAddress,E2TAddress2}
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
|
||||
|
||||
readerMock.On("GetE2TAddresses").Return(addresses, nil)
|
||||
readerMock.On("GetE2TInstances",addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")))
|
||||
|
||||
e2tKeepAliveWorker.E2TKeepAliveExpired()
|
||||
|
||||
rmrMessengerMock.AssertNotCalled(t, "Shutdown")
|
||||
}
|
||||
|
||||
func TestShutdownExpiredE2T_NoE2T(t *testing.T) {
|
||||
rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
|
||||
|
||||
readerMock.On("GetE2TAddresses").Return([]string{}, common.NewResourceNotFoundError("not found"))
|
||||
|
||||
e2tKeepAliveWorker.E2TKeepAliveExpired()
|
||||
|
||||
rmrMessengerMock.AssertNotCalled(t, "Shutdown")
|
||||
}
|
||||
|
||||
func TestShutdownExpiredE2T_NotExpired(t *testing.T) {
|
||||
rmrMessengerMock, readerMock, _, _, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
|
||||
|
||||
addresses := []string{E2TAddress,E2TAddress2}
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
|
||||
|
||||
readerMock.On("GetE2TAddresses").Return(addresses, nil)
|
||||
readerMock.On("GetE2TInstances",addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
|
||||
|
||||
e2tKeepAliveWorker.E2TKeepAliveExpired()
|
||||
|
||||
rmrMessengerMock.AssertNotCalled(t, "Shutdown")
|
||||
}
|
||||
|
||||
func TestShutdownExpiredE2T_One_E2TExpired(t *testing.T) {
|
||||
_, readerMock, _, e2tShutdownManagerMock, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
|
||||
|
||||
addresses := []string{E2TAddress,E2TAddress2}
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
|
||||
|
||||
time.Sleep(time.Duration(400) * time.Millisecond)
|
||||
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
|
||||
|
||||
readerMock.On("GetE2TAddresses").Return(addresses, nil)
|
||||
readerMock.On("GetE2TInstances",addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
|
||||
e2tShutdownManagerMock.On("Shutdown", e2tInstance1).Return(nil)
|
||||
|
||||
e2tKeepAliveWorker.E2TKeepAliveExpired()
|
||||
|
||||
e2tShutdownManagerMock.AssertNumberOfCalls(t, "Shutdown", 1)
|
||||
}
|
||||
|
||||
func TestShutdownExpiredE2T_Two_E2TExpired(t *testing.T) {
|
||||
_, readerMock, _, e2tShutdownManagerMock, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
|
||||
|
||||
addresses := []string{E2TAddress,E2TAddress2}
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
|
||||
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.AssociatedRanList = []string{"test4","test5","test6", "test7"}
|
||||
|
||||
time.Sleep(time.Duration(400) * time.Millisecond)
|
||||
|
||||
readerMock.On("GetE2TAddresses").Return(addresses, nil)
|
||||
readerMock.On("GetE2TInstances",addresses).Return([]*entities.E2TInstance{e2tInstance1, e2tInstance2}, nil)
|
||||
e2tShutdownManagerMock.On("Shutdown", e2tInstance1).Return(nil)
|
||||
e2tShutdownManagerMock.On("Shutdown", e2tInstance2).Return(nil)
|
||||
|
||||
e2tKeepAliveWorker.E2TKeepAliveExpired()
|
||||
|
||||
e2tShutdownManagerMock.AssertNumberOfCalls(t, "Shutdown", 2)
|
||||
}
|
||||
|
||||
func TestExecute_Two_E2TExpired(t *testing.T) {
|
||||
rmrMessengerMock, readerMock, _, e2tShutdownManagerMock, e2tKeepAliveWorker := initE2TKeepAliveTest(t)
|
||||
|
||||
addresses := []string{E2TAddress,E2TAddress2}
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.AssociatedRanList = []string{"test1","test2","test3"}
|
||||
|
||||
readerMock.On("GetE2TAddresses").Return(addresses, nil)
|
||||
readerMock.On("GetE2TInstances",addresses).Return([]*entities.E2TInstance{e2tInstance1}, nil)
|
||||
e2tShutdownManagerMock.On("Shutdown", e2tInstance1).Return(nil)
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, false).Return(&rmrCgo.MBuf{}, nil)
|
||||
|
||||
go e2tKeepAliveWorker.Execute()
|
||||
|
||||
time.Sleep(time.Duration(500) * time.Millisecond)
|
||||
|
||||
var payload, xAction []byte
|
||||
var msgSrc unsafe.Pointer
|
||||
req := rmrCgo.NewMBuf(rmrCgo.E2_TERM_KEEP_ALIVE_REQ, 0, "", &payload, &xAction, msgSrc)
|
||||
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", req, false)
|
||||
e2tShutdownManagerMock.AssertCalled(t, "Shutdown", e2tInstance1)
|
||||
}
|
124
setup/e2mgr/E2Manager/managers/e2t_shutdown_manager.go
Normal file
124
setup/e2mgr/E2Manager/managers/e2t_shutdown_manager.go
Normal file
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// Copyright 2019 AT&T Intellectual Property
|
||||
// Copyright 2019 Nokia
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
// platform project (RICP).
|
||||
|
||||
package managers
|
||||
|
||||
import (
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/services"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"time"
|
||||
)
|
||||
|
||||
type IE2TShutdownManager interface {
|
||||
Shutdown(e2tInstance *entities.E2TInstance) error
|
||||
}
|
||||
|
||||
type E2TShutdownManager struct {
|
||||
logger *logger.Logger
|
||||
config *configuration.Configuration
|
||||
rnibDataService services.RNibDataService
|
||||
e2TInstancesManager IE2TInstancesManager
|
||||
e2tAssociationManager *E2TAssociationManager
|
||||
kubernetesManager *KubernetesManager
|
||||
}
|
||||
|
||||
func NewE2TShutdownManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, e2TInstancesManager IE2TInstancesManager, e2tAssociationManager *E2TAssociationManager, kubernetes *KubernetesManager) *E2TShutdownManager {
|
||||
return &E2TShutdownManager{
|
||||
logger: logger,
|
||||
config: config,
|
||||
rnibDataService: rnibDataService,
|
||||
e2TInstancesManager: e2TInstancesManager,
|
||||
e2tAssociationManager: e2tAssociationManager,
|
||||
kubernetesManager: kubernetes,
|
||||
}
|
||||
}
|
||||
|
||||
func (m E2TShutdownManager) Shutdown(e2tInstance *entities.E2TInstance) error {
|
||||
m.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s is Dead, RIP", e2tInstance.Address)
|
||||
|
||||
isE2tInstanceBeingDeleted := m.isE2tInstanceAlreadyBeingDeleted(e2tInstance)
|
||||
if isE2tInstanceBeingDeleted {
|
||||
m.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s is already being deleted", e2tInstance.Address)
|
||||
return nil
|
||||
}
|
||||
|
||||
//go m.kubernetesManager.DeletePod(e2tInstance.PodName)
|
||||
|
||||
err := m.markE2tInstanceToBeDeleted(e2tInstance)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to mark E2T %s as 'ToBeDeleted'.", e2tInstance.Address)
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.clearNodebsAssociation(e2tInstance.AssociatedRanList)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to clear nodebs association to E2T %s.", e2tInstance.Address)
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.e2tAssociationManager.RemoveE2tInstance(e2tInstance)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TShutdownManager.Shutdown - Failed to remove E2T %s.", e2tInstance.Address)
|
||||
return err
|
||||
}
|
||||
|
||||
m.logger.Infof("#E2TShutdownManager.Shutdown - E2T %s was shutdown successfully.", e2tInstance.Address)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m E2TShutdownManager) clearNodebsAssociation(ranNamesToBeDissociated []string) error {
|
||||
for _, ranName := range ranNamesToBeDissociated {
|
||||
nodeb, err := m.rnibDataService.GetNodeb(ranName)
|
||||
if err != nil {
|
||||
m.logger.Warnf("#E2TShutdownManager.associateAndSetupNodebs - Failed to get nodeb %s from db.", ranName)
|
||||
_, ok := err.(*common.ResourceNotFoundError)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
nodeb.AssociatedE2TInstanceAddress = ""
|
||||
nodeb.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
|
||||
err = m.rnibDataService.UpdateNodebInfo(nodeb)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#E2TShutdownManager.associateAndSetupNodebs - Failed to save nodeb %s from db.", ranName)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m E2TShutdownManager) markE2tInstanceToBeDeleted(e2tInstance *entities.E2TInstance) error {
|
||||
e2tInstance.State = entities.ToBeDeleted
|
||||
e2tInstance.DeletionTimestamp = time.Now().UnixNano()
|
||||
|
||||
return m.rnibDataService.SaveE2TInstance(e2tInstance)
|
||||
}
|
||||
|
||||
func (m E2TShutdownManager) isE2tInstanceAlreadyBeingDeleted(e2tInstance *entities.E2TInstance) bool {
|
||||
delta := time.Now().UnixNano() - e2tInstance.DeletionTimestamp
|
||||
timestampNanosec := int64(time.Duration(m.config.E2TInstanceDeletionTimeoutMs) * time.Millisecond)
|
||||
|
||||
return e2tInstance.State == entities.ToBeDeleted && delta <= timestampNanosec
|
||||
}
|
510
setup/e2mgr/E2Manager/managers/e2t_shutdown_manager_test.go
Normal file
510
setup/e2mgr/E2Manager/managers/e2t_shutdown_manager_test.go
Normal file
@@ -0,0 +1,510 @@
|
||||
//
|
||||
// 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 (
|
||||
"bytes"
|
||||
"e2mgr/clients"
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/e2managererrors"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/models"
|
||||
"e2mgr/services"
|
||||
"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/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"io/ioutil"
|
||||
//"k8s.io/apimachinery/pkg/runtime"
|
||||
//"k8s.io/client-go/kubernetes/fake"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
const E2TAddress3 = "10.10.2.17:9800"
|
||||
|
||||
func initE2TShutdownManagerTest(t *testing.T) (*E2TShutdownManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock, *KubernetesManager) {
|
||||
log := initLog(t)
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, E2TInstanceDeletionTimeoutMs: 15000}
|
||||
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
|
||||
|
||||
e2tInstancesManager := NewE2TInstancesManager(rnibDataService, log)
|
||||
httpClientMock := &mocks.HttpClientMock{}
|
||||
rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
|
||||
associationManager := NewE2TAssociationManager(log, rnibDataService, e2tInstancesManager, rmClient)
|
||||
//kubernetesManager := initKubernetesManagerTest(t)
|
||||
|
||||
/*shutdownManager := NewE2TShutdownManager(log, config, rnibDataService, e2tInstancesManager, associationManager, kubernetesManager)
|
||||
|
||||
return shutdownManager, readerMock, writerMock, httpClientMock, kubernetesManager*/
|
||||
shutdownManager := NewE2TShutdownManager(log, config, rnibDataService, e2tInstancesManager, associationManager, nil)
|
||||
|
||||
return shutdownManager, readerMock, writerMock, httpClientMock, nil
|
||||
}
|
||||
|
||||
func TestShutdownSuccess1OutOf3Instances(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,_ := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.State = entities.Active
|
||||
e2tInstance2.AssociatedRanList = []string{"test3"}
|
||||
e2tInstance3 := entities.NewE2TInstance(E2TAddress3, PodName)
|
||||
e2tInstance3.State = entities.Active
|
||||
e2tInstance3.AssociatedRanList = []string{"test4"}
|
||||
writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
|
||||
|
||||
nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
|
||||
nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
|
||||
nodeb5 := &entities.NodebInfo{RanName:"test5", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test5").Return(nodeb5, nil)
|
||||
|
||||
e2tAddresses := []string{E2TAddress, E2TAddress2,E2TAddress3}
|
||||
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
|
||||
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, e2tInstance1.AssociatedRanList, nil)
|
||||
marshaled, _ := json.Marshal(data)
|
||||
body := bytes.NewBuffer(marshaled)
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
writerMock.On("SaveE2TAddresses", []string{E2TAddress2,E2TAddress3}).Return(nil)
|
||||
|
||||
nodeb1connected := *nodeb1
|
||||
nodeb1connected.AssociatedE2TInstanceAddress = ""
|
||||
nodeb1connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb1connected).Return(nil)
|
||||
nodeb2connected := *nodeb2
|
||||
nodeb2connected.AssociatedE2TInstanceAddress = ""
|
||||
nodeb2connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb2connected).Return(nil)
|
||||
nodeb5connected := *nodeb5
|
||||
nodeb5connected.AssociatedE2TInstanceAddress = ""
|
||||
nodeb5connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb5connected).Return(nil)
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestShutdownSuccess1InstanceWithoutRans(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,_ := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance1.AssociatedRanList = []string{}
|
||||
writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
|
||||
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, nil)
|
||||
marshaled, _ := json.Marshal(data)
|
||||
body := bytes.NewBuffer(marshaled)
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
|
||||
writerMock.On("SaveE2TAddresses", []string{}).Return(nil)
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestShutdownSuccess1Instance2Rans(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,_ := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
|
||||
writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
|
||||
|
||||
nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
|
||||
nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
|
||||
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1", "test2"}, nil)
|
||||
marshaled, _ := json.Marshal(data)
|
||||
body := bytes.NewBuffer(marshaled)
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
|
||||
writerMock.On("SaveE2TAddresses", []string{}).Return(nil)
|
||||
|
||||
nodeb1new := *nodeb1
|
||||
nodeb1new.AssociatedE2TInstanceAddress = ""
|
||||
nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb1new).Return(nil)
|
||||
nodeb2new := *nodeb2
|
||||
nodeb2new.AssociatedE2TInstanceAddress = ""
|
||||
nodeb2new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb2new).Return(nil)
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
|
||||
}
|
||||
|
||||
func TestShutdownE2tInstanceAlreadyBeingDeleted(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,_ := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.ToBeDeleted
|
||||
e2tInstance1.AssociatedRanList = []string{"test1"}
|
||||
e2tInstance1.DeletionTimestamp = time.Now().UnixNano()
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
|
||||
}
|
||||
|
||||
func TestShutdownFailureMarkInstanceAsToBeDeleted(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,_ := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
|
||||
writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(e2managererrors.NewRnibDbError())
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
|
||||
}
|
||||
|
||||
func TestShutdownFailureRoutingManagerError(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,_ := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.State = entities.Active
|
||||
e2tInstance2.AssociatedRanList = []string{"test3"}
|
||||
e2tInstance3 := entities.NewE2TInstance(E2TAddress3, PodName)
|
||||
e2tInstance3.State = entities.Active
|
||||
e2tInstance3.AssociatedRanList = []string{"test4"}
|
||||
writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
|
||||
|
||||
nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
|
||||
nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
|
||||
nodeb5 := &entities.NodebInfo{RanName:"test5", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test5").Return(nodeb5, nil)
|
||||
|
||||
e2tAddresses := []string{E2TAddress, E2TAddress2,E2TAddress3}
|
||||
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
|
||||
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, e2tInstance1.AssociatedRanList, nil)
|
||||
marshaled, _ := json.Marshal(data)
|
||||
body := bytes.NewBuffer(marshaled)
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusBadRequest, Body: respBody}, nil)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
writerMock.On("SaveE2TAddresses", []string{E2TAddress2,E2TAddress3}).Return(nil)
|
||||
|
||||
nodeb1connected := *nodeb1
|
||||
nodeb1connected.AssociatedE2TInstanceAddress = ""
|
||||
nodeb1connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb1connected).Return(nil)
|
||||
nodeb2connected := *nodeb2
|
||||
nodeb2connected.AssociatedE2TInstanceAddress = ""
|
||||
nodeb2connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb2connected).Return(nil)
|
||||
nodeb5connected := *nodeb5
|
||||
nodeb5connected.AssociatedE2TInstanceAddress = ""
|
||||
nodeb5connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb5connected).Return(nil)
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
|
||||
}
|
||||
|
||||
func TestShutdownFailureInClearNodebsAssociation(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,_ := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
|
||||
writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
|
||||
|
||||
nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
|
||||
|
||||
nodeb1new := *nodeb1
|
||||
nodeb1new.AssociatedE2TInstanceAddress = ""
|
||||
nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb1new).Return(common.NewInternalError(fmt.Errorf("for tests")))
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestShutdownResourceNotFoundErrorInGetNodeb(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,_ := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
|
||||
writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
|
||||
|
||||
nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
|
||||
var nodeb2 *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", "test2").Return(nodeb2, common.NewResourceNotFoundError("for testing"))
|
||||
|
||||
nodeb1new := *nodeb1
|
||||
nodeb1new.AssociatedE2TInstanceAddress = ""
|
||||
nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb1new).Return(nil)
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestShutdownResourceGeneralErrorInGetNodeb(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,_ := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
|
||||
writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
|
||||
|
||||
var nodeb1 *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", "test1").Return(nodeb1, common.NewInternalError(fmt.Errorf("for testing")))
|
||||
nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
|
||||
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1", "test2"}, nil)
|
||||
marshaled, _ := json.Marshal(data)
|
||||
body := bytes.NewBuffer(marshaled)
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
|
||||
writerMock.On("SaveE2TAddresses", []string{}).Return(nil)
|
||||
|
||||
nodeb2new := *nodeb2
|
||||
nodeb2new.AssociatedE2TInstanceAddress = ""
|
||||
nodeb2new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb2new).Return(nil)
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
|
||||
}
|
||||
|
||||
func TestShutdownFailureInRemoveE2TInstance(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,_ := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
|
||||
e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
|
||||
e2tInstance2.State = entities.Active
|
||||
e2tInstance2.AssociatedRanList = []string{"test3"}
|
||||
e2tInstance3 := entities.NewE2TInstance(E2TAddress3, PodName)
|
||||
e2tInstance3.State = entities.Active
|
||||
e2tInstance3.AssociatedRanList = []string{"test4"}
|
||||
writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
|
||||
|
||||
nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
|
||||
nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
|
||||
nodeb5 := &entities.NodebInfo{RanName:"test5", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test5").Return(nodeb5, nil)
|
||||
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, e2tInstance1.AssociatedRanList, nil)
|
||||
marshaled, _ := json.Marshal(data)
|
||||
body := bytes.NewBuffer(marshaled)
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(common.NewInternalError(fmt.Errorf("for tests")))
|
||||
|
||||
nodeb1connected := *nodeb1
|
||||
nodeb1connected.AssociatedE2TInstanceAddress = ""
|
||||
nodeb1connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb1connected).Return(nil)
|
||||
nodeb2connected := *nodeb2
|
||||
nodeb2connected.AssociatedE2TInstanceAddress = ""
|
||||
nodeb2connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb2connected).Return(nil)
|
||||
nodeb5connected := *nodeb5
|
||||
nodeb5connected.AssociatedE2TInstanceAddress = ""
|
||||
nodeb5connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb5connected).Return(nil)
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
}
|
||||
/*
|
||||
func TestShutdownSuccess2Instance2Rans(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,kubernetesManager := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance1.AssociatedRanList = []string{"test2"}
|
||||
writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
|
||||
|
||||
nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress2, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
|
||||
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test2"}, nil)
|
||||
marshaled, _ := json.Marshal(data)
|
||||
body := bytes.NewBuffer(marshaled)
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
|
||||
writerMock.On("SaveE2TAddresses", []string{}).Return(nil)
|
||||
|
||||
nodeb1new := *nodeb1
|
||||
nodeb1new.AssociatedE2TInstanceAddress = ""
|
||||
nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
nodeb2new := *nodeb2
|
||||
nodeb2new.AssociatedE2TInstanceAddress = ""
|
||||
nodeb2new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb2new).Return(nil)
|
||||
|
||||
test := TestStruct{
|
||||
description: "namespace, 2 pods in Oran",
|
||||
namespace: "oran",
|
||||
objs: []runtime.Object{pod("oran", PodName), pod("oran", "e2t_2"), pod("some-namespace", "POD_Test_1")},
|
||||
}
|
||||
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
})
|
||||
}
|
||||
|
||||
func TestShutdownSuccess2Instance2RansNoPod(t *testing.T) {
|
||||
shutdownManager, readerMock, writerMock, httpClientMock,kubernetesManager := initE2TShutdownManagerTest(t)
|
||||
|
||||
e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
|
||||
e2tInstance1.State = entities.Active
|
||||
e2tInstance1.AssociatedRanList = []string{"test2"}
|
||||
writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool { return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted })).Return(nil)
|
||||
|
||||
nodeb1 := &entities.NodebInfo{RanName:"test1", AssociatedE2TInstanceAddress:E2TAddress2, ConnectionStatus:entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
nodeb2 := &entities.NodebInfo{RanName:"test2", AssociatedE2TInstanceAddress:E2TAddress, ConnectionStatus:entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
|
||||
|
||||
data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test2"}, nil)
|
||||
marshaled, _ := json.Marshal(data)
|
||||
body := bytes.NewBuffer(marshaled)
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
|
||||
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
|
||||
writerMock.On("SaveE2TAddresses", []string{}).Return(nil)
|
||||
|
||||
nodeb1new := *nodeb1
|
||||
nodeb1new.AssociatedE2TInstanceAddress = ""
|
||||
nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
nodeb2new := *nodeb2
|
||||
nodeb2new.AssociatedE2TInstanceAddress = ""
|
||||
nodeb2new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &nodeb2new).Return(nil)
|
||||
|
||||
test := TestStruct{
|
||||
description: "namespace, 2 pods in Oran",
|
||||
namespace: "oran",
|
||||
objs: []runtime.Object{pod("oran", "e2t_2"), pod("some-namespace", "POD_Test_1")},
|
||||
}
|
||||
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
|
||||
|
||||
err := shutdownManager.Shutdown(e2tInstance1)
|
||||
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
})
|
||||
}*/
|
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// 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/converters"
|
||||
"e2mgr/logger"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
)
|
||||
|
||||
type EndcSetupFailureResponseManager struct {
|
||||
converter converters.IEndcSetupFailureResponseConverter
|
||||
}
|
||||
|
||||
func NewEndcSetupFailureResponseManager(converter converters.IEndcSetupFailureResponseConverter) *EndcSetupFailureResponseManager {
|
||||
return &EndcSetupFailureResponseManager{
|
||||
converter: converter,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *EndcSetupFailureResponseManager) PopulateNodebByPdu(logger *logger.Logger, nbIdentity *entities.NbIdentity, nodebInfo *entities.NodebInfo, payload []byte) error {
|
||||
|
||||
failureResponse, err := m.converter.UnpackEndcSetupFailureResponseAndExtract(payload)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("#EndcSetupFailureResponseManager.PopulateNodebByPdu - RAN name: %s - Unpack and extract failed. Error: %v", nodebInfo.RanName, err)
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Infof("#EndcSetupFailureResponseManager.PopulateNodebByPdu - RAN name: %s - Unpacked payload and extracted protobuf successfully", nodebInfo.RanName)
|
||||
|
||||
nodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED_SETUP_FAILED
|
||||
nodebInfo.SetupFailure = failureResponse
|
||||
nodebInfo.FailureType = entities.Failure_ENDC_X2_SETUP_FAILURE
|
||||
return nil
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// 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/converters"
|
||||
"e2mgr/tests"
|
||||
"fmt"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPopulateNodebByPduFailure(t *testing.T) {
|
||||
logger := tests.InitLog(t)
|
||||
nodebInfo := &entities.NodebInfo{}
|
||||
nodebIdentity := &entities.NbIdentity{}
|
||||
converter := converters.NewEndcSetupFailureResponseConverter(logger)
|
||||
handler := NewEndcSetupFailureResponseManager(converter)
|
||||
err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createRandomPayload())
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestPopulateNodebByPduSuccess(t *testing.T) {
|
||||
logger := tests.InitLog(t)
|
||||
nodebInfo := &entities.NodebInfo{}
|
||||
nodebIdentity := &entities.NbIdentity{}
|
||||
converter := converters.NewEndcSetupFailureResponseConverter(logger)
|
||||
handler := NewEndcSetupFailureResponseManager(converter)
|
||||
err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createSetupFailureResponsePayload(t))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, entities.ConnectionStatus_CONNECTED_SETUP_FAILED, nodebInfo.ConnectionStatus)
|
||||
assert.Equal(t, entities.Failure_ENDC_X2_SETUP_FAILURE, nodebInfo.FailureType)
|
||||
|
||||
}
|
||||
|
||||
func createSetupFailureResponsePayload(t *testing.T) []byte {
|
||||
packedPdu := "4024001a0000030005400200000016400100001140087821a00000008040"
|
||||
var payload []byte
|
||||
_, err := fmt.Sscanf(packedPdu, "%x", &payload)
|
||||
if err != nil {
|
||||
t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
|
||||
}
|
||||
return payload
|
||||
}
|
||||
|
||||
func createRandomPayload() []byte {
|
||||
payload := make([]byte, 20)
|
||||
rand.Read(payload)
|
||||
return payload
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// 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/converters"
|
||||
"e2mgr/logger"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
)
|
||||
|
||||
type EndcSetupResponseManager struct{
|
||||
converter converters.IEndcSetupResponseConverter
|
||||
}
|
||||
|
||||
func NewEndcSetupResponseManager(converter converters.IEndcSetupResponseConverter) *EndcSetupResponseManager {
|
||||
return &EndcSetupResponseManager{
|
||||
converter: converter,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *EndcSetupResponseManager) PopulateNodebByPdu(logger *logger.Logger, nbIdentity *entities.NbIdentity, nodebInfo *entities.NodebInfo, payload []byte) error {
|
||||
|
||||
gnbId, gnb, err := m.converter.UnpackEndcSetupResponseAndExtract(payload)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("#EndcSetupResponseManager.PopulateNodebByPdu - RAN name: %s - Unpack and extract failed. Error: %v", nodebInfo.RanName, err)
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Infof("#EndcSetupResponseManager.PopulateNodebByPdu - RAN name: %s - Unpacked payload and extracted protobuf successfully", nodebInfo.RanName)
|
||||
|
||||
nbIdentity.GlobalNbId = gnbId
|
||||
nodebInfo.GlobalNbId = gnbId
|
||||
nodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED
|
||||
nodebInfo.NodeType = entities.Node_GNB
|
||||
nodebInfo.Configuration = &entities.NodebInfo_Gnb{Gnb: gnb}
|
||||
|
||||
return nil
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// 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/converters"
|
||||
"e2mgr/tests"
|
||||
"fmt"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSetupResponsePopulateNodebByPduFailure(t *testing.T) {
|
||||
logger := tests.InitLog(t)
|
||||
nodebInfo := &entities.NodebInfo{}
|
||||
nodebIdentity := &entities.NbIdentity{}
|
||||
converter:= converters.NewEndcSetupResponseConverter(logger)
|
||||
handler := NewEndcSetupResponseManager(converter)
|
||||
err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createRandomPayload())
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestSetupResponsePopulateNodebByPduSuccess(t *testing.T) {
|
||||
logger := tests.InitLog(t)
|
||||
nodebInfo := &entities.NodebInfo{}
|
||||
nodebIdentity := &entities.NbIdentity{}
|
||||
converter:= converters.NewEndcSetupResponseConverter(logger)
|
||||
handler := NewEndcSetupResponseManager(converter)
|
||||
err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createSetupResponsePayload(t))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, entities.ConnectionStatus_CONNECTED, nodebInfo.ConnectionStatus)
|
||||
assert.Equal(t, entities.Node_GNB, nodebInfo.NodeType)
|
||||
|
||||
}
|
||||
|
||||
func createSetupResponsePayload(t *testing.T) []byte {
|
||||
packedPdu := "202400808e00000100f600808640000200fc00090002f829504a952a0a00fd007200010c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a000211e148033e4e5e4c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a00021a0044033e4e5e000000002c001e3f271f2e3d4ff0031e3f274400010000150400000a00020000"
|
||||
var payload []byte
|
||||
_, err := fmt.Sscanf(packedPdu, "%x", &payload)
|
||||
if err != nil {
|
||||
t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
|
||||
}
|
||||
return payload
|
||||
}
|
30
setup/e2mgr/E2Manager/managers/i_setup_response_manager.go
Normal file
30
setup/e2mgr/E2Manager/managers/i_setup_response_manager.go
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// 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 ISetupResponseManager interface {
|
||||
PopulateNodebByPdu(logger *logger.Logger, nbIdentity *entities.NbIdentity, nodebInfo *entities.NodebInfo, payload []byte) error
|
||||
}
|
87
setup/e2mgr/E2Manager/managers/kubernetes_manager.go
Normal file
87
setup/e2mgr/E2Manager/managers/kubernetes_manager.go
Normal file
@@ -0,0 +1,87 @@
|
||||
//
|
||||
// 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"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
type KubernetesManager struct {
|
||||
Logger *logger.Logger
|
||||
ClientSet kubernetes.Interface
|
||||
Config *configuration.Configuration
|
||||
}
|
||||
|
||||
func NewKubernetesManager(logger *logger.Logger, config *configuration.Configuration) *KubernetesManager {
|
||||
return &KubernetesManager{
|
||||
Logger: logger,
|
||||
//ClientSet: createClientSet(logger, config),
|
||||
Config: config,
|
||||
}
|
||||
}
|
||||
|
||||
/*func createClientSet(logger *logger.Logger, config *configuration.Configuration) kubernetes.Interface {
|
||||
|
||||
absConfigPath,err := filepath.Abs(config.Kubernetes.ConfigPath)
|
||||
if err != nil {
|
||||
logger.Errorf("#KubernetesManager.init - error: %s", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
kubernetesConfig, err := clientcmd.BuildConfigFromFlags("", absConfigPath)
|
||||
if err != nil {
|
||||
logger.Errorf("#KubernetesManager.init - error: %s", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
clientSet, err := kubernetes.NewForConfig(kubernetesConfig)
|
||||
if err != nil {
|
||||
logger.Errorf("#KubernetesManager.init - error: %s", err)
|
||||
return nil
|
||||
}
|
||||
return clientSet
|
||||
}*/
|
||||
|
||||
/*func (km KubernetesManager) DeletePod(podName string) error {
|
||||
km.Logger.Infof("#KubernetesManager.DeletePod - POD name: %s ", podName)
|
||||
|
||||
if km.ClientSet == nil {
|
||||
km.Logger.Errorf("#KubernetesManager.DeletePod - no kubernetesManager connection")
|
||||
return e2managererrors.NewInternalError()
|
||||
}
|
||||
|
||||
if len(podName) == 0 {
|
||||
km.Logger.Warnf("#KubernetesManager.DeletePod - empty pod name")
|
||||
return e2managererrors.NewInternalError()
|
||||
}
|
||||
|
||||
err := km.ClientSet.CoreV1().Pods(km.Config.Kubernetes.KubeNamespace).Delete(podName, &metaV1.DeleteOptions{})
|
||||
|
||||
if err != nil {
|
||||
km.Logger.Errorf("#KubernetesManager.DeletePod - POD %s can't be deleted, error: %s", podName, err)
|
||||
return err
|
||||
}
|
||||
|
||||
km.Logger.Infof("#KubernetesManager.DeletePod - POD %s was deleted", podName)
|
||||
return nil
|
||||
}*/
|
152
setup/e2mgr/E2Manager/managers/kubernetes_manager_test.go
Normal file
152
setup/e2mgr/E2Manager/managers/kubernetes_manager_test.go
Normal file
@@ -0,0 +1,152 @@
|
||||
//
|
||||
// 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"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type TestStruct struct {
|
||||
description string
|
||||
namespace string
|
||||
expected []string
|
||||
objs []runtime.Object
|
||||
}
|
||||
|
||||
func initKubernetesManagerTest(t *testing.T) *KubernetesManager {
|
||||
logger, err := logger.InitLogger(logger.DebugLevel)
|
||||
if err != nil {
|
||||
t.Errorf("#... - failed to initialize logger, error: %s", err)
|
||||
}
|
||||
config := &configuration.Configuration{}
|
||||
config.Kubernetes.KubeNamespace = "oran"
|
||||
config.Kubernetes.ConfigPath = "somePath"
|
||||
|
||||
kubernetesManager := NewKubernetesManager(logger, config)
|
||||
|
||||
return kubernetesManager
|
||||
}
|
||||
|
||||
func TestDelete_NoPodName(t *testing.T) {
|
||||
test := TestStruct{
|
||||
description: "2 namespace, 2 pods in oran",
|
||||
namespace: "oran",
|
||||
objs: []runtime.Object{pod("oran", "POD_Test_1"), pod("oran", "POD_Test_2"), pod("some-namespace", "POD_Test_1")},
|
||||
}
|
||||
|
||||
kubernetesManager := initKubernetesManagerTest(t)
|
||||
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
|
||||
|
||||
err := kubernetesManager.DeletePod("")
|
||||
assert.NotNil(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDelete_NoPods(t *testing.T) {
|
||||
test := TestStruct{
|
||||
description: "no pods",
|
||||
namespace: "oran",
|
||||
expected: nil,
|
||||
objs: nil,
|
||||
}
|
||||
|
||||
kubernetesManager := initKubernetesManagerTest(t)
|
||||
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
|
||||
|
||||
err := kubernetesManager.DeletePod("POD_Test")
|
||||
assert.NotNil(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDelete_PodExists(t *testing.T) {
|
||||
test := TestStruct{
|
||||
description: "2 namespace, 2 pods in oran",
|
||||
namespace: "oran",
|
||||
objs: []runtime.Object{pod("oran", "POD_Test_1"), pod("oran", "POD_Test_2"), pod("some-namespace", "POD_Test_1")},
|
||||
}
|
||||
|
||||
kubernetesManager := initKubernetesManagerTest(t)
|
||||
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
|
||||
|
||||
err := kubernetesManager.DeletePod("POD_Test_1")
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDelete_NoPodInNamespace(t *testing.T) {
|
||||
test := TestStruct{
|
||||
description: "2 namespace, 2 pods in oran",
|
||||
namespace: "oran",
|
||||
objs: []runtime.Object{pod("oran", "POD_Test_1"), pod("oran", "POD_Test_2"), pod("some-namespace", "POD_Test")},
|
||||
}
|
||||
|
||||
kubernetesManager := initKubernetesManagerTest(t)
|
||||
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
|
||||
|
||||
err := kubernetesManager.DeletePod("POD_Test")
|
||||
assert.NotNil(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDelete_NoNamespace(t *testing.T) {
|
||||
test := TestStruct{
|
||||
description: "No oran namespace",
|
||||
namespace: "oran",
|
||||
objs: []runtime.Object{pod("some-namespace", "POD_Test_1"), pod("some-namespace", "POD_Test_2"), pod("some-namespace", "POD_Test")},
|
||||
}
|
||||
|
||||
kubernetesManager := initKubernetesManagerTest(t)
|
||||
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
kubernetesManager.ClientSet = fake.NewSimpleClientset(test.objs...)
|
||||
|
||||
err := kubernetesManager.DeletePod("POD_Test")
|
||||
assert.NotNil(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func pod(namespace, image string) *v1.Pod {
|
||||
|
||||
return &v1.Pod{
|
||||
ObjectMeta: metaV1.ObjectMeta{
|
||||
Name: image,
|
||||
Namespace: namespace,
|
||||
Annotations: map[string]string{},
|
||||
},
|
||||
}
|
||||
}
|
||||
*/
|
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// 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 notificationmanager
|
||||
|
||||
import (
|
||||
"e2mgr/logger"
|
||||
"e2mgr/models"
|
||||
"e2mgr/providers/rmrmsghandlerprovider"
|
||||
"e2mgr/rmrCgo"
|
||||
"time"
|
||||
)
|
||||
|
||||
type NotificationManager struct {
|
||||
logger *logger.Logger
|
||||
notificationHandlerProvider *rmrmsghandlerprovider.NotificationHandlerProvider
|
||||
}
|
||||
|
||||
func NewNotificationManager(logger *logger.Logger, notificationHandlerProvider *rmrmsghandlerprovider.NotificationHandlerProvider) *NotificationManager {
|
||||
return &NotificationManager{
|
||||
logger: logger,
|
||||
notificationHandlerProvider: notificationHandlerProvider,
|
||||
}
|
||||
}
|
||||
|
||||
func (m NotificationManager) HandleMessage(mbuf *rmrCgo.MBuf) error {
|
||||
|
||||
notificationHandler, err := m.notificationHandlerProvider.GetNotificationHandler(mbuf.MType)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#NotificationManager.HandleMessage - Error: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
notificationRequest := models.NewNotificationRequest(mbuf.Meid, *mbuf.Payload, time.Now(), *mbuf.XAction, mbuf.GetMsgSrc())
|
||||
go notificationHandler.Handle(notificationRequest)
|
||||
return nil
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// 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 notificationmanager
|
||||
|
||||
import (
|
||||
"e2mgr/clients"
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/providers/rmrmsghandlerprovider"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"e2mgr/services/rmrsender"
|
||||
"e2mgr/tests"
|
||||
"fmt"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func initNotificationManagerTest(t *testing.T) (*logger.Logger, *mocks.RnibReaderMock, *NotificationManager) {
|
||||
logger := initLog(t)
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
|
||||
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
httpClient := &mocks.HttpClientMock{}
|
||||
|
||||
rmrSender := initRmrSender(&mocks.RmrMessengerMock{}, logger)
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
|
||||
e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
|
||||
routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClient)
|
||||
e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient)
|
||||
rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider()
|
||||
rmrNotificationHandlerProvider.Init(logger, config, rnibDataService, rmrSender, ranSetupManager, e2tInstancesManager,routingManagerClient, e2tAssociationManager)
|
||||
notificationManager := NewNotificationManager(logger, rmrNotificationHandlerProvider )
|
||||
return logger, readerMock, notificationManager
|
||||
}
|
||||
|
||||
func TestHandleMessageUnexistingMessageType(t *testing.T) {
|
||||
_, _, nm := initNotificationManagerTest(t)
|
||||
|
||||
mbuf := &rmrCgo.MBuf{MType: 1234}
|
||||
|
||||
err := nm.HandleMessage(mbuf)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestHandleMessageExistingMessageType(t *testing.T) {
|
||||
_, readerMock, nm := initNotificationManagerTest(t)
|
||||
payload := []byte("123")
|
||||
xaction := []byte("test")
|
||||
mbuf := &rmrCgo.MBuf{MType: rmrCgo.RIC_X2_SETUP_RESP, Meid: "test", Payload: &payload, XAction: &xaction}
|
||||
readerMock.On("GetNodeb", "test").Return(&entities.NodebInfo{}, fmt.Errorf("Some error"))
|
||||
err := nm.HandleMessage(mbuf)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
// TODO: extract to test_utils
|
||||
func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
|
||||
rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
|
||||
rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
|
||||
return rmrsender.NewRmrSender(log, rmrMessenger)
|
||||
}
|
||||
|
||||
// TODO: extract to test_utils
|
||||
func initLog(t *testing.T) *logger.Logger {
|
||||
log, err := logger.InitLogger(logger.InfoLevel)
|
||||
if err != nil {
|
||||
t.Errorf("#delete_all_request_handler_test.TestHandleSuccessFlow - failed to initialize logger, error: %s", err)
|
||||
}
|
||||
return log
|
||||
}
|
93
setup/e2mgr/E2Manager/managers/ran_disconnection_manager.go
Normal file
93
setup/e2mgr/E2Manager/managers/ran_disconnection_manager.go
Normal file
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// Copyright 2019 AT&T Intellectual Property
|
||||
// Copyright 2019 Nokia
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
// platform project (RICP).
|
||||
|
||||
package managers
|
||||
|
||||
import (
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/services"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
)
|
||||
|
||||
type IRanDisconnectionManager interface {
|
||||
DisconnectRan(inventoryName string) error
|
||||
}
|
||||
|
||||
type RanDisconnectionManager struct {
|
||||
logger *logger.Logger
|
||||
config *configuration.Configuration
|
||||
rnibDataService services.RNibDataService
|
||||
ranSetupManager *RanSetupManager
|
||||
e2tAssociationManager *E2TAssociationManager
|
||||
}
|
||||
|
||||
func NewRanDisconnectionManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, e2tAssociationManager *E2TAssociationManager) *RanDisconnectionManager {
|
||||
return &RanDisconnectionManager{
|
||||
logger: logger,
|
||||
config: config,
|
||||
rnibDataService: rnibDataService,
|
||||
e2tAssociationManager: e2tAssociationManager,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *RanDisconnectionManager) DisconnectRan(inventoryName string) error {
|
||||
nodebInfo, err := m.rnibDataService.GetNodeb(inventoryName)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#RanDisconnectionManager.DisconnectRan - RAN name: %s - Failed fetching RAN from rNib. Error: %v", inventoryName, err)
|
||||
return err
|
||||
}
|
||||
|
||||
connectionStatus := nodebInfo.GetConnectionStatus()
|
||||
m.logger.Infof("#RanDisconnectionManager.DisconnectRan - RAN name: %s - RAN's connection status: %s", nodebInfo.RanName, connectionStatus)
|
||||
|
||||
|
||||
if connectionStatus == entities.ConnectionStatus_SHUT_DOWN {
|
||||
m.logger.Warnf("#RanDisconnectionManager.DisconnectRan - RAN name: %s - quit. RAN's connection status is SHUT_DOWN", nodebInfo.RanName)
|
||||
return nil
|
||||
}
|
||||
|
||||
if connectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
|
||||
return m.updateNodebInfo(nodebInfo, entities.ConnectionStatus_SHUT_DOWN)
|
||||
}
|
||||
|
||||
err = m.updateNodebInfo(nodebInfo, entities.ConnectionStatus_DISCONNECTED)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e2tAddress := nodebInfo.AssociatedE2TInstanceAddress
|
||||
return m.e2tAssociationManager.DissociateRan(e2tAddress, nodebInfo.RanName)
|
||||
}
|
||||
|
||||
func (m *RanDisconnectionManager) updateNodebInfo(nodebInfo *entities.NodebInfo, connectionStatus entities.ConnectionStatus) error {
|
||||
|
||||
nodebInfo.ConnectionStatus = connectionStatus;
|
||||
err := m.rnibDataService.UpdateNodebInfo(nodebInfo)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#RanDisconnectionManager.updateNodebInfo - RAN name: %s - Failed updating RAN's connection status to %s in rNib. Error: %v", nodebInfo.RanName, connectionStatus, err)
|
||||
return err
|
||||
}
|
||||
|
||||
m.logger.Infof("#RanDisconnectionManager.updateNodebInfo - RAN name: %s - Successfully updated rNib. RAN's current connection status: %s", nodebInfo.RanName, nodebInfo.ConnectionStatus)
|
||||
return nil
|
||||
}
|
204
setup/e2mgr/E2Manager/managers/ran_disconnection_manager_test.go
Normal file
204
setup/e2mgr/E2Manager/managers/ran_disconnection_manager_test.go
Normal file
@@ -0,0 +1,204 @@
|
||||
//
|
||||
// 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/clients"
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"e2mgr/services/rmrsender"
|
||||
"e2mgr/tests"
|
||||
"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 ranName = "test"
|
||||
const e2tAddress = "10.10.2.15:9800"
|
||||
|
||||
func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessengerMock, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *RanDisconnectionManager, *mocks.HttpClientMock) {
|
||||
logger, err := logger.InitLogger(logger.DebugLevel)
|
||||
if err != nil {
|
||||
t.Errorf("#... - failed to initialize logger, error: %s", err)
|
||||
}
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
|
||||
|
||||
rmrMessengerMock := &mocks.RmrMessengerMock{}
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
e2tInstancesManager := NewE2TInstancesManager(rnibDataService, logger)
|
||||
httpClient := &mocks.HttpClientMock{}
|
||||
routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClient)
|
||||
e2tAssociationManager := NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient)
|
||||
ranDisconnectionManager := NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager)
|
||||
return logger, rmrMessengerMock, readerMock, writerMock, ranDisconnectionManager, httpClient
|
||||
}
|
||||
|
||||
func TestRanDisconnectionGetNodebFailure(t *testing.T) {
|
||||
_, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t)
|
||||
|
||||
var nodebInfo *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", ranName).Return(nodebInfo, common.NewInternalError(errors.New("Error")))
|
||||
err := ranDisconnectionManager.DisconnectRan(ranName)
|
||||
assert.NotNil(t, err)
|
||||
readerMock.AssertCalled(t, "GetNodeb", ranName)
|
||||
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
|
||||
}
|
||||
|
||||
func TestShutdownRan(t *testing.T) {
|
||||
_, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t)
|
||||
|
||||
origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
|
||||
err := ranDisconnectionManager.DisconnectRan(ranName)
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertCalled(t, "GetNodeb", ranName)
|
||||
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
|
||||
}
|
||||
|
||||
func TestShuttingdownRan(t *testing.T) {
|
||||
_, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t)
|
||||
|
||||
origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
|
||||
updatedNodebInfo := *origNodebInfo
|
||||
updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
|
||||
writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(rnibErr)
|
||||
err := ranDisconnectionManager.DisconnectRan(ranName)
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertCalled(t, "GetNodeb", ranName)
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
|
||||
}
|
||||
|
||||
func TestShuttingDownRanUpdateNodebInfoFailure(t *testing.T) {
|
||||
_, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t)
|
||||
|
||||
origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
|
||||
updatedNodebInfo := *origNodebInfo
|
||||
updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
|
||||
writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error")))
|
||||
err := ranDisconnectionManager.DisconnectRan(ranName)
|
||||
assert.NotNil(t, err)
|
||||
readerMock.AssertCalled(t, "GetNodeb", ranName)
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
|
||||
}
|
||||
|
||||
func TestConnectingRanUpdateNodebInfoFailure(t *testing.T) {
|
||||
_, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t)
|
||||
|
||||
origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
|
||||
updatedNodebInfo := *origNodebInfo
|
||||
updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error")))
|
||||
err := ranDisconnectionManager.DisconnectRan(ranName)
|
||||
assert.NotNil(t, err)
|
||||
readerMock.AssertCalled(t, "GetNodeb", ranName)
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
|
||||
}
|
||||
|
||||
func TestConnectingRanDisconnectSucceeds(t *testing.T) {
|
||||
_, _, readerMock, writerMock, ranDisconnectionManager, httpClient := initRanLostConnectionTest(t)
|
||||
|
||||
origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, AssociatedE2TInstanceAddress: E2TAddress}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
|
||||
updatedNodebInfo1 := *origNodebInfo
|
||||
updatedNodebInfo1.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &updatedNodebInfo1).Return(rnibErr)
|
||||
updatedNodebInfo2 := *origNodebInfo
|
||||
updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
updatedNodebInfo2.AssociatedE2TInstanceAddress = ""
|
||||
writerMock.On("UpdateNodebInfo", &updatedNodebInfo2).Return(rnibErr)
|
||||
e2tInstance := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{ranName}}
|
||||
readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
|
||||
e2tInstanceToSave := * e2tInstance
|
||||
e2tInstanceToSave.AssociatedRanList = []string{}
|
||||
writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil)
|
||||
mockHttpClient(httpClient, clients.DissociateRanE2TInstanceApiSuffix, true)
|
||||
err := ranDisconnectionManager.DisconnectRan(ranName)
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertCalled(t, "GetNodeb", ranName)
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
|
||||
}
|
||||
|
||||
func TestConnectingRanDissociateFailsRmError(t *testing.T) {
|
||||
_, _, readerMock, writerMock, ranDisconnectionManager, httpClient := initRanLostConnectionTest(t)
|
||||
|
||||
origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, AssociatedE2TInstanceAddress: E2TAddress}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
|
||||
updatedNodebInfo1 := *origNodebInfo
|
||||
updatedNodebInfo1.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &updatedNodebInfo1).Return(rnibErr)
|
||||
updatedNodebInfo2 := *origNodebInfo
|
||||
updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
updatedNodebInfo2.AssociatedE2TInstanceAddress = ""
|
||||
writerMock.On("UpdateNodebInfo", &updatedNodebInfo2).Return(rnibErr)
|
||||
e2tInstance := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{ranName}}
|
||||
readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
|
||||
e2tInstanceToSave := * e2tInstance
|
||||
e2tInstanceToSave.AssociatedRanList = []string{}
|
||||
writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil)
|
||||
mockHttpClient(httpClient, clients.DissociateRanE2TInstanceApiSuffix, false)
|
||||
err := ranDisconnectionManager.DisconnectRan(ranName)
|
||||
assert.Nil(t, err)
|
||||
readerMock.AssertCalled(t, "GetNodeb", ranName)
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
|
||||
}
|
||||
|
||||
func TestConnectingRanDissociateFailsDbError(t *testing.T) {
|
||||
_, _, readerMock, writerMock, ranDisconnectionManager, _ := initRanLostConnectionTest(t)
|
||||
|
||||
origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, AssociatedE2TInstanceAddress: e2tAddress}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
|
||||
updatedNodebInfo1 := *origNodebInfo
|
||||
updatedNodebInfo1.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &updatedNodebInfo1).Return(rnibErr)
|
||||
updatedNodebInfo2 := *origNodebInfo
|
||||
updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
updatedNodebInfo2.AssociatedE2TInstanceAddress = ""
|
||||
writerMock.On("UpdateNodebInfo", &updatedNodebInfo2).Return(rnibErr)
|
||||
e2tInstance := &entities.E2TInstance{Address: e2tAddress, AssociatedRanList: []string{ranName}}
|
||||
readerMock.On("GetE2TInstance", e2tAddress).Return(e2tInstance, common.NewInternalError(errors.New("Error")))
|
||||
err := ranDisconnectionManager.DisconnectRan(ranName)
|
||||
assert.NotNil(t, err)
|
||||
readerMock.AssertCalled(t, "GetNodeb", ranName)
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
|
||||
writerMock.AssertNotCalled(t, "SaveE2TInstance", )
|
||||
}
|
||||
|
||||
func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
|
||||
rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
|
||||
rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
|
||||
return rmrsender.NewRmrSender(log, rmrMessenger)
|
||||
}
|
131
setup/e2mgr/E2Manager/managers/ran_setup_manager.go
Normal file
131
setup/e2mgr/E2Manager/managers/ran_setup_manager.go
Normal file
@@ -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/e2managererrors"
|
||||
"e2mgr/e2pdus"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"e2mgr/services/rmrsender"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type RanSetupManager struct {
|
||||
logger *logger.Logger
|
||||
rnibDataService services.RNibDataService
|
||||
rmrSender *rmrsender.RmrSender
|
||||
}
|
||||
|
||||
type IRanSetupManager interface {
|
||||
ExecuteSetup(nodebInfo *entities.NodebInfo, status entities.ConnectionStatus) error
|
||||
}
|
||||
|
||||
func NewRanSetupManager(logger *logger.Logger, rmrSender *rmrsender.RmrSender, rnibDataService services.RNibDataService) *RanSetupManager {
|
||||
return &RanSetupManager{
|
||||
logger: logger,
|
||||
rnibDataService: rnibDataService,
|
||||
rmrSender: rmrSender,
|
||||
}
|
||||
}
|
||||
|
||||
// Update retries and connection status
|
||||
func (m *RanSetupManager) updateConnectionStatus(nodebInfo *entities.NodebInfo, status entities.ConnectionStatus) error {
|
||||
// Update retries and connection status
|
||||
nodebInfo.ConnectionStatus = status
|
||||
err := m.rnibDataService.UpdateNodebInfo(nodebInfo)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#RanSetupManager.updateConnectionStatus - Ran name: %s - Failed updating RAN's connection status to %v : %s", nodebInfo.RanName, status, err)
|
||||
} else {
|
||||
m.logger.Infof("#RanSetupManager.updateConnectionStatus - Ran name: %s - Successfully updated rNib. RAN's current connection status: %v", nodebInfo.RanName, status)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Decrement retries and connection status (disconnected)
|
||||
func (m *RanSetupManager) updateConnectionStatusDisconnected(nodebInfo *entities.NodebInfo) error {
|
||||
// Update retries and connection status
|
||||
nodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
err := m.rnibDataService.UpdateNodebInfo(nodebInfo)
|
||||
if err != nil {
|
||||
m.logger.Errorf("#RanSetupManager.updateConnectionStatusDisconnected - Ran name: %s - Failed updating RAN's connection status to DISCONNECTED : %s", nodebInfo.RanName, err)
|
||||
} else {
|
||||
m.logger.Infof("#RanSetupManager.updateConnectionStatusDisconnected - Ran name: %s - Successfully updated rNib. RAN's current connection status: DISCONNECTED", nodebInfo.RanName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *RanSetupManager) prepareSetupRequest(nodebInfo *entities.NodebInfo) (int, *models.E2RequestMessage, error) {
|
||||
// Build the endc/x2 setup request
|
||||
switch nodebInfo.E2ApplicationProtocol {
|
||||
case entities.E2ApplicationProtocol_X2_SETUP_REQUEST:
|
||||
rmrMsgType := rmrCgo.RIC_X2_SETUP_REQ
|
||||
request := models.NewE2RequestMessage(nodebInfo.RanName /*tid*/, nodebInfo.Ip, uint16(nodebInfo.Port), nodebInfo.RanName, e2pdus.PackedX2setupRequest)
|
||||
return rmrMsgType, request, nil
|
||||
case entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST:
|
||||
rmrMsgType := rmrCgo.RIC_ENDC_X2_SETUP_REQ
|
||||
request := models.NewE2RequestMessage(nodebInfo.RanName /*tid*/, nodebInfo.Ip, uint16(nodebInfo.Port), nodebInfo.RanName, e2pdus.PackedEndcX2setupRequest)
|
||||
return rmrMsgType, request, nil
|
||||
}
|
||||
|
||||
m.logger.Errorf("#RanSetupManager.prepareSetupRequest - Unsupported nodebInfo.E2ApplicationProtocol %d ", nodebInfo.E2ApplicationProtocol)
|
||||
return 0, nil, e2managererrors.NewInternalError()
|
||||
}
|
||||
|
||||
// ExecuteSetup updates the connection status and number of attempts in the nodebInfo and send an endc/x2 setup request to establish a connection with the RAN
|
||||
func (m *RanSetupManager) ExecuteSetup(nodebInfo *entities.NodebInfo, status entities.ConnectionStatus) error {
|
||||
|
||||
// Update retries and connection status
|
||||
if err := m.updateConnectionStatus(nodebInfo, status); err != nil {
|
||||
return e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
// Build the endc/x2 setup request
|
||||
rmrMsgType, request, err := m.prepareSetupRequest(nodebInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Send the endc/x2 setup request
|
||||
var xAction []byte
|
||||
var msgSrc unsafe.Pointer
|
||||
msg := models.NewRmrMessage(rmrMsgType, nodebInfo.RanName, request.GetMessageAsBytes(m.logger), xAction, msgSrc)
|
||||
|
||||
err = m.rmrSender.Send(msg)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#RanSetupManager.ExecuteSetup - failed sending setup request to RMR: %s", err)
|
||||
|
||||
err := m.updateConnectionStatusDisconnected(nodebInfo)
|
||||
|
||||
// Decrement retries and connection status (disconnected)
|
||||
if err != nil {
|
||||
return e2managererrors.NewRnibDbError()
|
||||
}
|
||||
|
||||
return e2managererrors.NewRmrError()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
219
setup/e2mgr/E2Manager/managers/ran_setup_manager_test.go
Normal file
219
setup/e2mgr/E2Manager/managers/ran_setup_manager_test.go
Normal file
@@ -0,0 +1,219 @@
|
||||
//
|
||||
// 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/e2managererrors"
|
||||
"e2mgr/e2pdus"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"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/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func initRanSetupManagerTest(t *testing.T) (*mocks.RmrMessengerMock, *mocks.RnibWriterMock, *RanSetupManager) {
|
||||
logger, err := logger.InitLogger(logger.DebugLevel)
|
||||
if err != nil {
|
||||
t.Errorf("#... - failed to initialize logger, error: %s", err)
|
||||
}
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
|
||||
|
||||
rmrMessengerMock := &mocks.RmrMessengerMock{}
|
||||
rmrSender := initRmrSender(rmrMessengerMock, logger)
|
||||
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
ranSetupManager := NewRanSetupManager(logger, rmrSender, rnibDataService)
|
||||
return rmrMessengerMock, writerMock, ranSetupManager
|
||||
}
|
||||
|
||||
func TestExecuteSetupConnectingX2Setup(t *testing.T) {
|
||||
rmrMessengerMock, writerMock, mgr := initRanSetupManagerTest(t)
|
||||
|
||||
ranName := "test1"
|
||||
|
||||
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
var rnibErr error
|
||||
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
|
||||
|
||||
payload := e2pdus.PackedX2setupRequest
|
||||
xAction := []byte(ranName)
|
||||
var msgSrc unsafe.Pointer
|
||||
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction, msgSrc)
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
|
||||
|
||||
if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err != nil {
|
||||
t.Errorf("want: success, got: error: %s", err)
|
||||
}
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
|
||||
rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
|
||||
}
|
||||
|
||||
func TestExecuteSetupConnectingEndcX2Setup(t *testing.T) {
|
||||
rmrMessengerMock, writerMock, mgr := initRanSetupManagerTest(t)
|
||||
|
||||
ranName := "test1"
|
||||
|
||||
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
|
||||
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
|
||||
var rnibErr error
|
||||
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
|
||||
|
||||
payload := e2pdus.PackedEndcX2setupRequest
|
||||
xAction := []byte(ranName)
|
||||
var msgSrc unsafe.Pointer
|
||||
msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction, msgSrc)
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
|
||||
|
||||
if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err != nil {
|
||||
t.Errorf("want: success, got: error: %s", err)
|
||||
}
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
|
||||
rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
|
||||
}
|
||||
|
||||
func TestExecuteSetupDisconnected(t *testing.T) {
|
||||
rmrMessengerMock, writerMock, mgr := initRanSetupManagerTest(t)
|
||||
|
||||
ranName := "test1"
|
||||
|
||||
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
var argNodebDisconnected = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
var rnibErr error
|
||||
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
|
||||
writerMock.On("UpdateNodebInfo", argNodebDisconnected).Return(rnibErr)
|
||||
|
||||
payload := []byte{0}
|
||||
xAction := []byte(ranName)
|
||||
var msgSrc unsafe.Pointer
|
||||
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction, msgSrc)
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, fmt.Errorf("send failure"))
|
||||
|
||||
if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
|
||||
t.Errorf("want: failure, got: success")
|
||||
}
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
|
||||
rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
|
||||
}
|
||||
|
||||
func TestExecuteSetupConnectingRnibError(t *testing.T) {
|
||||
rmrMessengerMock, writerMock, mgr := initRanSetupManagerTest(t)
|
||||
|
||||
ranName := "test1"
|
||||
|
||||
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
var argNodebDisconnected = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
var rnibErr = common.NewInternalError(fmt.Errorf("DB error"))
|
||||
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
|
||||
writerMock.On("UpdateNodebInfo", argNodebDisconnected).Return(rnibErr)
|
||||
|
||||
payload := []byte{0}
|
||||
xAction := []byte(ranName)
|
||||
var msgSrc unsafe.Pointer
|
||||
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction, msgSrc)
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, fmt.Errorf("send failure"))
|
||||
|
||||
if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
|
||||
t.Errorf("want: failure, got: success")
|
||||
} else {
|
||||
assert.IsType(t, e2managererrors.NewRnibDbError(), err)
|
||||
}
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
|
||||
rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
|
||||
}
|
||||
|
||||
func TestExecuteSetupDisconnectedRnibError(t *testing.T) {
|
||||
rmrMessengerMock, writerMock, mgr := initRanSetupManagerTest(t)
|
||||
|
||||
ranName := "test1"
|
||||
|
||||
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
var argNodebDisconnected = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
var rnibErr error
|
||||
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
|
||||
writerMock.On("UpdateNodebInfo", argNodebDisconnected).Return(common.NewInternalError(fmt.Errorf("DB error")))
|
||||
|
||||
payload := []byte{0}
|
||||
xAction := []byte(ranName)
|
||||
var msgSrc unsafe.Pointer
|
||||
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction, msgSrc)
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, fmt.Errorf("send failure"))
|
||||
|
||||
if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
|
||||
t.Errorf("want: failure, got: success")
|
||||
} else {
|
||||
assert.IsType(t, e2managererrors.NewRnibDbError(), err)
|
||||
}
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
|
||||
rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
|
||||
}
|
||||
|
||||
func TestExecuteSetupUnsupportedProtocol(t *testing.T) {
|
||||
rmrMessengerMock, writerMock, mgr := initRanSetupManagerTest(t)
|
||||
|
||||
ranName := "test1"
|
||||
|
||||
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_UNKNOWN_E2_APPLICATION_PROTOCOL}
|
||||
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_UNKNOWN_E2_APPLICATION_PROTOCOL}
|
||||
var rnibErr error
|
||||
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
|
||||
|
||||
payload := e2pdus.PackedX2setupRequest
|
||||
xAction := []byte(ranName)
|
||||
var msgSrc unsafe.Pointer
|
||||
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction, msgSrc)
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
|
||||
|
||||
if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
|
||||
t.Errorf("want: error, got: success")
|
||||
}
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
|
||||
rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
|
||||
}
|
||||
|
||||
func initLog(t *testing.T) *logger.Logger {
|
||||
log, err := logger.InitLogger(logger.InfoLevel)
|
||||
if err != nil {
|
||||
t.Errorf("#initLog test - failed to initialize logger, error: %s", err)
|
||||
}
|
||||
return log
|
||||
}
|
62
setup/e2mgr/E2Manager/managers/ran_status_change_manager.go
Normal file
62
setup/e2mgr/E2Manager/managers/ran_status_change_manager.go
Normal file
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// 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/enums"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/models"
|
||||
"e2mgr/services/rmrsender"
|
||||
"encoding/json"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type RanStatusChangeManager struct {
|
||||
logger *logger.Logger
|
||||
rmrSender *rmrsender.RmrSender
|
||||
}
|
||||
|
||||
func NewRanStatusChangeManager(logger *logger.Logger, rmrSender *rmrsender.RmrSender) *RanStatusChangeManager {
|
||||
return &RanStatusChangeManager{
|
||||
logger: logger,
|
||||
rmrSender: rmrSender,
|
||||
}
|
||||
}
|
||||
|
||||
type IRanStatusChangeManager interface {
|
||||
Execute(msgType int, msgDirection enums.MessageDirection, nodebInfo *entities.NodebInfo) error
|
||||
}
|
||||
|
||||
func (m *RanStatusChangeManager) Execute(msgType int, msgDirection enums.MessageDirection, nodebInfo *entities.NodebInfo) error {
|
||||
|
||||
resourceStatusPayload := models.NewResourceStatusPayload(nodebInfo.NodeType, msgDirection)
|
||||
resourceStatusJson, err := json.Marshal(resourceStatusPayload)
|
||||
|
||||
if err != nil {
|
||||
m.logger.Errorf("#RanStatusChangeManager.Execute - RAN name: %s - Error marshaling resource status payload: %v", nodebInfo.RanName, err)
|
||||
return err
|
||||
}
|
||||
|
||||
var xAction []byte
|
||||
var msgSrc unsafe.Pointer
|
||||
rmrMessage := models.NewRmrMessage(msgType, nodebInfo.RanName, resourceStatusJson, xAction, msgSrc)
|
||||
return m.rmrSender.Send(rmrMessage)
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// 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/enums"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services/rmrsender"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func initRanStatusChangeManagerTest(t *testing.T) (*logger.Logger, *mocks.RmrMessengerMock, *rmrsender.RmrSender) {
|
||||
logger, err := logger.InitLogger(logger.DebugLevel)
|
||||
if err != nil {
|
||||
t.Fatalf("#initStatusChangeManagerTest - failed to initialize logger, error: %s", err)
|
||||
}
|
||||
|
||||
rmrMessengerMock := &mocks.RmrMessengerMock{}
|
||||
rmrSender := initRmrSender(rmrMessengerMock, logger)
|
||||
|
||||
return logger, rmrMessengerMock, rmrSender
|
||||
}
|
||||
|
||||
func TestMarshalFailure(t *testing.T) {
|
||||
logger, _, rmrSender := initRanStatusChangeManagerTest(t)
|
||||
m := NewRanStatusChangeManager(logger, rmrSender)
|
||||
|
||||
nodebInfo := entities.NodebInfo{}
|
||||
err := m.Execute(123, 4, &nodebInfo)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestMarshalSuccess(t *testing.T) {
|
||||
logger, rmrMessengerMock, rmrSender := initRanStatusChangeManagerTest(t)
|
||||
m := NewRanStatusChangeManager(logger, rmrSender)
|
||||
|
||||
nodebInfo := entities.NodebInfo{NodeType: entities.Node_ENB}
|
||||
var err error
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(&rmrCgo.MBuf{}, err)
|
||||
err = m.Execute(rmrCgo.RAN_CONNECTED, enums.RIC_TO_RAN, &nodebInfo)
|
||||
|
||||
assert.Nil(t, err)
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// 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/converters"
|
||||
"e2mgr/logger"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
)
|
||||
|
||||
type X2SetupFailureResponseManager struct {
|
||||
converter converters.IX2SetupFailureResponseConverter
|
||||
}
|
||||
|
||||
func NewX2SetupFailureResponseManager(converter converters.IX2SetupFailureResponseConverter) *X2SetupFailureResponseManager {
|
||||
return &X2SetupFailureResponseManager{
|
||||
converter: converter,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *X2SetupFailureResponseManager) PopulateNodebByPdu(logger *logger.Logger, nbIdentity *entities.NbIdentity, nodebInfo *entities.NodebInfo, payload []byte) error {
|
||||
|
||||
failureResponse, err := m.converter.UnpackX2SetupFailureResponseAndExtract(payload)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("#X2SetupFailureResponseManager.PopulateNodebByPdu - RAN name: %s - Unpack and extract failed. Error: %v", nodebInfo.RanName, err)
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Infof("#X2SetupFailureResponseManager.PopulateNodebByPdu - RAN name: %s - Unpacked payload and extracted protobuf successfully", nodebInfo.RanName)
|
||||
|
||||
nodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED_SETUP_FAILED
|
||||
nodebInfo.SetupFailure = failureResponse
|
||||
nodebInfo.FailureType = entities.Failure_X2_SETUP_FAILURE
|
||||
return nil
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// 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/converters"
|
||||
"e2mgr/tests"
|
||||
"fmt"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPopulateX2NodebByPduFailure(t *testing.T) {
|
||||
logger := tests.InitLog(t)
|
||||
nodebInfo := &entities.NodebInfo{}
|
||||
nodebIdentity := &entities.NbIdentity{}
|
||||
handler := NewX2SetupFailureResponseManager(converters.NewX2SetupFailureResponseConverter(logger))
|
||||
err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createRandomPayload())
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestPopulateX2NodebByPduSuccess(t *testing.T) {
|
||||
logger := tests.InitLog(t)
|
||||
nodebInfo := &entities.NodebInfo{}
|
||||
nodebIdentity := &entities.NbIdentity{}
|
||||
handler := NewX2SetupFailureResponseManager(converters.NewX2SetupFailureResponseConverter(logger))
|
||||
err := handler.PopulateNodebByPdu(logger, nodebIdentity, nodebInfo, createX2SetupFailureResponsePayload(t))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, entities.ConnectionStatus_CONNECTED_SETUP_FAILED, nodebInfo.ConnectionStatus)
|
||||
assert.Equal(t, entities.Failure_X2_SETUP_FAILURE, nodebInfo.FailureType)
|
||||
|
||||
}
|
||||
|
||||
func createX2SetupFailureResponsePayload(t *testing.T) []byte {
|
||||
packedPdu := "4006001a0000030005400200000016400100001140087821a00000008040"
|
||||
var payload []byte
|
||||
_, err := fmt.Sscanf(packedPdu, "%x", &payload)
|
||||
if err != nil {
|
||||
t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
|
||||
}
|
||||
return payload
|
||||
}
|
57
setup/e2mgr/E2Manager/managers/x2_setup_response_manager.go
Normal file
57
setup/e2mgr/E2Manager/managers/x2_setup_response_manager.go
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// 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/converters"
|
||||
"e2mgr/logger"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
)
|
||||
|
||||
type X2SetupResponseManager struct {
|
||||
converter converters.IX2SetupResponseConverter
|
||||
}
|
||||
|
||||
func NewX2SetupResponseManager(converter converters.IX2SetupResponseConverter) *X2SetupResponseManager {
|
||||
return &X2SetupResponseManager{
|
||||
converter: converter,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *X2SetupResponseManager) PopulateNodebByPdu(logger *logger.Logger, nbIdentity *entities.NbIdentity, nodebInfo *entities.NodebInfo, payload []byte) error {
|
||||
|
||||
enbId, enb, err := m.converter.UnpackX2SetupResponseAndExtract(payload)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("#X2SetupResponseManager.PopulateNodebByPdu - RAN name: %s - Unpack and extract failed. %v", nodebInfo.RanName, err)
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Infof("#X2SetupResponseManager.PopulateNodebByPdu - RAN name: %s - Unpacked payload and extracted protobuf successfully", nodebInfo.RanName)
|
||||
|
||||
nbIdentity.GlobalNbId = enbId
|
||||
nodebInfo.GlobalNbId = enbId
|
||||
nodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED
|
||||
nodebInfo.NodeType = entities.Node_ENB
|
||||
nodebInfo.Configuration = &entities.NodebInfo_Enb{Enb: enb}
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user