First commit

This commit is contained in:
Leonardo Bonati
2021-12-08 20:17:46 +00:00
commit 60dffad583
2923 changed files with 463894 additions and 0 deletions

View File

@@ -0,0 +1,224 @@
//
// 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 httpmsghandlers
import "C"
import (
"e2mgr/clients"
"e2mgr/configuration"
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"time"
)
type DeleteAllRequestHandler struct {
rnibDataService services.RNibDataService
rmrSender *rmrsender.RmrSender
config *configuration.Configuration
logger *logger.Logger
e2tInstancesManager managers.IE2TInstancesManager
rmClient clients.IRoutingManagerClient
}
const PartialSuccessDueToRmErrorMessage = "Operation succeeded except for routing manager outbound call"
func NewDeleteAllRequestHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rnibDataService services.RNibDataService, e2tInstancesManager managers.IE2TInstancesManager, rmClient clients.IRoutingManagerClient) *DeleteAllRequestHandler {
return &DeleteAllRequestHandler{
logger: logger,
rnibDataService: rnibDataService,
rmrSender: rmrSender,
config: config,
e2tInstancesManager: e2tInstancesManager,
rmClient: rmClient,
}
}
func (h *DeleteAllRequestHandler) Handle(request models.Request) (models.IResponse, error) {
h.logger.Infof("#DeleteAllRequestHandler.Handle - handling shutdown request")
e2tAddresses, err := h.e2tInstancesManager.GetE2TAddresses()
if err != nil {
return nil, err
}
if len(e2tAddresses) == 0 {
err, _ = h.updateNodebs(h.updateNodebInfoForceShutdown)
return nil, err
}
dissocErr := h.rmClient.DissociateAllRans(e2tAddresses)
if dissocErr != nil {
h.logger.Warnf("#DeleteAllRequestHandler.Handle - routing manager failure. continue flow.")
}
err, updatedAtLeastOnce := h.updateNodebs(h.updateNodebInfoShuttingDown)
if err != nil {
return nil, err
}
err = h.e2tInstancesManager.ClearRansOfAllE2TInstances()
if err != nil {
return nil, err
}
rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
err = h.rmrSender.Send(&rmrMessage)
if err != nil {
h.logger.Errorf("#DeleteAllRequestHandler.Handle - failed to send sctp clear all message to RMR: %s", err)
return nil, e2managererrors.NewRmrError()
}
if !updatedAtLeastOnce {
h.logger.Infof("#DeleteAllRequestHandler.Handle - DB wasn't updated, not activating timer")
if dissocErr != nil {
return models.NewRedButtonPartialSuccessResponseModel(PartialSuccessDueToRmErrorMessage), nil
}
return nil, nil
}
time.Sleep(time.Duration(h.config.BigRedButtonTimeoutSec) * time.Second)
h.logger.Infof("#DeleteAllRequestHandler.Handle - timer expired")
err, _ = h.updateNodebs(h.updateNodebInfoShutDown)
if err != nil {
return nil, err
}
if dissocErr != nil {
return models.NewRedButtonPartialSuccessResponseModel(PartialSuccessDueToRmErrorMessage), nil
}
return nil, nil
}
func (h *DeleteAllRequestHandler) updateNodebs(updateCb func(node *entities.NodebInfo) (error, bool)) (error, bool) {
nbIdentityList, err := h.rnibDataService.GetListNodebIds()
if err != nil {
h.logger.Errorf("#DeleteAllRequestHandler.updateNodebs - failed to get nodes list from rNib. Error: %s", err)
return e2managererrors.NewRnibDbError(), false
}
updatedAtLeastOnce := false
for _, nbIdentity := range nbIdentityList {
node, err := h.rnibDataService.GetNodeb(nbIdentity.InventoryName)
if err != nil {
_, ok := err.(*common.ResourceNotFoundError)
if !ok {
h.logger.Errorf("#DeleteAllRequestHandler.updateNodebs - failed to get nodeB entity for ran name: %s from rNib. error: %s", nbIdentity.InventoryName, err)
return e2managererrors.NewRnibDbError(), false
}
continue
}
err, updated := updateCb(node)
if err != nil {
return err, false
}
if updated {
updatedAtLeastOnce = true
}
}
return nil, updatedAtLeastOnce
}
func (h *DeleteAllRequestHandler) updateNodebInfoForceShutdown(node *entities.NodebInfo) (error, bool) {
err := h.updateNodebInfo(node, entities.ConnectionStatus_SHUT_DOWN, true)
if err != nil {
return err, false
}
return nil, true
}
func (h *DeleteAllRequestHandler) updateNodebInfoShuttingDown(node *entities.NodebInfo) (error, bool) {
if node.ConnectionStatus == entities.ConnectionStatus_SHUT_DOWN {
return nil, false
}
err := h.updateNodebInfo(node, entities.ConnectionStatus_SHUTTING_DOWN, true)
if err != nil {
return err, false
}
return nil, true
}
func (h *DeleteAllRequestHandler) updateNodebInfoShutDown(node *entities.NodebInfo) (error, bool) {
if node.ConnectionStatus == entities.ConnectionStatus_SHUT_DOWN {
return nil, false
}
if node.ConnectionStatus != entities.ConnectionStatus_SHUTTING_DOWN {
h.logger.Warnf("#DeleteAllRequestHandler.updateNodebInfoShutDown - RAN name: %s - ignore, status is not Shutting Down", node.RanName)
return nil, false
}
err := h.updateNodebInfo(node, entities.ConnectionStatus_SHUT_DOWN, false)
if err != nil {
return err, false
}
return nil, true
}
func (h *DeleteAllRequestHandler) updateNodebInfo(node *entities.NodebInfo, connectionStatus entities.ConnectionStatus, resetAssociatedE2TAddress bool) error {
node.ConnectionStatus = connectionStatus
if resetAssociatedE2TAddress {
node.AssociatedE2TInstanceAddress = ""
}
err := h.rnibDataService.UpdateNodebInfo(node)
if err != nil {
h.logger.Errorf("#DeleteAllRequestHandler.updateNodebInfo - RAN name: %s - failed updating nodeB entity in rNib. error: %s", node.RanName, err)
return e2managererrors.NewRnibDbError()
}
h.logger.Infof("#DeleteAllRequestHandler.updateNodebInfo - RAN name: %s, connection status: %s", node.RanName, connectionStatus)
return nil
}

View File

@@ -0,0 +1,473 @@
//
// 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 httpmsghandlers
import (
"bytes"
"e2mgr/clients"
"e2mgr/configuration"
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"e2mgr/tests"
"encoding/json"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"io/ioutil"
"net/http"
"testing"
)
func setupDeleteAllRequestHandlerTest(t *testing.T) (*DeleteAllRequestHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.HttpClientMock) {
log := initLog(t)
config := configuration.ParseConfiguration()
config.BigRedButtonTimeoutSec = 1
config.RoutingManager.BaseUrl = BaseRMUrl
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := getRmrSender(rmrMessengerMock, log)
e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, log)
httpClientMock := &mocks.HttpClientMock{}
rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
handler := NewDeleteAllRequestHandler(log, rmrSender, config, rnibDataService, e2tInstancesManager, rmClient)
return handler, readerMock, writerMock, rmrMessengerMock, httpClientMock
}
func mapE2TAddressesToE2DataList(e2tAddresses []string) models.RoutingManagerE2TDataList {
e2tDataList := make(models.RoutingManagerE2TDataList, len(e2tAddresses))
for i, v := range e2tAddresses {
e2tDataList[i] = models.NewRoutingManagerE2TData(v)
}
return e2tDataList
}
func mockHttpClientDissociateAllRans(httpClientMock *mocks.HttpClientMock, e2tAddresses []string, ok bool) {
data := mapE2TAddressesToE2DataList(e2tAddresses)
marshaled, _ := json.Marshal(data)
body := bytes.NewBuffer(marshaled)
url := BaseRMUrl + clients.DissociateRanE2TInstanceApiSuffix
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
var status int
if ok {
status = http.StatusOK
} else {
status = http.StatusBadRequest
}
httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: status, Body: respBody}, nil)
}
func TestGetE2TAddressesFailure(t *testing.T) {
h, readerMock, _, _, _ := setupDeleteAllRequestHandlerTest(t)
readerMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
}
func TestOneRanGetE2TAddressesEmptyList(t *testing.T) {
h, readerMock, writerMock, _, _ := setupDeleteAllRequestHandlerTest(t)
readerMock.On("GetE2TAddresses").Return([]string{}, nil)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
_, err := h.Handle(nil)
assert.Nil(t, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestTwoRansGetE2TAddressesEmptyListOneGetNodebFailure(t *testing.T) {
h, readerMock, writerMock, _, _ := setupDeleteAllRequestHandlerTest(t)
readerMock.On("GetE2TAddresses").Return([]string{}, nil)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
var nb2 *entities.NodebInfo
readerMock.On("GetNodeb", "RanName_2").Return(nb2, common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t,&e2managererrors.RnibDbError{}, err)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
readerMock.AssertExpectations(t)
}
func TestTwoRansGetE2TAddressesEmptyListOneUpdateNodebInfoFailure(t *testing.T) {
h, readerMock, writerMock, _, _ := setupDeleteAllRequestHandlerTest(t)
readerMock.On("GetE2TAddresses").Return([]string{}, nil)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
updatedNb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb2).Return(common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t,&e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestOneRanDissociateSucceedsTryShuttingDownFailure(t *testing.T) {
h, readerMock, writerMock, _, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true)
nbIdentityList := []*entities.NbIdentity{}
readerMock.On("GetListNodebIds").Return(nbIdentityList, common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestOneRanDissociateFailsTryShuttingDownFailure(t *testing.T) {
h, readerMock, writerMock, _, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, false)
nbIdentityList := []*entities.NbIdentity{}
readerMock.On("GetListNodebIds").Return(nbIdentityList, common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestOneRanTryShuttingDownSucceedsClearFails(t *testing.T) {
h, readerMock, writerMock, _, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{}, common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSendFails(t *testing.T) {
h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}}
readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil)
updatedE2tInstance := e2tInstance
updatedE2tInstance.AssociatedRanList = []string{}
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, e2managererrors.NewRmrError())
_, err := h.Handle(nil)
assert.IsType(t, &e2managererrors.RmrError{}, err)
rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func testTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdown(t *testing.T, partial bool) {
h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, !partial)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN}
nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1", "RanName_2"}}
readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil)
updatedE2tInstance := e2tInstance
updatedE2tInstance.AssociatedRanList = []string{}
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil)
resp, err := h.Handle(nil)
assert.Nil(t, err)
if partial {
assert.IsType(t, &models.RedButtonPartialSuccessResponseModel{}, resp)
} else {
assert.Nil(t, resp)
}
rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdownSuccess(t *testing.T) {
testTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdown(t, false)
}
func TestTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdownPartialSuccess(t *testing.T) {
testTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdown(t, true)
}
//func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsAlreadyShutdown(t *testing.T) {
// h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
// e2tAddresses := []string{E2TAddress}
// readerMock.On("GetE2TAddresses").Return(e2tAddresses , nil)
// mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses ,true)
// nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
// nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
// readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
// updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
// writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
// readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
// e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}}
// readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance }, nil)
// updatedE2tInstance := e2tInstance
// updatedE2tInstance.AssociatedRanList = []string{}
// writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
//
// rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
// mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction)
// rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil)
//
// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
// nbAfterTimer := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
// readerMock.On("GetNodeb", /*"RanName_1"*/mock.Anything).Return(nbAfterTimer , nil) // Since this is a second call with same arguments we send mock.Anything due to mock limitations
// _, err := h.Handle(nil)
// assert.Nil(t, err)
// rmrMessengerMock.AssertCalled(t, "SendMsg",mbuf, true)
// readerMock.AssertExpectations(t)
// writerMock.AssertExpectations(t)
// writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
//}
//func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDownUpdateFailure(t *testing.T) {
// h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
// e2tAddresses := []string{E2TAddress}
// readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
// mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true)
// nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
// //nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
// //readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
// updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
// writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
// readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
// e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}}
// readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil)
// updatedE2tInstance := e2tInstance
// updatedE2tInstance.AssociatedRanList = []string{}
// writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
//
// rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
// mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction)
// rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil)
//
// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
// readerMock.On("GetNodeb", "RanName_1").Return(updatedNb1, nil)
// updatedNb2 := *updatedNb1
// updatedNb2.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
// writerMock.On("UpdateNodebInfo", &updatedNb2).Return(common.NewInternalError(errors.New("error")))
// _, err := h.Handle(nil)
// assert.IsType(t,&e2managererrors.RnibDbError{}, err)
// rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true)
// readerMock.AssertExpectations(t)
// writerMock.AssertExpectations(t)
//}
func testOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDown(t *testing.T, partial bool) {
h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, !partial)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
//nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
//readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}}
readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil)
updatedE2tInstance := e2tInstance
updatedE2tInstance.AssociatedRanList = []string{}
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil)
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
readerMock.On("GetNodeb", "RanName_1").Return(updatedNb1, nil)
updatedNb2 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb2).Return(nil)
_, err := h.Handle(nil)
assert.Nil(t, err)
rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
}
func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDownSuccess (t *testing.T) {
testOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDown(t, false)
}
func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDownPartialSuccess (t *testing.T) {
testOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDown(t, true)
}
func TestSuccessTwoE2TInstancesSixRans(t *testing.T) {
h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress, E2TAddress2}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}, {InventoryName: "RanName_3"}, {InventoryName: "RanName_4"}, {InventoryName: "RanName_5"}, {InventoryName: "RanName_6"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
//nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
//readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
//nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
//readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
//nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
//readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil)
//nb4 := &entities.NodebInfo{RanName: "RanName_4", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress2}
//readerMock.On("GetNodeb", "RanName_4").Return(nb4, nil)
//nb5 := &entities.NodebInfo{RanName: "RanName_5", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress2}
//readerMock.On("GetNodeb", "RanName_5").Return(nb5, nil)
//nb6 := &entities.NodebInfo{RanName: "RanName_6", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress2}
//readerMock.On("GetNodeb", "RanName_6").Return(nb6, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
updatedNb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb2).Return(nil)
updatedNb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb3).Return(nil)
updatedNb4 := &entities.NodebInfo{RanName: "RanName_4", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb4).Return(nil)
updatedNb5 := &entities.NodebInfo{RanName: "RanName_5", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb5).Return(nil)
updatedNb6 := &entities.NodebInfo{RanName: "RanName_6", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb6).Return(nil)
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1", "RanName_2", "RanName_3"}}
e2tInstance2 := entities.E2TInstance{Address: E2TAddress2, AssociatedRanList: []string{"RanName_4", "RanName_5", "RanName_6"}}
readerMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{&e2tInstance, &e2tInstance2}, nil)
updatedE2tInstance := e2tInstance
updatedE2tInstance.AssociatedRanList = []string{}
updatedE2tInstance2 := e2tInstance2
updatedE2tInstance2.AssociatedRanList = []string{}
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
writerMock.On("SaveE2TInstance", &updatedE2tInstance2).Return(nil)
rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil)
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
readerMock.On("GetNodeb", "RanName_1").Return(updatedNb1, nil)
readerMock.On("GetNodeb", "RanName_2").Return(updatedNb2, nil)
readerMock.On("GetNodeb", "RanName_3").Return(updatedNb3, nil)
readerMock.On("GetNodeb", "RanName_4").Return(updatedNb4, nil)
readerMock.On("GetNodeb", "RanName_5").Return(updatedNb5, nil)
readerMock.On("GetNodeb", "RanName_6").Return(updatedNb6, nil)
updatedNb1AfterTimer := *updatedNb1
updatedNb1AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb1AfterTimer).Return(nil)
updatedNb2AfterTimer := *updatedNb2
updatedNb2AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb2AfterTimer).Return(nil)
updatedNb3AfterTimer := *updatedNb3
updatedNb3AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb3AfterTimer).Return(nil)
updatedNb4AfterTimer := *updatedNb4
updatedNb4AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb4AfterTimer).Return(nil)
updatedNb5AfterTimer := *updatedNb5
updatedNb5AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb5AfterTimer).Return(nil)
updatedNb6AfterTimer := *updatedNb6
updatedNb6AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb6AfterTimer).Return(nil)
_, err := h.Handle(nil)
assert.Nil(t, err)
rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 12)
}
func initLog(t *testing.T) *logger.Logger {
log, err := logger.InitLogger(logger.DebugLevel)
if err != nil {
t.Errorf("#initLog test - failed to initialize logger, error: %s", err)
}
return log
}
func getRmrSender(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)
}

View 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 httpmsghandlers
import (
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
)
type GetE2TInstancesRequestHandler struct {
e2tInstancesManager managers.IE2TInstancesManager
logger *logger.Logger
}
func NewGetE2TInstancesRequestHandler(logger *logger.Logger, e2tInstancesManager managers.IE2TInstancesManager) *GetE2TInstancesRequestHandler {
return &GetE2TInstancesRequestHandler{
logger: logger,
e2tInstancesManager: e2tInstancesManager,
}
}
func (h *GetE2TInstancesRequestHandler) Handle(request models.Request) (models.IResponse, error) {
e2tInstances, err := h.e2tInstancesManager.GetE2TInstances()
if err != nil {
h.logger.Errorf("#GetE2TInstancesRequestHandler.Handle - Error fetching E2T instances from rNib: %s", err)
return nil, err
}
mapped := make([]*models.E2TInstanceResponseModel, len(e2tInstances))
for i, v := range e2tInstances {
mapped[i] = models.NewE2TInstanceResponseModel(v.Address, v.AssociatedRanList)
}
return models.E2TInstancesResponse(mapped), nil
}

View File

@@ -0,0 +1,78 @@
//
// 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 httpmsghandlers
import (
"e2mgr/configuration"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/services"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"testing"
)
const E2TAddress2 = "10.0.2.15:3213"
func setupGetE2TInstancesListRequestHandlerTest(t *testing.T) (*GetE2TInstancesRequestHandler, *mocks.RnibReaderMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, log)
handler := NewGetE2TInstancesRequestHandler(log, e2tInstancesManager)
return handler, readerMock
}
func TestGetE2TInstancesFailure(t *testing.T) {
handler, rnibReaderMock := setupGetE2TInstancesListRequestHandlerTest(t)
rnibReaderMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("error")))
_, err := handler.Handle(nil)
assert.NotNil(t, err)
}
func TestGetE2TInstancesNoInstances(t *testing.T) {
handler, rnibReaderMock := setupGetE2TInstancesListRequestHandlerTest(t)
rnibReaderMock.On("GetE2TAddresses").Return([]string{}, nil)
resp, err := handler.Handle(nil)
assert.Nil(t, err)
assert.IsType(t, models.E2TInstancesResponse{}, resp)
assert.Len(t, resp, 0)
}
func TestGetE2TInstancesSuccess(t *testing.T) {
handler, rnibReaderMock := setupGetE2TInstancesListRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress, E2TAddress2}
rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"test1", "test2"}}
e2tInstance2 := entities.E2TInstance{Address: E2TAddress2, AssociatedRanList: []string{"test3", "test4", "test5"}}
rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{&e2tInstance, &e2tInstance2}, nil)
resp, err := handler.Handle(nil)
assert.Nil(t, err)
assert.IsType(t, models.E2TInstancesResponse{}, resp)
assert.Len(t, resp, 2)
}

View File

@@ -0,0 +1,52 @@
//
// 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 httpmsghandlers
import (
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/models"
"e2mgr/services"
)
type GetNodebIdListRequestHandler struct {
rNibDataService services.RNibDataService
logger *logger.Logger
}
func NewGetNodebIdListRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService) *GetNodebIdListRequestHandler {
return &GetNodebIdListRequestHandler{
logger: logger,
rNibDataService: rNibDataService,
}
}
func (handler *GetNodebIdListRequestHandler) Handle(request models.Request) (models.IResponse, error) {
nodebIdList, err := handler.rNibDataService.GetListNodebIds()
if err != nil {
handler.logger.Errorf("#GetNodebIdListRequestHandler.Handle - Error fetching Nodeb Identity list from rNib: %v", err)
return nil, e2managererrors.NewRnibDbError()
}
return models.NewGetNodebIdListResponse(nodebIdList), nil
}

View 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 httpmsghandlers
import (
"e2mgr/configuration"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/services"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"testing"
)
func setupGetNodebIdListRequestHandlerTest(t *testing.T) (*GetNodebIdListRequestHandler, *mocks.RnibReaderMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
handler := NewGetNodebIdListRequestHandler(log, rnibDataService)
return handler, readerMock
}
func TestHandleGetNodebIdListSuccess(t *testing.T) {
handler, readerMock := setupGetNodebIdListRequestHandlerTest(t)
var rnibError error
readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, rnibError)
response, err := handler.Handle(nil)
assert.Nil(t, err)
assert.NotNil(t, response)
assert.IsType(t, &models.GetNodebIdListResponse{}, response)
}
func TestHandleGetNodebIdListFailure(t *testing.T) {
handler, readerMock := setupGetNodebIdListRequestHandlerTest(t)
var nodebIdList []*entities.NbIdentity
readerMock.On("GetListNodebIds").Return(nodebIdList, common.NewInternalError(errors.New("#reader.GetListNodebIds - Internal Error")))
response, err := handler.Handle(nil)
assert.NotNil(t, err)
assert.Nil(t, response)
}

View 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 httpmsghandlers
import (
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/models"
"e2mgr/services"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
)
type GetNodebRequestHandler struct {
rNibDataService services.RNibDataService
logger *logger.Logger
}
func NewGetNodebRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService) *GetNodebRequestHandler {
return &GetNodebRequestHandler{
logger: logger,
rNibDataService: rNibDataService,
}
}
func (handler *GetNodebRequestHandler) Handle(request models.Request) (models.IResponse, error) {
getNodebRequest := request.(models.GetNodebRequest)
ranName:= getNodebRequest.RanName
nodeb, err := handler.rNibDataService.GetNodeb(ranName)
if err != nil {
handler.logger.Errorf("#GetNodebRequestHandler.Handle - RAN name: %s - Error fetching RAN from rNib: %v", ranName, err)
return nil, rnibErrorToE2ManagerError(err)
}
return models.NewGetNodebResponse(nodeb), nil
}
func rnibErrorToE2ManagerError(err error) error {
_, ok := err.(*common.ResourceNotFoundError)
if ok {
return e2managererrors.NewResourceNotFoundError()
}
return e2managererrors.NewRnibDbError()
}

View File

@@ -0,0 +1,64 @@
//
// 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 httpmsghandlers
import (
"e2mgr/configuration"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/services"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"testing"
)
func setupGetNodebRequestHandlerTest(t *testing.T) (*GetNodebRequestHandler, *mocks.RnibReaderMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
handler := NewGetNodebRequestHandler(log, rnibDataService)
return handler, readerMock
}
func TestHandleGetNodebSuccess(t *testing.T) {
handler, readerMock := setupGetNodebRequestHandlerTest(t)
ranName := "test1"
var rnibError error
readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{RanName:ranName}, rnibError)
response, err := handler.Handle(models.GetNodebRequest{RanName: ranName})
assert.Nil(t, err)
assert.NotNil(t, response)
assert.IsType(t, &models.GetNodebResponse{}, response)
}
func TestHandleGetNodebFailure(t *testing.T) {
handler, readerMock := setupGetNodebRequestHandlerTest(t)
ranName := "test1"
var nodebInfo *entities.NodebInfo
readerMock.On("GetNodeb", ranName).Return(nodebInfo, common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")))
response, err := handler.Handle(models.GetNodebRequest{RanName: ranName})
assert.NotNil(t, err)
assert.Nil(t, response)
}

View File

@@ -0,0 +1,28 @@
//
// 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 httpmsghandlers
import (
"e2mgr/models"
)
type RequestHandler interface {
Handle(request models.Request) (models.IResponse, error)
}

View File

@@ -0,0 +1,221 @@
//
// 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 httpmsghandlers
import (
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
"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/go-ozzo/ozzo-validation"
"github.com/go-ozzo/ozzo-validation/is"
)
const (
X2SetupActivityName = "X2_SETUP"
EndcSetupActivityName = "ENDC_SETUP"
)
type SetupRequestHandler struct {
rNibDataService services.RNibDataService
logger *logger.Logger
ranSetupManager managers.IRanSetupManager
protocol entities.E2ApplicationProtocol
e2tAssociationManager *managers.E2TAssociationManager
e2tInstancesManager managers.IE2TInstancesManager
}
func NewSetupRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService,
ranSetupManager managers.IRanSetupManager, protocol entities.E2ApplicationProtocol, e2tInstancesManager managers.IE2TInstancesManager, e2tAssociationManager *managers.E2TAssociationManager) *SetupRequestHandler {
return &SetupRequestHandler{
logger: logger,
rNibDataService: rNibDataService,
ranSetupManager: ranSetupManager,
protocol: protocol,
e2tAssociationManager: e2tAssociationManager,
e2tInstancesManager: e2tInstancesManager,
}
}
func (h *SetupRequestHandler) Handle(request models.Request) (models.IResponse, error) {
setupRequest := request.(models.SetupRequest)
err := h.validateRequestDetails(setupRequest)
if err != nil {
return nil, err
}
nodebInfo, err := h.rNibDataService.GetNodeb(setupRequest.RanName)
if err != nil {
_, ok := err.(*common.ResourceNotFoundError)
if !ok {
h.logger.Errorf("#SetupRequestHandler.Handle - failed to get nodeB entity for ran name: %v from RNIB. Error: %s", setupRequest.RanName, err)
return nil, e2managererrors.NewRnibDbError()
}
result := h.connectNewRan(&setupRequest, h.protocol)
return nil, result
}
if nodebInfo.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithAssociatedE2TAddress - RAN: %s in wrong state (%s)", nodebInfo.RanName, entities.ConnectionStatus_name[int32(nodebInfo.ConnectionStatus)])
result := e2managererrors.NewWrongStateError(h.getActivityName(h.protocol), entities.ConnectionStatus_name[int32(nodebInfo.ConnectionStatus)])
return nil, result
}
if len(nodebInfo.AssociatedE2TInstanceAddress) != 0 {
result := h.connectExistingRanWithAssociatedE2TAddress(nodebInfo)
return nil, result
}
result := h.connectExistingRanWithoutAssociatedE2TAddress(nodebInfo)
return nil, result
}
func createInitialNodeInfo(requestDetails *models.SetupRequest, protocol entities.E2ApplicationProtocol) (*entities.NodebInfo, *entities.NbIdentity) {
nodebInfo := &entities.NodebInfo{
Ip: requestDetails.RanIp,
Port: uint32(requestDetails.RanPort),
ConnectionStatus: entities.ConnectionStatus_CONNECTING,
E2ApplicationProtocol: protocol,
RanName: requestDetails.RanName,
}
nbIdentity := &entities.NbIdentity{
InventoryName: requestDetails.RanName,
}
return nodebInfo, nbIdentity
}
func (h *SetupRequestHandler) connectExistingRanWithoutAssociatedE2TAddress(nodebInfo *entities.NodebInfo) error {
e2tAddress, err := h.e2tInstancesManager.SelectE2TInstance()
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - failed selecting E2T instance", nodebInfo.RanName)
if nodebInfo.ConnectionStatus == entities.ConnectionStatus_DISCONNECTED{
return err
}
nodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
updateError := h.rNibDataService.UpdateNodebInfo(nodebInfo)
if updateError != nil {
h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - failed updating nodeb. error: %s", nodebInfo.RanName, updateError)
}
return err
}
err = h.e2tAssociationManager.AssociateRan(e2tAddress, nodebInfo)
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - failed associating ran to e2t address %s. error: %s", nodebInfo.RanName, e2tAddress, err)
return err
}
h.logger.Infof("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - successfully updated nodeb in rNib", nodebInfo.RanName)
result := h.ranSetupManager.ExecuteSetup(nodebInfo, entities.ConnectionStatus_CONNECTING)
return result
}
func (h *SetupRequestHandler) connectExistingRanWithAssociatedE2TAddress(nodebInfo *entities.NodebInfo) error {
status := entities.ConnectionStatus_CONNECTING
if nodebInfo.ConnectionStatus == entities.ConnectionStatus_CONNECTED {
status = nodebInfo.ConnectionStatus
}
err := h.rNibDataService.UpdateNodebInfo(nodebInfo)
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithAssociatedE2TAddress - RAN name: %s - failed resetting connection attempts of RAN. error: %s", nodebInfo.RanName, err)
return e2managererrors.NewRnibDbError()
}
h.logger.Infof("#SetupRequestHandler.connectExistingRanWithAssociatedE2TAddress - RAN name: %s - successfully reset connection attempts of RAN", nodebInfo.RanName)
result := h.ranSetupManager.ExecuteSetup(nodebInfo, status)
return result
}
func (h *SetupRequestHandler) connectNewRan(request *models.SetupRequest, protocol entities.E2ApplicationProtocol) error {
e2tAddress, err := h.e2tInstancesManager.SelectE2TInstance()
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectNewRan - RAN name: %s - failed selecting E2T instance", request.RanName)
return err
}
nodebInfo, nodebIdentity := createInitialNodeInfo(request, protocol)
err = h.rNibDataService.SaveNodeb(nodebIdentity, nodebInfo)
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectNewRan - RAN name: %s - failed to save initial nodeb entity in RNIB. error: %s", request.RanName, err)
return e2managererrors.NewRnibDbError()
}
h.logger.Infof("#SetupRequestHandler.connectNewRan - RAN name: %s - initial nodeb entity was saved to rNib", request.RanName)
err = h.e2tAssociationManager.AssociateRan(e2tAddress, nodebInfo)
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectNewRan - RAN name: %s - failed associating ran to e2t address %s. error: %s", request.RanName, e2tAddress, err)
return err
}
result := h.ranSetupManager.ExecuteSetup(nodebInfo, entities.ConnectionStatus_CONNECTING)
return result
}
func (handler *SetupRequestHandler) validateRequestDetails(request models.SetupRequest) error {
if request.RanPort == 0 {
handler.logger.Errorf("#SetupRequestHandler.validateRequestDetails - validation failure: port cannot be zero")
return e2managererrors.NewRequestValidationError()
}
err := validation.ValidateStruct(&request,
validation.Field(&request.RanIp, validation.Required, is.IP),
validation.Field(&request.RanName, validation.Required),
)
if err != nil {
handler.logger.Errorf("#SetupRequestHandler.validateRequestDetails - validation failure, error: %v", err)
return e2managererrors.NewRequestValidationError()
}
return nil
}
func (handler *SetupRequestHandler) getActivityName(protocol entities.E2ApplicationProtocol) string {
if protocol == entities.E2ApplicationProtocol_X2_SETUP_REQUEST {
return X2SetupActivityName
}
return EndcSetupActivityName
}

View File

@@ -0,0 +1,462 @@
//
// 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 httpmsghandlers
import (
"bytes"
"e2mgr/clients"
"e2mgr/configuration"
"e2mgr/e2managererrors"
"e2mgr/e2pdus"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/rmrCgo"
"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"
"net/http"
"testing"
)
const E2TAddress = "10.0.2.15:8989"
const RanName = "test"
const BaseRMUrl = "http://10.10.2.15:12020/routingmanager"
func initSetupRequestTest(t *testing.T, protocol entities.E2ApplicationProtocol) (*mocks.RnibReaderMock, *mocks.RnibWriterMock, *SetupRequestHandler, *mocks.E2TInstancesManagerMock, *mocks.RanSetupManagerMock, *mocks.HttpClientMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
config.RoutingManager.BaseUrl = BaseRMUrl
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
ranSetupManagerMock := &mocks.RanSetupManagerMock{}
e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
httpClientMock := &mocks.HttpClientMock{}
mockHttpClientAssociateRan(httpClientMock)
rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
e2tAssociationManager := managers.NewE2TAssociationManager(log, rnibDataService, e2tInstancesManagerMock, rmClient)
handler := NewSetupRequestHandler(log, rnibDataService, ranSetupManagerMock, protocol, e2tInstancesManagerMock, e2tAssociationManager)
return readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, httpClientMock
}
func initSetupRequestTestBasicMocks(t *testing.T, protocol entities.E2ApplicationProtocol) (*mocks.RnibReaderMock, *mocks.RnibWriterMock, *SetupRequestHandler, *mocks.RmrMessengerMock, *mocks.HttpClientMock, *mocks.E2TInstancesManagerMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
config.RoutingManager.BaseUrl = BaseRMUrl
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := getRmrSender(rmrMessengerMock, log)
ranSetupManager := managers.NewRanSetupManager(log, rmrSender, rnibDataService)
e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
httpClientMock := &mocks.HttpClientMock{}
rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
e2tAssociationManager := managers.NewE2TAssociationManager(log, rnibDataService, e2tInstancesManagerMock, rmClient)
handler := NewSetupRequestHandler(log, rnibDataService, ranSetupManager, protocol, e2tInstancesManagerMock, e2tAssociationManager)
return readerMock, writerMock, handler, rmrMessengerMock, httpClientMock, e2tInstancesManagerMock
}
func mockHttpClientAssociateRan(httpClientMock *mocks.HttpClientMock) {
data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)}
marshaled, _ := json.Marshal(data)
body := bytes.NewBuffer(marshaled)
url := BaseRMUrl + clients.AssociateRanToE2TInstanceApiSuffix
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
}
func TestX2SetupHandleNoPortError(t *testing.T) {
readerMock, _, handler, _, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
sr := models.SetupRequest{"127.0.0.1", 0, RanName,}
_, err := handler.Handle(sr)
assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
readerMock.AssertNotCalled(t, "GetNodeb")
}
func TestX2SetupHandleNoRanNameError(t *testing.T) {
readerMock, _, handler, _, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
sr := models.SetupRequest{RanPort: 8080, RanIp: "127.0.0.1"}
_, err := handler.Handle(sr)
assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
readerMock.AssertNotCalled(t, "GetNodeb")
}
func TestX2SetupHandleNoIpError(t *testing.T) {
readerMock, _, handler, _, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
sr := models.SetupRequest{RanPort: 8080, RanName: RanName}
_, err := handler.Handle(sr)
assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
readerMock.AssertNotCalled(t, "GetNodeb")
}
func TestX2SetupHandleInvalidIpError(t *testing.T) {
readerMock, _, handler, _, _, _:= initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
sr := models.SetupRequest{RanPort: 8080, RanName: RanName, RanIp: "invalid ip"}
_, err := handler.Handle(sr)
assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
readerMock.AssertNotCalled(t, "GetNodeb")
}
func TestSetupGetNodebFailure(t *testing.T) {
readerMock, _, handler, _, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
rnibErr := &common.ValidationError{}
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
sr := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(sr)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
}
func TestSetupNewRanSelectE2TInstancesDbError(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return("", e2managererrors.NewRnibDbError())
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance")
writerMock.AssertNotCalled(t, "SaveNodeb")
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupNewRanSelectE2TInstancesNoInstances(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
nodebInfo, _ := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
updatedNb := *nodebInfo
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(nil)
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.Nil(t, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
e2tInstancesManagerMock.AssertExpectations(t)
ranSetupManagerMock.AssertExpectations(t)
}
func TestSetupNewRanAssociateRanFailure(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, httpClientMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(e2managererrors.NewRnibDbError())
setupRequest := &models.SetupRequest{"127.0.0.1", 8080, RanName,}
nb, nbIdentity := createInitialNodeInfo(setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
writerMock.On("SaveNodeb", nbIdentity, mock.Anything).Return(nil)
writerMock.On("UpdateNodebInfo", nb).Return(nil)
nb.AssociatedE2TInstanceAddress = E2TAddress
mockHttpClientAssociateRan(httpClientMock)
updatedNb := *nb
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
_, err := handler.Handle(*setupRequest)
assert.NotNil(t, err)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
e2tInstancesManagerMock.AssertExpectations(t)
ranSetupManagerMock.AssertExpectations(t)
httpClientMock.AssertExpectations(t)
}
func TestSetupNewRanSaveNodebFailure(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(common.NewInternalError(fmt.Errorf("")))
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupNewRanSetupDbError(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(e2managererrors.NewRnibDbError())
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil)
updatedNb := *nodebInfo
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
_, err := handler.Handle(setupRequest)
assert.NotNil(t, err)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
ranSetupManagerMock.AssertExpectations(t)
}
func TestSetupNewRanSetupRmrError(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil)
updatedNb := *nodebInfo
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(e2managererrors.NewRmrError())
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.RmrError{}, err)
}
func TestSetupNewRanSetupSuccess(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil)
updatedNb := *nodebInfo
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(nil)
_, err := handler.Handle(setupRequest)
assert.Nil(t, err)
}
func TestX2SetupExistingRanShuttingDown(t *testing.T) {
readerMock, _, handler, e2tInstancesManagerMock, ranSetupManagerMock , _:= initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}, nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.WrongStateError{}, err)
e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestEndcSetupExistingRanShuttingDown(t *testing.T) {
readerMock, _, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}, nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.WrongStateError{}, err)
e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupExistingRanWithoutAssocE2TInstanceSelectDbError(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
e2tInstancesManagerMock.On("SelectE2TInstance").Return("", e2managererrors.NewRnibDbError())
updatedNb := *nb
updatedNb.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupExistingRanWithoutAssocE2TInstanceSelectNoInstanceError(t *testing.T) {
readerMock, writerMock, handler, rmrMessengerMock, httpClientMock,e2tInstancesManagerMock:= initSetupRequestTestBasicMocks(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
readerMock.On("GetE2TAddresses").Return([]string{}, nil)
writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", "10.0.2.15:8989", []string{"test"}).Return(nil)
mockHttpClientAssociateRan(httpClientMock)
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.InternalError{}, err)
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
writerMock.AssertExpectations(t)
}
func TestSetupExistingRanWithoutAssocE2TInstanceSelectNoInstanceErrorUpdateFailure(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
e2tInstancesManagerMock.On("SelectE2TInstance").Return("", e2managererrors.NewE2TInstanceAbsenceError())
updatedNb := *nb
updatedNb.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(common.NewInternalError(fmt.Errorf("")))
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.E2TInstanceAbsenceError{}, err)
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupExistingRanWithoutAssocE2TInstanceSelectErrorAlreadyDisconnected(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, e2managererrors.NewE2TInstanceAbsenceError())
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.E2TInstanceAbsenceError{}, err)
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
//func TestSetupExistingRanWithoutAssocE2TInstanceAssociateRanFailure(t *testing.T) {
// readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
// nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
// readerMock.On("GetNodeb", RanName).Return(nb, nil)
// e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
// e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(e2managererrors.NewRnibDbError())
// writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
// _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
// assert.IsType(t, &e2managererrors.RnibDbError{}, err)
// writerMock.AssertNotCalled(t, "UpdateNodebInfo")
// ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
//}
//func TestSetupExistingRanWithoutAssocE2TInstanceAssociateRanSucceedsUpdateNodebFails(t *testing.T) {
// readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
// nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
// readerMock.On("GetNodeb", RanName).Return(nb, nil)
// e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
// e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
// updatedNb := *nb
// updatedNb.AssociatedE2TInstanceAddress = E2TAddress
// writerMock.On("UpdateNodebInfo", &updatedNb).Return(common.NewInternalError(fmt.Errorf("")))
// _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
// assert.IsType(t, /* &e2managererrors.RnibDbError{} */&common.InternalError{}, err)
// ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
//}
//func TestSetupExistingRanWithoutAssocE2TInstanceExecuteSetupFailure(t *testing.T) {
// readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
// nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
// readerMock.On("GetNodeb", RanName).Return(nb, nil)
// e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
// e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
// updatedNb := *nb
// updatedNb.AssociatedE2TInstanceAddress = E2TAddress
// writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
// ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(e2managererrors.NewRnibDbError())
// _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
// assert.IsType(t, &e2managererrors.RnibDbError{}, err)
//}
//
//func TestSetupExistingRanWithoutAssocE2TInstanceSuccess(t *testing.T) {
// readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
// nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
// readerMock.On("GetNodeb", RanName).Return(nb, nil)
// e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
// e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
// updatedNb := *nb
// updatedNb.AssociatedE2TInstanceAddress = E2TAddress
// writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
// ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(nil)
// _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
// assert.Nil(t, err)
//}
func TestSetupExistingRanWithAssocE2TInstanceUpdateNodebFailure(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
updatedNb := *nb
writerMock.On("UpdateNodebInfo", &updatedNb).Return(common.NewInternalError(fmt.Errorf("")))
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance")
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupExistingRanWithAssocE2TInstanceExecuteSetupRmrError(t *testing.T) {
readerMock, writerMock, handler, rmrMessengerMock, _, _ := initSetupRequestTestBasicMocks(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
updatedNb := *nb
updatedNb3 := updatedNb
updatedNb3.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
payload := e2pdus.PackedX2setupRequest
xaction := []byte(RanName)
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction, nil)
rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg, e2managererrors.NewRmrError())
writerMock.On("UpdateNodebInfo", &updatedNb3).Return(nil)
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.IsType(t, &e2managererrors.RmrError{}, err)
writerMock.AssertExpectations(t)
}
func TestSetupExistingRanWithAssocE2TInstanceConnectedSuccess(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
updatedNb := *nb
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTED).Return(nil)
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.Nil(t, err)
e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance")
}
func TestSetupExistingRanWithoutAssocE2TInstanceExecuteRoutingManagerError(t *testing.T) {
readerMock, writerMock, handler, rmrMessengerMock, httpClientMock, e2tInstancesManagerMock := initSetupRequestTestBasicMocks(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
writerMock.On("UpdateNodebInfo", nb).Return(nil)
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
mockHttpClientAssociateRan(httpClientMock)
e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
msg := &rmrCgo.MBuf{}
var errNIl error
rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg, errNIl)
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.Nil(t, err)
writerMock.AssertExpectations(t)
readerMock.AssertExpectations(t)
httpClientMock.AssertExpectations(t)
}

View File

@@ -0,0 +1,233 @@
//
// 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 httpmsghandlers
import (
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/models"
"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"
)
const VALIDATION_FAILURE_MESSAGE = "#UpdateGnbRequestHandler.Handle - validation failure: %s is a mandatory field"
type UpdateGnbRequestHandler struct {
logger *logger.Logger
rNibDataService services.RNibDataService
}
func NewUpdateGnbRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService) *UpdateGnbRequestHandler {
return &UpdateGnbRequestHandler{
logger: logger,
rNibDataService: rNibDataService,
}
}
func (h *UpdateGnbRequestHandler) Handle(request models.Request) (models.IResponse, error) {
updateGnbRequest := request.(models.UpdateGnbRequest)
h.logger.Infof("#UpdateGnbRequestHandler.Handle - Ran name: %s", updateGnbRequest.RanName)
err := h.validateRequestBody(updateGnbRequest)
if err != nil {
return nil, err
}
nodebInfo, err := h.rNibDataService.GetNodeb(updateGnbRequest.RanName)
if err != nil {
_, ok := err.(*common.ResourceNotFoundError)
if !ok {
h.logger.Errorf("#UpdateGnbRequestHandler.Handle - RAN name: %s - failed to get nodeb entity from RNIB. Error: %s", updateGnbRequest.RanName, err)
return nil, e2managererrors.NewRnibDbError()
}
h.logger.Errorf("#UpdateGnbRequestHandler.Handle - RAN name: %s - RAN not found on RNIB. Error: %s", updateGnbRequest.RanName, err)
return nil, e2managererrors.NewResourceNotFoundError()
}
err = h.updateGnbCells(nodebInfo, updateGnbRequest)
if err != nil {
return nil, err
}
return models.NewUpdateGnbResponse(nodebInfo), nil
}
func (h *UpdateGnbRequestHandler) updateGnbCells(nodebInfo *entities.NodebInfo, updateGnbRequest models.UpdateGnbRequest) error {
ranName := nodebInfo.RanName
gnb := nodebInfo.GetGnb()
if gnb == nil {
h.logger.Errorf("#UpdateGnbRequestHandler.updateGnbCells - RAN name: %s - nodeb missing gnb configuration", ranName)
return e2managererrors.NewInternalError()
}
if len(gnb.ServedNrCells) != 0 {
err := h.rNibDataService.RemoveServedNrCells(ranName, gnb.ServedNrCells)
if err != nil {
h.logger.Errorf("#UpdateGnbRequestHandler.updateGnbCells - RAN name: %s - Failed removing served nr cells", ranName)
return e2managererrors.NewRnibDbError()
}
}
gnb.ServedNrCells = updateGnbRequest.ServedNrCells
err := h.rNibDataService.UpdateGnbCells(nodebInfo, updateGnbRequest.ServedNrCells)
if err != nil {
h.logger.Errorf("#UpdateGnbRequestHandler.updateGnbCells - RAN name: %s - Failed updating GNB cells. Error: %s", ranName, err)
return e2managererrors.NewRnibDbError()
}
h.logger.Infof("#UpdateGnbRequestHandler.updateGnbCells - RAN name: %s - Successfully updated GNB cells", ranName)
return nil
}
func (h *UpdateGnbRequestHandler) validateRequestBody(updateGnbRequest models.UpdateGnbRequest) error {
if len(updateGnbRequest.ServedNrCells) == 0 {
h.logger.Errorf(VALIDATION_FAILURE_MESSAGE+" and cannot be empty", "servedCells")
return e2managererrors.NewRequestValidationError()
}
for _, servedNrCell := range updateGnbRequest.ServedNrCells {
if servedNrCell.ServedNrCellInformation == nil {
h.logger.Errorf(VALIDATION_FAILURE_MESSAGE+" and cannot be empty", "servedNrCellInformation")
return e2managererrors.NewRequestValidationError()
}
err := isServedNrCellInformationValid(servedNrCell.ServedNrCellInformation)
if err != nil {
h.logger.Errorf(VALIDATION_FAILURE_MESSAGE, err)
return e2managererrors.NewRequestValidationError()
}
if len(servedNrCell.NrNeighbourInfos) == 0 {
continue
}
for _, nrNeighbourInformation := range servedNrCell.NrNeighbourInfos {
err := isNrNeighbourInformationValid(nrNeighbourInformation)
if err != nil {
h.logger.Errorf(VALIDATION_FAILURE_MESSAGE, err)
return e2managererrors.NewRequestValidationError()
}
}
}
return nil
}
func isServedNrCellInformationValid(servedNrCellInformation *entities.ServedNRCellInformation) error {
if servedNrCellInformation.CellId == "" {
return errors.New("cellId")
}
if servedNrCellInformation.ChoiceNrMode == nil {
return errors.New("choiceNrMode")
}
if servedNrCellInformation.NrMode == entities.Nr_UNKNOWN {
return errors.New("nrMode")
}
if servedNrCellInformation.NrPci == 0 {
return errors.New("nrPci")
}
if len(servedNrCellInformation.ServedPlmns) == 0 {
return errors.New("servedPlmns")
}
return isServedNrCellInfoChoiceNrModeValid(servedNrCellInformation.ChoiceNrMode)
}
func isServedNrCellInfoChoiceNrModeValid(choiceNrMode *entities.ServedNRCellInformation_ChoiceNRMode) error {
if choiceNrMode.Fdd != nil {
return isServedNrCellInfoFddValid(choiceNrMode.Fdd)
}
if choiceNrMode.Tdd != nil {
return isServedNrCellInfoTddValid(choiceNrMode.Tdd)
}
return errors.New("served nr cell fdd / tdd")
}
func isServedNrCellInfoTddValid(tdd *entities.ServedNRCellInformation_ChoiceNRMode_TddInfo) error {
return nil
}
func isServedNrCellInfoFddValid(fdd *entities.ServedNRCellInformation_ChoiceNRMode_FddInfo) error {
return nil
}
func isNrNeighbourInformationValid(nrNeighbourInformation *entities.NrNeighbourInformation) error {
if nrNeighbourInformation.NrCgi == "" {
return errors.New("nrCgi")
}
if nrNeighbourInformation.ChoiceNrMode == nil {
return errors.New("choiceNrMode")
}
if nrNeighbourInformation.NrMode == entities.Nr_UNKNOWN {
return errors.New("nrMode")
}
if nrNeighbourInformation.NrPci == 0 {
return errors.New("nrPci")
}
return isNrNeighbourInfoChoiceNrModeValid(nrNeighbourInformation.ChoiceNrMode)
}
func isNrNeighbourInfoChoiceNrModeValid(choiceNrMode *entities.NrNeighbourInformation_ChoiceNRMode) error {
if choiceNrMode.Fdd != nil {
return isNrNeighbourInfoFddValid(choiceNrMode.Fdd)
}
if choiceNrMode.Tdd != nil {
return isNrNeighbourInfoTddValid(choiceNrMode.Tdd)
}
return errors.New("nr neighbour fdd / tdd")
}
func isNrNeighbourInfoTddValid(tdd *entities.NrNeighbourInformation_ChoiceNRMode_TddInfo) error {
return nil
}
func isNrNeighbourInfoFddValid(fdd *entities.NrNeighbourInformation_ChoiceNRMode_FddInfo) error {
return nil
}

View File

@@ -0,0 +1,99 @@
//
// 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 httpmsghandlers
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/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"unsafe"
)
const (
X2_RESET_ACTIVITY_NAME = "X2_RESET"
)
type X2ResetRequestHandler struct {
rNibDataService services.RNibDataService
rmrSender *rmrsender.RmrSender
logger *logger.Logger
}
func NewX2ResetRequestHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender, rNibDataService services.RNibDataService) *X2ResetRequestHandler {
return &X2ResetRequestHandler{
rNibDataService: rNibDataService,
rmrSender: rmrSender,
logger: logger,
}
}
func (handler *X2ResetRequestHandler) Handle(request models.Request) (models.IResponse, error) {
resetRequest := request.(models.ResetRequest)
handler.logger.Infof("#X2ResetRequestHandler.Handle - Ran name: %s", resetRequest.RanName)
if len(resetRequest.Cause) == 0 {
resetRequest.Cause = e2pdus.OmInterventionCause
}
payload, ok := e2pdus.KnownCausesToX2ResetPDU(resetRequest.Cause)
if !ok {
handler.logger.Errorf("#X2ResetRequestHandler.Handle - Unknown cause (%s)", resetRequest.Cause)
return nil, e2managererrors.NewRequestValidationError()
}
nodeb, err := handler.rNibDataService.GetNodeb(resetRequest.RanName)
if err != nil {
handler.logger.Errorf("#X2ResetRequestHandler.Handle - failed to get status of RAN: %s from RNIB. Error: %s", resetRequest.RanName, err.Error())
_, ok := err.(*common.ResourceNotFoundError)
if ok {
return nil, e2managererrors.NewResourceNotFoundError()
}
return nil, e2managererrors.NewRnibDbError()
}
if nodeb.ConnectionStatus != entities.ConnectionStatus_CONNECTED {
handler.logger.Errorf("#X2ResetRequestHandler.Handle - RAN: %s in wrong state (%s)", resetRequest.RanName, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)])
return nil, e2managererrors.NewWrongStateError(X2_RESET_ACTIVITY_NAME, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)])
}
var xAction []byte
var msgSrc unsafe.Pointer
msg := models.NewRmrMessage(rmrCgo.RIC_X2_RESET, resetRequest.RanName, payload, xAction, msgSrc)
err = handler.rmrSender.Send(msg)
if err != nil {
handler.logger.Errorf("#X2ResetRequestHandler.Handle - failed to send reset message to RMR: %s", err)
return nil, e2managererrors.NewRmrError()
}
handler.logger.Infof("#X2ResetRequestHandler.Handle - sent x2 reset to RAN: %s with cause: %s", resetRequest.RanName, resetRequest.Cause)
return nil, nil
}

View File

@@ -0,0 +1,154 @@
//
// 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 httpmsghandlers
import (
"e2mgr/configuration"
"e2mgr/e2managererrors"
"e2mgr/mocks"
"e2mgr/models"
"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"
"testing"
"unsafe"
)
func setupX2ResetRequestHandlerTest(t *testing.T) (*X2ResetRequestHandler, *mocks.RmrMessengerMock, *mocks.RnibReaderMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := getRmrSender(rmrMessengerMock, log)
handler := NewX2ResetRequestHandler(log, rmrSender, rnibDataService)
return handler, rmrMessengerMock, readerMock
}
func TestHandleSuccessfulDefaultCause(t *testing.T) {
handler, rmrMessengerMock, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
// o&m intervention
payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
var xAction[]byte
var msgSrc unsafe.Pointer
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction, msgSrc)
rmrMessengerMock.On("SendMsg", msg, true).Return(msg, nil)
var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
_, actual := handler.Handle(models.ResetRequest{RanName: ranName})
assert.Nil(t, actual)
}
func TestHandleSuccessfulRequestedCause(t *testing.T) {
handler, rmrMessengerMock, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x40}
var xAction[]byte
var msgSrc unsafe.Pointer
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction, msgSrc)
rmrMessengerMock.On("SendMsg", msg, true).Return(msg, nil)
var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
_, actual := handler.Handle(models.ResetRequest{RanName: ranName, Cause: "protocol:transfer-syntax-error"})
assert.Nil(t, actual)
}
func TestHandleFailureUnknownCause(t *testing.T) {
handler, _, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
_, actual := handler.Handle(models.ResetRequest{RanName: ranName, Cause: "XXX"})
assert.IsType(t, e2managererrors.NewRequestValidationError(), actual)
}
func TestHandleFailureWrongState(t *testing.T) {
handler, _, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
_, actual := handler.Handle(models.ResetRequest{RanName: ranName})
assert.IsType(t, e2managererrors.NewWrongStateError(X2_RESET_ACTIVITY_NAME, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)]), actual)
}
func TestHandleFailureRanNotFound(t *testing.T) {
handler, _, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError("nodeb not found"))
_, actual := handler.Handle(models.ResetRequest{RanName: ranName})
assert.IsType(t, e2managererrors.NewResourceNotFoundError(), actual)
}
func TestHandleFailureRnibError(t *testing.T) {
handler, _, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{}, common.NewInternalError(fmt.Errorf("internal error")))
_, actual := handler.Handle(models.ResetRequest{RanName: ranName})
assert.IsType(t, e2managererrors.NewRnibDbError(), actual)
}
func TestHandleFailureRmrError(t *testing.T) {
handler, rmrMessengerMock, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
// o&m intervention
payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
var xAction[]byte
var msgSrc unsafe.Pointer
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction, msgSrc)
rmrMessengerMock.On("SendMsg", msg, true).Return(&rmrCgo.MBuf{}, fmt.Errorf("rmr error"))
var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
_, actual := handler.Handle(models.ResetRequest{RanName: ranName})
assert.IsType(t, e2managererrors.NewRmrError(), actual)
}