First commit
This commit is contained in:
@@ -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
|
||||
|
||||
}
|
@@ -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)
|
||||
}
|
@@ -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
|
||||
}
|
@@ -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)
|
||||
}
|
@@ -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
|
||||
}
|
@@ -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)
|
||||
}
|
@@ -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()
|
||||
}
|
@@ -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)
|
||||
}
|
@@ -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)
|
||||
}
|
@@ -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
|
||||
}
|
@@ -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)
|
||||
}
|
@@ -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
|
||||
}
|
@@ -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
|
||||
}
|
@@ -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)
|
||||
}
|
@@ -0,0 +1,273 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/e2managererrors"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"e2mgr/services/rmrsender"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"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"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type E2SetupRequestNotificationHandler struct {
|
||||
logger *logger.Logger
|
||||
config *configuration.Configuration
|
||||
e2tInstancesManager managers.IE2TInstancesManager
|
||||
rmrSender *rmrsender.RmrSender
|
||||
rNibDataService services.RNibDataService
|
||||
e2tAssociationManager *managers.E2TAssociationManager
|
||||
}
|
||||
|
||||
func NewE2SetupRequestNotificationHandler(logger *logger.Logger, config *configuration.Configuration, e2tInstancesManager managers.IE2TInstancesManager, rmrSender *rmrsender.RmrSender, rNibDataService services.RNibDataService, e2tAssociationManager *managers.E2TAssociationManager) E2SetupRequestNotificationHandler {
|
||||
return E2SetupRequestNotificationHandler{
|
||||
logger: logger,
|
||||
config: config,
|
||||
e2tInstancesManager: e2tInstancesManager,
|
||||
rmrSender: rmrSender,
|
||||
rNibDataService: rNibDataService,
|
||||
e2tAssociationManager: e2tAssociationManager,
|
||||
}
|
||||
}
|
||||
|
||||
func (h E2SetupRequestNotificationHandler) Handle(request *models.NotificationRequest) {
|
||||
ranName := request.RanName
|
||||
h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - received E2_SETUP_REQUEST. Payload: %x", ranName, request.Payload)
|
||||
|
||||
setupRequest, e2tIpAddress, err := h.parseSetupRequest(request.Payload)
|
||||
if err != nil {
|
||||
h.logger.Errorf(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - E2T Address: %s - handling E2_SETUP_REQUEST", e2tIpAddress)
|
||||
h.logger.Debugf("#E2SetupRequestNotificationHandler.Handle - E2_SETUP_REQUEST has been parsed successfully %+v", setupRequest)
|
||||
|
||||
_, err = h.e2tInstancesManager.GetE2TInstance(e2tIpAddress)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed retrieving E2TInstance. error: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
nodebInfo, err := h.rNibDataService.GetNodeb(ranName)
|
||||
|
||||
if err != nil {
|
||||
|
||||
if _, ok := err.(*common.ResourceNotFoundError); !ok {
|
||||
h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to retrieve nodebInfo entity. Error: %s", ranName, err)
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
if nodebInfo, err = h.handleNewRan(ranName, e2tIpAddress, setupRequest); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
} else {
|
||||
if err = h.handleExistingRan(ranName, nodebInfo, setupRequest); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = h.e2tAssociationManager.AssociateRan(e2tIpAddress, nodebInfo)
|
||||
|
||||
if err != nil {
|
||||
|
||||
h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to associate E2T to nodeB entity. Error: %s", ranName, err)
|
||||
if _, ok := err.(*e2managererrors.RoutingManagerError); ok {
|
||||
h.handleUnsuccessfulResponse(nodebInfo, request)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
h.handleSuccessfulResponse(ranName, request, setupRequest)
|
||||
}
|
||||
|
||||
func (h E2SetupRequestNotificationHandler) handleNewRan(ranName string, e2tIpAddress string, setupRequest *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
|
||||
|
||||
nodebInfo, err := h.buildNodebInfo(ranName, e2tIpAddress, setupRequest)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Errorf("#E2SetupRequestNotificationHandler.handleNewRan - RAN name: %s - failed to build nodebInfo entity. Error: %s", ranName, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nbIdentity := h.buildNbIdentity(ranName, setupRequest)
|
||||
err = h.rNibDataService.SaveNodeb(nbIdentity, nodebInfo)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Errorf("#E2SetupRequestNotificationHandler.handleNewRan - RAN name: %s - failed to save nodebInfo entity. Error: %s", ranName, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nodebInfo, nil
|
||||
}
|
||||
|
||||
func (h E2SetupRequestNotificationHandler) setGnbFunctions(nodebInfo *entities.NodebInfo, setupRequest *models.E2SetupRequestMessage) error {
|
||||
ranFunctions, err := setupRequest.ExtractRanFunctionsList()
|
||||
|
||||
if err != nil {
|
||||
h.logger.Errorf("#E2SetupRequestNotificationHandler.setGnbFunctions - RAN name: %s - failed to update nodebInfo entity. Error: %s", nodebInfo.GetRanName(), err)
|
||||
return err
|
||||
}
|
||||
|
||||
if ranFunctions != nil {
|
||||
nodebInfo.GetGnb().RanFunctions = ranFunctions
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h E2SetupRequestNotificationHandler) handleExistingRan(ranName string, nodebInfo *entities.NodebInfo, setupRequest *models.E2SetupRequestMessage) error {
|
||||
if nodebInfo.GetConnectionStatus() == entities.ConnectionStatus_SHUTTING_DOWN {
|
||||
h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", ranName, nodebInfo.ConnectionStatus)
|
||||
return errors.New("nodeB entity in incorrect state")
|
||||
}
|
||||
|
||||
err := h.setGnbFunctions(nodebInfo, setupRequest)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h E2SetupRequestNotificationHandler) handleUnsuccessfulResponse(nodebInfo *entities.NodebInfo, req *models.NotificationRequest) {
|
||||
failureResponse := models.NewE2SetupFailureResponseMessage(models.TimeToWaitEnum.V60s)
|
||||
h.logger.Debugf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", failureResponse)
|
||||
|
||||
responsePayload, err := xml.Marshal(&failureResponse.E2APPDU)
|
||||
if err != nil {
|
||||
h.logger.Warnf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", nodebInfo.RanName, responsePayload)
|
||||
}
|
||||
|
||||
responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload)
|
||||
|
||||
msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_FAILURE, nodebInfo.RanName, responsePayload, req.TransactionId, req.GetMsgSrc())
|
||||
h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", nodebInfo.RanName, msg)
|
||||
_ = h.rmrSender.WhSend(msg)
|
||||
|
||||
}
|
||||
|
||||
func (h E2SetupRequestNotificationHandler) handleSuccessfulResponse(ranName string, req *models.NotificationRequest, setupRequest *models.E2SetupRequestMessage) {
|
||||
|
||||
ricNearRtId, err := convertTo20BitString(h.config.GlobalRicId.RicNearRtId)
|
||||
if err != nil {
|
||||
h.logger.Errorf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - failed to convert RicNearRtId value %s to 20 bit string . Error: %s", ranName, h.config.GlobalRicId.RicNearRtId, err)
|
||||
return
|
||||
}
|
||||
successResponse := models.NewE2SetupSuccessResponseMessage(h.config.GlobalRicId.PlmnId, ricNearRtId, setupRequest)
|
||||
h.logger.Debugf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", successResponse)
|
||||
|
||||
responsePayload, err := xml.Marshal(&successResponse.E2APPDU)
|
||||
if err != nil {
|
||||
h.logger.Warnf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload)
|
||||
}
|
||||
|
||||
responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload)
|
||||
|
||||
msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_RESP, ranName, responsePayload, req.TransactionId, req.GetMsgSrc())
|
||||
h.logger.Infof("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", ranName, msg)
|
||||
_ = h.rmrSender.Send(msg)
|
||||
}
|
||||
|
||||
func replaceEmptyTagsWithSelfClosing(responsePayload []byte) []byte {
|
||||
responseString := strings.NewReplacer(
|
||||
"<reject></reject>", "<reject/>",
|
||||
"<ignore></ignore>", "<ignore/>",
|
||||
"<transport-resource-unavailable></transport-resource-unavailable>", "<transport-resource-unavailable/>",
|
||||
"<v60s></v60s>", "<v60s/>",
|
||||
"<v20s></v20s>", "<v20s/>",
|
||||
"<v10s></v10s>", "<v10s/>",
|
||||
"<v5s></v5s>", "<v5s/>",
|
||||
"<v2s></v2s>", "<v2s/>",
|
||||
"<v1s></v1s>", "<v1s/>",
|
||||
).Replace(string(responsePayload))
|
||||
return []byte(responseString)
|
||||
}
|
||||
|
||||
func convertTo20BitString(ricNearRtId string) (string, error) {
|
||||
r, err := strconv.ParseUint(ricNearRtId, 16, 32)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%020b", r)[:20], nil
|
||||
}
|
||||
|
||||
func (h E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte) (*models.E2SetupRequestMessage, string, error) {
|
||||
|
||||
pipInd := bytes.IndexByte(payload, '|')
|
||||
if pipInd < 0 {
|
||||
return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Error parsing E2 Setup Request failed extract Payload: no | separator found")
|
||||
}
|
||||
|
||||
e2tIpAddress := string(payload[:pipInd])
|
||||
if len(e2tIpAddress) == 0 {
|
||||
return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Empty E2T Address received")
|
||||
}
|
||||
|
||||
h.logger.Infof("#E2SetupRequestNotificationHandler.parseSetupRequest - payload: %s", payload[pipInd+1:])
|
||||
|
||||
setupRequest := &models.E2SetupRequestMessage{}
|
||||
err := xml.Unmarshal(payload[pipInd+1:], &setupRequest.E2APPDU)
|
||||
if err != nil {
|
||||
return nil, "", errors.New(fmt.Sprintf("#E2SetupRequestNotificationHandler.parseSetupRequest - Error unmarshalling E2 Setup Request payload: %x", payload))
|
||||
}
|
||||
|
||||
return setupRequest, e2tIpAddress, nil
|
||||
}
|
||||
|
||||
func (h E2SetupRequestNotificationHandler) buildNodebInfo(ranName string, e2tAddress string, request *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
|
||||
|
||||
var err error
|
||||
nodebInfo := &entities.NodebInfo{
|
||||
AssociatedE2TInstanceAddress: e2tAddress,
|
||||
ConnectionStatus: entities.ConnectionStatus_CONNECTED,
|
||||
RanName: ranName,
|
||||
NodeType: entities.Node_GNB,
|
||||
Configuration: &entities.NodebInfo_Gnb{Gnb: &entities.Gnb{}},
|
||||
GlobalNbId: h.buildGlobalNbId(request),
|
||||
}
|
||||
|
||||
err = h.setGnbFunctions(nodebInfo, request)
|
||||
return nodebInfo, err
|
||||
}
|
||||
|
||||
func (h E2SetupRequestNotificationHandler) buildGlobalNbId(setupRequest *models.E2SetupRequestMessage) *entities.GlobalNbId {
|
||||
return &entities.GlobalNbId{
|
||||
PlmnId: setupRequest.GetPlmnId(),
|
||||
NbId: setupRequest.GetNbId(),
|
||||
}
|
||||
}
|
||||
|
||||
func (h E2SetupRequestNotificationHandler) buildNbIdentity(ranName string, setupRequest *models.E2SetupRequestMessage) *entities.NbIdentity {
|
||||
return &entities.NbIdentity{
|
||||
InventoryName: ranName,
|
||||
GlobalNbId: h.buildGlobalNbId(setupRequest),
|
||||
}
|
||||
}
|
@@ -0,0 +1,417 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"e2mgr/tests"
|
||||
"errors"
|
||||
"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"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
prefix = "10.0.2.15:9999|"
|
||||
e2tInstanceFullAddress = "10.0.2.15:9999"
|
||||
nodebRanName = "gnb:310-410-b5c67788"
|
||||
GnbSetupRequestXmlPath = "../../tests/resources/setupRequest_gnb.xml"
|
||||
GnbWithoutFunctionsSetupRequestXmlPath = "../../tests/resources/setupRequest_gnb_without_functions.xml"
|
||||
EnGnbSetupRequestXmlPath = "../../tests/resources/setupRequest_en-gNB.xml"
|
||||
NgEnbSetupRequestXmlPath = "../../tests/resources/setupRequest_ng-eNB.xml"
|
||||
EnbSetupRequestXmlPath = "../../tests/resources/setupRequest_enb.xml"
|
||||
)
|
||||
|
||||
func readXmlFile(t *testing.T, xmlPath string) []byte {
|
||||
path, err := filepath.Abs(xmlPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
xmlAsBytes, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return xmlAsBytes
|
||||
}
|
||||
|
||||
func TestParseGnbSetupRequest_Success(t *testing.T) {
|
||||
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
|
||||
handler, _, _, _, _, _ := initMocks(t)
|
||||
prefBytes := []byte(prefix)
|
||||
request, _, err := handler.parseSetupRequest(append(prefBytes, xmlGnb...))
|
||||
assert.Equal(t, "131014", request.GetPlmnId())
|
||||
assert.Equal(t, "10011001101010101011", request.GetNbId())
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestParseEnGnbSetupRequest_Success(t *testing.T) {
|
||||
enGnbXml := readXmlFile(t, EnGnbSetupRequestXmlPath)
|
||||
handler, _, _, _, _, _ := initMocks(t)
|
||||
prefBytes := []byte(prefix)
|
||||
request, _, err := handler.parseSetupRequest(append(prefBytes, enGnbXml...))
|
||||
assert.Equal(t, "131014", request.GetPlmnId())
|
||||
assert.Equal(t, "11000101110001101100011111111000", request.GetNbId())
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestParseNgEnbSetupRequest_Success(t *testing.T) {
|
||||
ngEnbXml := readXmlFile(t, NgEnbSetupRequestXmlPath)
|
||||
handler, _, _, _, _, _ := initMocks(t)
|
||||
prefBytes := []byte(prefix)
|
||||
request, _, err := handler.parseSetupRequest(append(prefBytes, ngEnbXml...))
|
||||
assert.Equal(t, "131014", request.GetPlmnId())
|
||||
assert.Equal(t, "101010101010101010", request.GetNbId())
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestParseEnbSetupRequest_Success(t *testing.T) {
|
||||
enbXml := readXmlFile(t, EnbSetupRequestXmlPath)
|
||||
handler, _, _, _, _, _ := initMocks(t)
|
||||
prefBytes := []byte(prefix)
|
||||
request, _, err := handler.parseSetupRequest(append(prefBytes, enbXml...))
|
||||
assert.Equal(t, "6359AB", request.GetPlmnId())
|
||||
assert.Equal(t, "101010101010101010", request.GetNbId())
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestParseSetupRequest_PipFailure(t *testing.T) {
|
||||
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
|
||||
handler, _, _, _, _, _ := initMocks(t)
|
||||
prefBytes := []byte("10.0.2.15:9999")
|
||||
request, _, err := handler.parseSetupRequest(append(prefBytes, xmlGnb...))
|
||||
assert.Nil(t, request)
|
||||
assert.NotNil(t, err)
|
||||
assert.EqualError(t, err, "#E2SetupRequestNotificationHandler.parseSetupRequest - Error parsing E2 Setup Request failed extract Payload: no | separator found")
|
||||
}
|
||||
|
||||
func TestParseSetupRequest_UnmarshalFailure(t *testing.T) {
|
||||
handler, _, _, _, _, _ := initMocks(t)
|
||||
prefBytes := []byte(prefix)
|
||||
request, _, err := handler.parseSetupRequest(append(prefBytes, 1, 2, 3))
|
||||
assert.Nil(t, request)
|
||||
assert.NotNil(t, err)
|
||||
assert.EqualError(t, err, "#E2SetupRequestNotificationHandler.parseSetupRequest - Error unmarshalling E2 Setup Request payload: 31302e302e322e31353a393939397c010203")
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_HandleNewGnbSuccess(t *testing.T) {
|
||||
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
|
||||
handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
|
||||
var e2tInstance = &entities.E2TInstance{}
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
|
||||
var gnb *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
|
||||
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
|
||||
routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(nil)
|
||||
writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
|
||||
e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
|
||||
var errEmpty error
|
||||
rmrMessage := &rmrCgo.MBuf{}
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(rmrMessage, errEmpty)
|
||||
prefBytes := []byte(prefix)
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
|
||||
handler.Handle(notificationRequest)
|
||||
assertNewNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_HandleNewGnbWithoutFunctionsSuccess(t *testing.T) {
|
||||
xmlGnb := readXmlFile(t, GnbWithoutFunctionsSetupRequestXmlPath)
|
||||
handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
|
||||
var e2tInstance = &entities.E2TInstance{}
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
|
||||
var gnb *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
|
||||
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
|
||||
routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(nil)
|
||||
writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
|
||||
e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
|
||||
var errEmpty error
|
||||
rmrMessage := &rmrCgo.MBuf{}
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(rmrMessage, errEmpty)
|
||||
prefBytes := []byte(prefix)
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
|
||||
handler.Handle(notificationRequest)
|
||||
assertNewNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_HandleNewEnGnbSuccess(t *testing.T) {
|
||||
xmlEnGnb := readXmlFile(t, EnGnbSetupRequestXmlPath)
|
||||
handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
|
||||
var e2tInstance = &entities.E2TInstance{}
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
|
||||
var gnb *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
|
||||
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
|
||||
routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(nil)
|
||||
writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
|
||||
e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
|
||||
var errEmpty error
|
||||
rmrMessage := &rmrCgo.MBuf{}
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(rmrMessage, errEmpty)
|
||||
prefBytes := []byte(prefix)
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlEnGnb...)}
|
||||
handler.Handle(notificationRequest)
|
||||
assertNewNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_HandleNewNgEnbSuccess(t *testing.T) {
|
||||
xmlNgEnb := readXmlFile(t, NgEnbSetupRequestXmlPath)
|
||||
handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
|
||||
var e2tInstance = &entities.E2TInstance{}
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
|
||||
var gnb *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
|
||||
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
|
||||
routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(nil)
|
||||
writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
|
||||
e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
|
||||
var errEmpty error
|
||||
rmrMessage := &rmrCgo.MBuf{}
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(rmrMessage, errEmpty)
|
||||
prefBytes := []byte(prefix)
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlNgEnb...)}
|
||||
handler.Handle(notificationRequest)
|
||||
assertNewNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_HandleExistingGnbSuccess(t *testing.T) {
|
||||
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
|
||||
|
||||
handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
|
||||
var e2tInstance = &entities.E2TInstance{}
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
|
||||
var gnb = &entities.NodebInfo{
|
||||
RanName: nodebRanName,
|
||||
AssociatedE2TInstanceAddress: e2tInstanceFullAddress,
|
||||
ConnectionStatus: entities.ConnectionStatus_CONNECTED,
|
||||
NodeType: entities.Node_GNB,
|
||||
Configuration: &entities.NodebInfo_Gnb{Gnb: &entities.Gnb{}},
|
||||
}
|
||||
readerMock.On("GetNodeb", mock.Anything).Return(gnb, nil)
|
||||
routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(nil)
|
||||
writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
|
||||
e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
|
||||
var errEmpty error
|
||||
rmrMessage := &rmrCgo.MBuf{}
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(rmrMessage, errEmpty)
|
||||
prefBytes := []byte(prefix)
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
|
||||
handler.Handle(notificationRequest)
|
||||
assertExistingNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_HandleParseError(t *testing.T) {
|
||||
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
|
||||
|
||||
handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
|
||||
prefBytes := []byte("invalid_prefix")
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
|
||||
handler.Handle(notificationRequest)
|
||||
readerMock.AssertNotCalled(t, "GetNodeb", mock.Anything)
|
||||
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
|
||||
routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
|
||||
writerMock.AssertNotCalled(t, "UpdateNodebInfo", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_HandleUnmarshalError(t *testing.T) {
|
||||
handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
|
||||
prefBytes := []byte(prefix)
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, "xmlGnb"...)}
|
||||
handler.Handle(notificationRequest)
|
||||
readerMock.AssertNotCalled(t, "GetNodeb", mock.Anything)
|
||||
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
|
||||
routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
|
||||
writerMock.AssertNotCalled(t, "UpdateNodebInfo", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_HandleGetE2TInstanceError(t *testing.T) {
|
||||
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
|
||||
handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
|
||||
var e2tInstance *entities.E2TInstance
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, common.NewResourceNotFoundError("Not found"))
|
||||
prefBytes := []byte(prefix)
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
|
||||
handler.Handle(notificationRequest)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
|
||||
readerMock.AssertNotCalled(t, "GetNodeb", mock.Anything)
|
||||
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
|
||||
routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
|
||||
writerMock.AssertNotCalled(t, "UpdateNodebInfo", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_HandleGetNodebError(t *testing.T) {
|
||||
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
|
||||
|
||||
handler, readerMock, writerMock, routingManagerClientMock, e2tInstancesManagerMock, rmrMessengerMock := initMocks(t)
|
||||
var e2tInstance = &entities.E2TInstance{}
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
|
||||
var gnb *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewInternalError(errors.New("some error")))
|
||||
prefBytes := []byte(prefix)
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
|
||||
handler.Handle(notificationRequest)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
|
||||
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
|
||||
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
|
||||
routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
|
||||
writerMock.AssertNotCalled(t, "UpdateNodebInfo", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_HandleAssociationError(t *testing.T) {
|
||||
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
|
||||
|
||||
handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
|
||||
var e2tInstance = &entities.E2TInstance{}
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
|
||||
var gnb *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
|
||||
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
|
||||
writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
|
||||
e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
|
||||
routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(errors.New("association error"))
|
||||
var errEmpty error
|
||||
rmrMessage := &rmrCgo.MBuf{}
|
||||
rmrMessengerMock.On("WhSendMsg", mock.Anything, mock.Anything).Return(rmrMessage, errEmpty)
|
||||
|
||||
prefBytes := []byte(prefix)
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
|
||||
handler.Handle(notificationRequest)
|
||||
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
|
||||
writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
|
||||
routingManagerClientMock.AssertCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
|
||||
writerMock.AssertCalled(t, "UpdateNodebInfo", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
|
||||
rmrMessengerMock.AssertCalled(t, "WhSendMsg", mock.Anything, mock.Anything)
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_ConvertTo20BitStringError(t *testing.T) {
|
||||
xmlEnGnb := readXmlFile(t, EnGnbSetupRequestXmlPath)
|
||||
logger := tests.InitLog(t)
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, GlobalRicId: struct {
|
||||
PlmnId string
|
||||
RicNearRtId string
|
||||
}{PlmnId: "131014", RicNearRtId: "10011001101010101011"}}
|
||||
rmrMessengerMock := &mocks.RmrMessengerMock{}
|
||||
rmrSender := tests.InitRmrSender(rmrMessengerMock, logger)
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
routingManagerClientMock := &mocks.RoutingManagerClientMock{}
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
|
||||
e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManagerMock, routingManagerClientMock)
|
||||
handler := NewE2SetupRequestNotificationHandler(logger, config, e2tInstancesManagerMock, rmrSender, rnibDataService, e2tAssociationManager)
|
||||
|
||||
var e2tInstance = &entities.E2TInstance{}
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
|
||||
var gnb *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
|
||||
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
|
||||
routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(nil)
|
||||
writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
|
||||
e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
|
||||
var errEmpty error
|
||||
rmrMessage := &rmrCgo.MBuf{}
|
||||
rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(rmrMessage, errEmpty)
|
||||
prefBytes := []byte(prefix)
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlEnGnb...)}
|
||||
handler.Handle(notificationRequest)
|
||||
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
|
||||
writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
|
||||
routingManagerClientMock.AssertCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
|
||||
writerMock.AssertCalled(t, "UpdateNodebInfo", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
|
||||
}
|
||||
|
||||
func TestE2SetupRequestNotificationHandler_HandleExistingGnbInvalidStatusError(t *testing.T) {
|
||||
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
|
||||
handler, readerMock, writerMock, routingManagerClientMock, e2tInstancesManagerMock, rmrMessengerMock := initMocks(t)
|
||||
var gnb = &entities.NodebInfo{RanName: nodebRanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}
|
||||
readerMock.On("GetNodeb", mock.Anything).Return(gnb, nil)
|
||||
var e2tInstance = &entities.E2TInstance{}
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
|
||||
prefBytes := []byte(prefix)
|
||||
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
|
||||
handler.Handle(notificationRequest)
|
||||
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
|
||||
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
|
||||
routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
|
||||
writerMock.AssertNotCalled(t, "UpdateNodebInfo", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
|
||||
}
|
||||
|
||||
func initMocks(t *testing.T) (E2SetupRequestNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock, *mocks.RoutingManagerClientMock) {
|
||||
logger := tests.InitLog(t)
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, GlobalRicId: struct {
|
||||
PlmnId string
|
||||
RicNearRtId string
|
||||
}{PlmnId: "131014", RicNearRtId: "556670"}}
|
||||
rmrMessengerMock := &mocks.RmrMessengerMock{}
|
||||
rmrSender := tests.InitRmrSender(rmrMessengerMock, logger)
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
routingManagerClientMock := &mocks.RoutingManagerClientMock{}
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
|
||||
e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManagerMock, routingManagerClientMock)
|
||||
handler := NewE2SetupRequestNotificationHandler(logger, config, e2tInstancesManagerMock, rmrSender, rnibDataService, e2tAssociationManager)
|
||||
return handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock
|
||||
}
|
||||
|
||||
func assertNewNodebSuccessCalls(readerMock *mocks.RnibReaderMock, t *testing.T, e2tInstancesManagerMock *mocks.E2TInstancesManagerMock, writerMock *mocks.RnibWriterMock, routingManagerClientMock *mocks.RoutingManagerClientMock, rmrMessengerMock *mocks.RmrMessengerMock) {
|
||||
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
|
||||
writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
|
||||
routingManagerClientMock.AssertCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
|
||||
writerMock.AssertCalled(t, "UpdateNodebInfo", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", mock.Anything, mock.Anything)
|
||||
}
|
||||
|
||||
func assertExistingNodebSuccessCalls(readerMock *mocks.RnibReaderMock, t *testing.T, e2tInstancesManagerMock *mocks.E2TInstancesManagerMock, writerMock *mocks.RnibWriterMock, routingManagerClientMock *mocks.RoutingManagerClientMock, rmrMessengerMock *mocks.RmrMessengerMock) {
|
||||
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
|
||||
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
|
||||
routingManagerClientMock.AssertCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
|
||||
writerMock.AssertCalled(t, "UpdateNodebInfo", mock.Anything)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", mock.Anything, mock.Anything)
|
||||
}
|
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/clients"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/models"
|
||||
"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"
|
||||
)
|
||||
|
||||
type E2TermInitNotificationHandler struct {
|
||||
logger *logger.Logger
|
||||
ranDisconnectionManager *managers.RanDisconnectionManager
|
||||
e2tInstancesManager managers.IE2TInstancesManager
|
||||
routingManagerClient clients.IRoutingManagerClient
|
||||
}
|
||||
|
||||
func NewE2TermInitNotificationHandler(logger *logger.Logger, ranDisconnectionManager *managers.RanDisconnectionManager, e2tInstancesManager managers.IE2TInstancesManager, routingManagerClient clients.IRoutingManagerClient) E2TermInitNotificationHandler {
|
||||
return E2TermInitNotificationHandler{
|
||||
logger: logger,
|
||||
ranDisconnectionManager: ranDisconnectionManager,
|
||||
e2tInstancesManager: e2tInstancesManager,
|
||||
routingManagerClient: routingManagerClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (h E2TermInitNotificationHandler) Handle(request *models.NotificationRequest) {
|
||||
unmarshalledPayload := models.E2TermInitPayload{}
|
||||
err := json.Unmarshal(request.Payload, &unmarshalledPayload)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Error unmarshaling E2 Term Init payload: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
e2tAddress := unmarshalledPayload.Address
|
||||
|
||||
if len(e2tAddress) == 0 {
|
||||
h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Empty E2T address received")
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T payload: %s - handling E2_TERM_INIT", unmarshalledPayload)
|
||||
|
||||
e2tInstance, err := h.e2tInstancesManager.GetE2TInstance(e2tAddress)
|
||||
|
||||
if err != nil {
|
||||
_, ok := err.(*common.ResourceNotFoundError)
|
||||
|
||||
if !ok {
|
||||
h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed retrieving E2TInstance. error: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
h.HandleNewE2TInstance(e2tAddress, unmarshalledPayload.PodName)
|
||||
return
|
||||
}
|
||||
|
||||
if len(e2tInstance.AssociatedRanList) == 0 {
|
||||
h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T Address: %s - E2T instance has no associated RANs", e2tInstance.Address)
|
||||
return
|
||||
}
|
||||
|
||||
if e2tInstance.State == entities.ToBeDeleted{
|
||||
h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T Address: %s - E2T instance status is: %s, ignore", e2tInstance.Address, e2tInstance.State)
|
||||
return
|
||||
}
|
||||
|
||||
h.HandleExistingE2TInstance(e2tInstance)
|
||||
|
||||
h.logger.Infof("#E2TermInitNotificationHandler.Handle - Completed handling of E2_TERM_INIT")
|
||||
}
|
||||
|
||||
func (h E2TermInitNotificationHandler) HandleExistingE2TInstance(e2tInstance *entities.E2TInstance) {
|
||||
|
||||
for _, ranName := range e2tInstance.AssociatedRanList {
|
||||
|
||||
if err := h.ranDisconnectionManager.DisconnectRan(ranName); err != nil {
|
||||
if _, ok := err.(*common.ResourceNotFoundError); !ok{
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h E2TermInitNotificationHandler) HandleNewE2TInstance(e2tAddress string, podName string) {
|
||||
|
||||
err := h.routingManagerClient.AddE2TInstance(e2tAddress)
|
||||
|
||||
if err != nil{
|
||||
h.logger.Errorf("#E2TermInitNotificationHandler.HandleNewE2TInstance - e2t address: %s - routing manager failure", e2tAddress)
|
||||
return
|
||||
}
|
||||
|
||||
_ = h.e2tInstancesManager.AddE2TInstance(e2tAddress, podName)
|
||||
}
|
@@ -0,0 +1,478 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"e2mgr/clients"
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"e2mgr/services/rmrsender"
|
||||
"e2mgr/tests"
|
||||
"fmt"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
e2tInitPayload = "{\"address\":\"10.0.2.15\", \"fqdn\":\"\"}"
|
||||
e2tInstanceAddress = "10.0.2.15"
|
||||
podName = "podNAme_test"
|
||||
)
|
||||
|
||||
func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.E2TInstancesManagerMock, *mocks.RoutingManagerClientMock) {
|
||||
|
||||
logger := initLog(t)
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
|
||||
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
|
||||
routingManagerClientMock := &mocks.RoutingManagerClientMock{}
|
||||
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
|
||||
e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
|
||||
e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManagerMock, routingManagerClientMock)
|
||||
|
||||
ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager)
|
||||
handler := NewE2TermInitNotificationHandler(logger, ranDisconnectionManager, e2tInstancesManagerMock, routingManagerClientMock)
|
||||
|
||||
return logger, handler, readerMock, writerMock, e2tInstancesManagerMock, routingManagerClientMock
|
||||
}
|
||||
|
||||
func initRanLostConnectionTestWithRealE2tInstanceManager(t *testing.T) (*logger.Logger, *configuration.Configuration, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
|
||||
|
||||
logger := initLog(t)
|
||||
config := configuration.ParseConfiguration()
|
||||
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
httpClientMock := &mocks.HttpClientMock{}
|
||||
|
||||
routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClientMock)
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
|
||||
e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
|
||||
e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient)
|
||||
ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager)
|
||||
handler := NewE2TermInitNotificationHandler(logger, ranDisconnectionManager, e2tInstancesManager, routingManagerClient)
|
||||
return logger, config, handler, readerMock, writerMock, httpClientMock
|
||||
}
|
||||
|
||||
func TestE2TermInitUnmarshalPayloadFailure(t *testing.T) {
|
||||
_, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte("asd")}
|
||||
handler.Handle(notificationRequest)
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "GetE2TInstance")
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "AddE2TInstance")
|
||||
}
|
||||
|
||||
func TestE2TermInitEmptyE2TAddress(t *testing.T) {
|
||||
_, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte("{\"address\":\"\"}")}
|
||||
handler.Handle(notificationRequest)
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "GetE2TInstance")
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "AddE2TInstance")
|
||||
}
|
||||
|
||||
func TestE2TermInitGetE2TInstanceFailure(t *testing.T) {
|
||||
_, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
|
||||
var e2tInstance *entities.E2TInstance
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewInternalError(fmt.Errorf("internal error")))
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
handler.Handle(notificationRequest)
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "AddE2TInstance")
|
||||
}
|
||||
|
||||
func TestE2TermInitGetE2TInstanceDbFailure(t *testing.T) {
|
||||
_, _, handler, readerMock, writerMock, _ := initRanLostConnectionTestWithRealE2tInstanceManager(t)
|
||||
var e2tInstance *entities.E2TInstance
|
||||
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewInternalError(fmt.Errorf("internal error")))
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
handler.Handle(notificationRequest)
|
||||
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
|
||||
}
|
||||
|
||||
func TestE2TermInitNewE2TInstance(t *testing.T) {
|
||||
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
|
||||
var e2tInstance *entities.E2TInstance
|
||||
|
||||
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewResourceNotFoundError("not found"))
|
||||
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
url := config.RoutingManager.BaseUrl + clients.AddE2TInstanceApiSuffix
|
||||
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
e2tAddresses := []string{}
|
||||
readerMock.On("GetE2TAddresses").Return(e2tAddresses, common.NewResourceNotFoundError(""))
|
||||
|
||||
e2tAddresses = append(e2tAddresses, e2tInstanceAddress)
|
||||
writerMock.On("SaveE2TAddresses", e2tAddresses).Return(nil)
|
||||
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
httpClientMock.AssertCalled(t, "Post", url, mock.Anything, mock.Anything)
|
||||
writerMock.AssertCalled(t, "SaveE2TInstance", mock.Anything)
|
||||
writerMock.AssertCalled(t, "SaveE2TAddresses", e2tAddresses)
|
||||
}
|
||||
|
||||
func TestE2TermInitNewE2TInstance__RoutingManagerError(t *testing.T) {
|
||||
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
|
||||
|
||||
var e2tInstance *entities.E2TInstance
|
||||
|
||||
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewResourceNotFoundError("not found"))
|
||||
|
||||
url := config.RoutingManager.BaseUrl + clients.AddE2TInstanceApiSuffix
|
||||
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{}, errors.New("error"))
|
||||
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 0)
|
||||
}
|
||||
|
||||
func TestE2TermInitExistingE2TInstanceNoAssociatedRans(t *testing.T) {
|
||||
_, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
|
||||
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
handler.Handle(notificationRequest)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceAddress)
|
||||
}
|
||||
|
||||
func TestE2TermInitHandlerSuccessOneRan(t *testing.T) {
|
||||
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
|
||||
|
||||
var rnibErr error
|
||||
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
|
||||
|
||||
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
|
||||
|
||||
var disconnectedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
readerMock.On("GetNodeb", RanName).Return(disconnectedNodeb, rnibErr)
|
||||
|
||||
var updatedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""}
|
||||
writerMock.On("UpdateNodebInfo", updatedNodeb).Return(rnibErr)
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
|
||||
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
|
||||
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix
|
||||
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
|
||||
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1)
|
||||
httpClientMock.AssertNumberOfCalls(t, "Post", 1)
|
||||
}
|
||||
|
||||
func TestE2TermInitHandlerSuccessOneRan_RoutingManagerError(t *testing.T) {
|
||||
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
|
||||
|
||||
var rnibErr error
|
||||
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
|
||||
|
||||
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
|
||||
|
||||
var disconnectedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
readerMock.On("GetNodeb", RanName).Return(disconnectedNodeb, rnibErr)
|
||||
|
||||
var updatedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""}
|
||||
writerMock.On("UpdateNodebInfo", updatedNodeb).Return(rnibErr)
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
|
||||
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
|
||||
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
|
||||
url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix
|
||||
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{}, errors.New("error"))
|
||||
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
|
||||
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1)
|
||||
httpClientMock.AssertNumberOfCalls(t, "Post", 1)
|
||||
}
|
||||
|
||||
func TestE2TermInitHandlerSuccessOneRanShuttingdown(t *testing.T) {
|
||||
_, _, handler, readerMock, writerMock, _ := initRanLostConnectionTestWithRealE2tInstanceManager(t)
|
||||
var rnibErr error
|
||||
|
||||
var initialNodeb = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
|
||||
|
||||
var argNodeb = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
|
||||
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
|
||||
}
|
||||
|
||||
func TestE2TermInitHandlerSuccessOneRan_ToBeDeleted(t *testing.T) {
|
||||
_, _, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
|
||||
var rnibErr error
|
||||
|
||||
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
|
||||
|
||||
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
|
||||
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
|
||||
e2tInstance.State = entities.ToBeDeleted
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
|
||||
|
||||
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
httpClientMock.AssertNotCalled(t, "Post", mock.Anything, mock.Anything, mock.Anything)
|
||||
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
|
||||
}
|
||||
|
||||
func TestE2TermInitHandlerSuccessTwoRans(t *testing.T) {
|
||||
|
||||
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
|
||||
|
||||
var rnibErr error
|
||||
test2 := "test2"
|
||||
|
||||
//First RAN
|
||||
var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
var disconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
readerMock.On("GetNodeb", RanName).Return(firstRan, rnibErr).Return(disconnectedFirstRan, rnibErr)
|
||||
|
||||
var updatedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
writerMock.On("UpdateNodebInfo", updatedFirstRan).Return(rnibErr)
|
||||
|
||||
var updatedDisconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""}
|
||||
writerMock.On("UpdateNodebInfo", updatedDisconnectedFirstRan).Return(rnibErr)
|
||||
|
||||
//Second RAN
|
||||
var secondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
var disconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
readerMock.On("GetNodeb", test2).Return(secondRan, rnibErr).Return(disconnectedSecondRan, rnibErr)
|
||||
|
||||
var updatedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
writerMock.On("UpdateNodebInfo", updatedSecondRan).Return(rnibErr)
|
||||
|
||||
var updatedDisconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: ""}
|
||||
writerMock.On("UpdateNodebInfo", updatedDisconnectedSecondRan).Return(rnibErr)
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2)
|
||||
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
|
||||
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix
|
||||
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 4)
|
||||
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 2)
|
||||
httpClientMock.AssertNumberOfCalls(t, "Post", 2)
|
||||
}
|
||||
|
||||
func TestE2TermInitHandlerSuccessTwoRansSecondRanShutdown(t *testing.T) {
|
||||
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
|
||||
|
||||
var rnibErr error
|
||||
test2 := "test2"
|
||||
|
||||
//First RAN
|
||||
var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
var disconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
readerMock.On("GetNodeb", RanName).Return(firstRan, rnibErr).Return(disconnectedFirstRan, rnibErr)
|
||||
|
||||
var updatedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
writerMock.On("UpdateNodebInfo", updatedFirstRan).Return(rnibErr)
|
||||
|
||||
var updatedDisconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""}
|
||||
writerMock.On("UpdateNodebInfo", updatedDisconnectedFirstRan).Return(rnibErr)
|
||||
|
||||
//Second RAN
|
||||
var secondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
readerMock.On("GetNodeb", test2).Return(secondRan, rnibErr)
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
|
||||
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
|
||||
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix
|
||||
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
|
||||
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1)
|
||||
httpClientMock.AssertNumberOfCalls(t, "Post", 1)
|
||||
}
|
||||
|
||||
func TestE2TermInitHandlerSuccessTwoRansFirstNotFoundFailure(t *testing.T) {
|
||||
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
|
||||
|
||||
var rnibErr error
|
||||
test2 := "test2"
|
||||
|
||||
//First RAN
|
||||
var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
readerMock.On("GetNodeb", RanName).Return(firstRan, common.NewResourceNotFoundError("not found"))
|
||||
|
||||
//Second RAN
|
||||
var secondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
var disconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
readerMock.On("GetNodeb", test2).Return(secondRan, rnibErr).Return(disconnectedSecondRan, rnibErr)
|
||||
|
||||
var updatedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
writerMock.On("UpdateNodebInfo", updatedSecondRan).Return(rnibErr)
|
||||
|
||||
var updatedDisconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: ""}
|
||||
writerMock.On("UpdateNodebInfo", updatedDisconnectedSecondRan).Return(rnibErr)
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2)
|
||||
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
|
||||
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
|
||||
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix
|
||||
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
|
||||
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
|
||||
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1)
|
||||
httpClientMock.AssertNumberOfCalls(t, "Post", 1)
|
||||
}
|
||||
|
||||
func TestE2TermInitHandlerSuccessTwoRansFirstRnibInternalErrorFailure(t *testing.T) {
|
||||
_, _, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
|
||||
|
||||
test2 := "test2"
|
||||
|
||||
//First RAN
|
||||
var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
|
||||
readerMock.On("GetNodeb", RanName).Return(firstRan, common.NewInternalError(fmt.Errorf("internal error")))
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2)
|
||||
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
|
||||
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
|
||||
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 0)
|
||||
httpClientMock.AssertNumberOfCalls(t, "Post", 0)
|
||||
}
|
||||
|
||||
func TestE2TermInitHandlerSuccessZeroRans(t *testing.T) {
|
||||
_, handler, _, writerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
|
||||
}
|
||||
|
||||
func TestE2TermInitHandlerFailureGetNodebInternalError(t *testing.T) {
|
||||
_, handler, readerMock, writerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
|
||||
|
||||
var nodebInfo *entities.NodebInfo
|
||||
readerMock.On("GetNodeb", "test1").Return(nodebInfo, common.NewInternalError(fmt.Errorf("internal error")))
|
||||
|
||||
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
|
||||
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, "test1")
|
||||
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
|
||||
handler.Handle(notificationRequest)
|
||||
|
||||
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
|
||||
}
|
||||
|
||||
// TODO: extract to test_utils
|
||||
func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
|
||||
rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
|
||||
rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
|
||||
return rmrsender.NewRmrSender(log, rmrMessenger)
|
||||
}
|
||||
|
||||
// TODO: extract to test_utils
|
||||
func initLog(t *testing.T) *logger.Logger {
|
||||
log, err := logger.InitLogger(logger.InfoLevel)
|
||||
if err != nil {
|
||||
t.Errorf("#delete_all_request_handler_test.TestHandleSuccessFlow - failed to initialize logger, error: %s", err)
|
||||
}
|
||||
return log
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Copyright 2019 AT&T Intellectual Property
|
||||
// Copyright 2019 Nokia
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
// platform project (RICP).
|
||||
|
||||
package rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/models"
|
||||
"e2mgr/services"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type E2TKeepAliveResponseHandler struct {
|
||||
logger *logger.Logger
|
||||
rnibDataService services.RNibDataService
|
||||
e2TInstancesManager managers.IE2TInstancesManager
|
||||
}
|
||||
|
||||
func NewE2TKeepAliveResponseHandler(logger *logger.Logger, rnibDataService services.RNibDataService, e2TInstancesManager managers.IE2TInstancesManager) E2TKeepAliveResponseHandler {
|
||||
return E2TKeepAliveResponseHandler{
|
||||
logger: logger,
|
||||
rnibDataService: rnibDataService,
|
||||
e2TInstancesManager: e2TInstancesManager,
|
||||
}
|
||||
}
|
||||
|
||||
func (h E2TKeepAliveResponseHandler) Handle(request *models.NotificationRequest) {
|
||||
unmarshalledPayload := models.E2TKeepAlivePayload{}
|
||||
err := json.Unmarshal(request.Payload, &unmarshalledPayload)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Errorf("#E2TKeepAliveResponseHandler.Handle - Error unmarshaling RMR request payload: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
_ = h.e2TInstancesManager.ResetKeepAliveTimestamp(unmarshalledPayload.Address)
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// Copyright 2019 AT&T Intellectual Property
|
||||
// Copyright 2019 Nokia
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
// platform project (RICP).
|
||||
|
||||
package rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/models"
|
||||
"e2mgr/services"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func initE2TKeepAliveTest(t *testing.T) (*logger.Logger, E2TKeepAliveResponseHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.E2TInstancesManagerMock) {
|
||||
|
||||
logger := initLog(t)
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
|
||||
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
|
||||
e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
|
||||
handler := NewE2TKeepAliveResponseHandler(logger, rnibDataService, e2tInstancesManagerMock)
|
||||
return logger, handler, readerMock, writerMock, e2tInstancesManagerMock
|
||||
}
|
||||
|
||||
func TestE2TKeepAliveUnmarshalPayloadFailure(t *testing.T) {
|
||||
_, handler, _, _, e2tInstancesManagerMock := initE2TKeepAliveTest(t)
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte("asd")}
|
||||
handler.Handle(notificationRequest)
|
||||
e2tInstancesManagerMock.AssertNotCalled(t, "ResetKeepAliveTimestamp")
|
||||
}
|
||||
|
||||
func TestE2TKeepAliveUnmarshalPayloadSuccess(t *testing.T) {
|
||||
_, handler, _, _, e2tInstancesManagerMock := initE2TKeepAliveTest(t)
|
||||
|
||||
jsonRequest := "{\"address\":\"10.10.2.15:9800\"}"
|
||||
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(jsonRequest)}
|
||||
|
||||
e2tInstancesManagerMock.On("ResetKeepAliveTimestamp", "10.10.2.15:9800").Return(nil)
|
||||
handler.Handle(notificationRequest)
|
||||
e2tInstancesManagerMock.AssertCalled(t, "ResetKeepAliveTimestamp", "10.10.2.15:9800")
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
/*import (
|
||||
"e2mgr/converters"
|
||||
"e2mgr/e2pdus"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/models"
|
||||
"e2mgr/services"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"time"
|
||||
)
|
||||
|
||||
type EnbLoadInformationNotificationHandler struct {
|
||||
logger *logger.Logger
|
||||
rnibDataService services.RNibDataService
|
||||
//extractor converters.IEnbLoadInformationExtractor
|
||||
}
|
||||
|
||||
func NewEnbLoadInformationNotificationHandler(logger *logger.Logger, rnibDataService services.RNibDataService, extractor converters.IEnbLoadInformationExtractor) EnbLoadInformationNotificationHandler {
|
||||
return EnbLoadInformationNotificationHandler{
|
||||
logger: logger,
|
||||
rnibDataService: rnibDataService,
|
||||
extractor: extractor,
|
||||
}
|
||||
}
|
||||
|
||||
func elapsed(startTime time.Time) float64 {
|
||||
return float64(time.Since(startTime)) / float64(time.Millisecond)
|
||||
}
|
||||
|
||||
func (h EnbLoadInformationNotificationHandler) Handle(request *models.NotificationRequest) {
|
||||
|
||||
pdu, err := converters.UnpackX2apPdu(h.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Unpack failed. Error: %v", request.RanName, err)
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Debugf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Unpacked message successfully", request.RanName)
|
||||
|
||||
ranLoadInformation := &entities.RanLoadInformation{LoadTimestamp: uint64(request.StartTime.UnixNano())}
|
||||
|
||||
err = h.extractor.ExtractAndBuildRanLoadInformation(pdu, ranLoadInformation)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Failed at ExtractAndBuildRanLoadInformation. Error: %v", request.RanName, err)
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Debugf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Successfully done with extracting and building RAN load information. elapsed: %f ms", request.RanName, elapsed(request.StartTime))
|
||||
|
||||
rnibErr := h.rnibDataService.SaveRanLoadInformation(request.RanName, ranLoadInformation)
|
||||
|
||||
if rnibErr != nil {
|
||||
h.logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Failed saving RAN load information. Error: %v", request.RanName, rnibErr)
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Infof("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Successfully saved RAN load information to RNIB. elapsed: %f ms", request.RanName, elapsed(request.StartTime))
|
||||
}*/
|
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
/*import (
|
||||
"e2mgr/models"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
FullUperPdu string = "004c07080004001980da0100075bde017c148003d5a8205000017c180003d5a875555403331420000012883a0003547400cd20002801ea16007c1f07c1f107c1f0781e007c80800031a02c000c88199040a00352083669190000d8908020000be0c4001ead4016e007ab50100002f8320067ab5005b8c1ead5070190c00001d637805f220000f56a081400005f020000f56a1d555400ccc508002801ea16007c1f07c1f107c1f0781e007c80800031a02c000c88199040a00352083669190000d8908020000be044001ead4016e007ab50100002f8120067ab5005b8c1ead5070190c00000"
|
||||
FullAperPdu string = "" // TODO: populate and use it
|
||||
BasicUperPdu string = "004898000400190d0000074200017c148003d5a80000"
|
||||
BasicAperPdu string = "" // TODO: populate and use it
|
||||
GarbagePdu string = "12312312"
|
||||
)
|
||||
|
||||
func createNotificationRequest(ranName string, transactionId []byte, packedPdu string) (*models.NotificationRequest, error) {
|
||||
var packedByteSlice []byte
|
||||
|
||||
_, err := fmt.Sscanf(packedPdu, "%x", &packedByteSlice)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return models.NewNotificationRequest(ranName, packedByteSlice, time.Now(), transactionId, nil), nil
|
||||
}
|
||||
|
||||
func createNotificationRequestAndHandle(ranName string, transactionId []byte, loadInformationHandler EnbLoadInformationNotificationHandler, pdu string) error {
|
||||
notificationRequest, err := createNotificationRequest(ranName, transactionId, pdu)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loadInformationHandler.Handle(notificationRequest)
|
||||
return nil
|
||||
}*/
|
||||
|
||||
//func TestLoadInformationHandlerSuccess(t *testing.T) {
|
||||
// log, err := logger.InitLogger(logger.InfoLevel)
|
||||
// if err != nil {
|
||||
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerSuccess - failed to initialize logger, error: %v", err)
|
||||
// }
|
||||
//
|
||||
// inventoryName := "testRan"
|
||||
//
|
||||
// writerMock := &mocks.RnibWriterMock{}
|
||||
// rnibWriterProvider := func() rNibWriter.RNibWriter {
|
||||
// return writerMock
|
||||
// }
|
||||
//
|
||||
// var rnibErr error
|
||||
// writerMock.On("SaveRanLoadInformation",inventoryName, mock.Anything).Return(rnibErr)
|
||||
//
|
||||
// loadInformationHandler := NewEnbLoadInformationNotificationHandler(rnibWriterProvider)
|
||||
//
|
||||
// var packedExampleByteSlice []byte
|
||||
// _, err = fmt.Sscanf(FullUperPdu, "%x", &packedExampleByteSlice)
|
||||
// notificationRequest := models.NewNotificationRequest(inventoryName, packedExampleByteSlice, time.Now(), " 881828026419")
|
||||
// loadInformationHandler.Handle(log, notificationRequest)
|
||||
//
|
||||
// writerMock.AssertNumberOfCalls(t, "SaveRanLoadInformation", 1)
|
||||
//}
|
||||
//
|
||||
//func TestLoadInformationHandlerPayloadFailure(t *testing.T) {
|
||||
// log, err := logger.InitLogger(logger.InfoLevel)
|
||||
// if err != nil {
|
||||
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerPayloadFailure - failed to initialize logger, error: %v", err)
|
||||
// }
|
||||
//
|
||||
// inventoryName := "testRan"
|
||||
//
|
||||
// writerMock := &mocks.RnibWriterMock{}
|
||||
// rnibWriterProvider := func() rNibWriter.RNibWriter {
|
||||
// return writerMock
|
||||
// }
|
||||
//
|
||||
// var rnibErr error
|
||||
// writerMock.On("SaveRanLoadInformation",inventoryName, mock.Anything).Return(rnibErr)
|
||||
//
|
||||
// loadInformationHandler := NewEnbLoadInformationNotificationHandler(rnibWriterProvider)
|
||||
//
|
||||
// var packedExampleByteSlice []byte
|
||||
// _, err = fmt.Sscanf(GarbagePdu, "%x", &packedExampleByteSlice)
|
||||
// notificationRequest := models.NewNotificationRequest(inventoryName, packedExampleByteSlice, time.Now(), " 881828026419")
|
||||
// loadInformationHandler.Handle(log, notificationRequest)
|
||||
//
|
||||
// writerMock.AssertNumberOfCalls(t, "SaveRanLoadInformation", 0)
|
||||
//}
|
||||
|
||||
// Integration test
|
||||
//func TestLoadInformationHandlerOverrideSuccess(t *testing.T) {
|
||||
// log, err := logger.InitLogger(logger.InfoLevel)
|
||||
// if err != nil {
|
||||
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerOverrideSuccess - failed to initialize logger, error: %s", err)
|
||||
// }
|
||||
//
|
||||
// rNibWriter.Init("e2Manager", 1)
|
||||
// defer rNibWriter.Close()
|
||||
// reader.Init("e2Manager", 1)
|
||||
// defer reader.Close()
|
||||
// loadInformationHandler := NewEnbLoadInformationNotificationHandler(rNibWriter.GetRNibWriter)
|
||||
//
|
||||
// err = createNotificationRequestAndHandle("ranName", " 881828026419", loadInformationHandler, FullUperPdu)
|
||||
//
|
||||
// if err != nil {
|
||||
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerOverrideSuccess - failed creating NotificationRequest, error: %v", err)
|
||||
// }
|
||||
//
|
||||
// err = createNotificationRequestAndHandle("ranName", " 881828026419", loadInformationHandler, BasicUperPdu)
|
||||
//
|
||||
// if err != nil {
|
||||
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerOverrideSuccess - failed creating NotificationRequest, error: %v", err)
|
||||
// }
|
||||
//
|
||||
// ranLoadInformation, rnibErr := reader.GetRNibReader().GetRanLoadInformation("ranName")
|
||||
//
|
||||
// if (rnibErr != nil) {
|
||||
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerOverrideSuccess - RNIB error: %v", err)
|
||||
// }
|
||||
//
|
||||
// assert.Len(t, ranLoadInformation.CellLoadInfos, 1)
|
||||
//}
|
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// Copyright 2019 AT&T Intellectual Property
|
||||
// Copyright 2019 Nokia
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
// platform project (RICP).
|
||||
|
||||
|
||||
package rmrmsghandlers
|
||||
|
||||
// #cgo CFLAGS: -I../../3rdparty/asn1codec/inc/ -I../../3rdparty/asn1codec/e2ap_engine/
|
||||
// #cgo LDFLAGS: -L ../../3rdparty/asn1codec/lib/ -L../../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
|
||||
// #include <asn1codec_utils.h>
|
||||
// #include <configuration_update_wrapper.h>
|
||||
import "C"
|
||||
import (
|
||||
"e2mgr/converters"
|
||||
"e2mgr/e2pdus"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services/rmrsender"
|
||||
"e2mgr/utils"
|
||||
)
|
||||
|
||||
type EndcConfigurationUpdateHandler struct {
|
||||
logger *logger.Logger
|
||||
rmrSender *rmrsender.RmrSender
|
||||
}
|
||||
|
||||
func NewEndcConfigurationUpdateHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender) EndcConfigurationUpdateHandler {
|
||||
return EndcConfigurationUpdateHandler{
|
||||
logger: logger,
|
||||
rmrSender: rmrSender,
|
||||
}
|
||||
}
|
||||
|
||||
func (h EndcConfigurationUpdateHandler) Handle(request *models.NotificationRequest) {
|
||||
|
||||
refinedMessage, err := converters.UnpackX2apPduAndRefine(h.logger, e2pdus.MaxAsn1CodecAllocationBufferSize /*allocation buffer*/, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Errorf("#endc_configuration_update_handler.Handle - unpack failed. Error: %v", err)
|
||||
|
||||
msg := models.NewRmrMessage(rmrCgo.RIC_ENDC_CONF_UPDATE_FAILURE, request.RanName, e2pdus.PackedEndcConfigurationUpdateFailure, request.TransactionId, request.GetMsgSrc())
|
||||
_ = h.rmrSender.Send(msg)
|
||||
|
||||
h.logger.Infof("#EndcConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling endc configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Infof("#endc_configuration_update_handler.Handle - Endc configuration update initiating message received")
|
||||
h.logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update initiating message payload: %s", refinedMessage.PduPrint)
|
||||
msg := models.NewRmrMessage(rmrCgo.RIC_ENDC_CONF_UPDATE_ACK, request.RanName, e2pdus.PackedEndcConfigurationUpdateAck, request.TransactionId, request.GetMsgSrc())
|
||||
_ = h.rmrSender.Send(msg)
|
||||
|
||||
h.logger.Infof("#EndcConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling endc configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
}
|
@@ -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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const PackedEndcConfigurationUpdateAck = "2025000a00000100f70003000000"
|
||||
const PackedEndcConfigurationUpdateFailure = "402500080000010005400142"
|
||||
|
||||
func initEndcConfigurationUpdateHandlerTest(t *testing.T) (EndcConfigurationUpdateHandler, *mocks.RmrMessengerMock) {
|
||||
log := initLog(t)
|
||||
rmrMessengerMock := &mocks.RmrMessengerMock{}
|
||||
rmrSender := initRmrSender(rmrMessengerMock, log)
|
||||
h := NewEndcConfigurationUpdateHandler(log, rmrSender)
|
||||
return h, rmrMessengerMock
|
||||
}
|
||||
|
||||
func TestHandleEndcConfigUpdateSuccess(t *testing.T) {
|
||||
h, rmrMessengerMock := initEndcConfigurationUpdateHandlerTest(t)
|
||||
|
||||
ranName := "test"
|
||||
xAction := []byte("123456aa")
|
||||
|
||||
var payload []byte
|
||||
_, _ = fmt.Sscanf(PackedEndcConfigurationUpdateAck, "%x", &payload)
|
||||
var msgSrc unsafe.Pointer
|
||||
|
||||
mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_CONF_UPDATE_ACK, len(payload), ranName, &payload, &xAction, msgSrc)
|
||||
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now(),
|
||||
TransactionId: *mBuf.XAction}
|
||||
var err error
|
||||
rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, err)
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
|
||||
}
|
||||
|
||||
func TestHandleEndcConfigUpdateFailure(t *testing.T) {
|
||||
h, rmrMessengerMock := initEndcConfigurationUpdateHandlerTest(t)
|
||||
|
||||
ranName := "test"
|
||||
xAction := []byte("123456aa")
|
||||
|
||||
var payload []byte
|
||||
_, _ = fmt.Sscanf(PackedEndcConfigurationUpdateFailure, "%x", &payload)
|
||||
var msgSrc unsafe.Pointer
|
||||
|
||||
mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_CONF_UPDATE_FAILURE, len(payload), ranName, &payload, &xAction, msgSrc)
|
||||
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: 0, Payload: []byte{0}, StartTime: time.Now(),
|
||||
TransactionId: *mBuf.XAction}
|
||||
rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, fmt.Errorf("send failure"))
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/models"
|
||||
)
|
||||
|
||||
type NotificationHandler interface {
|
||||
Handle(*models.NotificationRequest)
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Copyright 2019 AT&T Intellectual Property
|
||||
// Copyright 2019 Nokia
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
// platform project (RICP).
|
||||
|
||||
|
||||
package rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/models"
|
||||
)
|
||||
|
||||
type RanLostConnectionHandler struct {
|
||||
ranDisconnectionManager managers.IRanDisconnectionManager
|
||||
logger *logger.Logger
|
||||
}
|
||||
|
||||
func NewRanLostConnectionHandler(logger *logger.Logger, ranDisconnectionManager managers.IRanDisconnectionManager) RanLostConnectionHandler {
|
||||
return RanLostConnectionHandler{
|
||||
logger: logger,
|
||||
ranDisconnectionManager: ranDisconnectionManager,
|
||||
}
|
||||
}
|
||||
func (h RanLostConnectionHandler) Handle(request *models.NotificationRequest) {
|
||||
|
||||
ranName := request.RanName
|
||||
|
||||
h.logger.Warnf("#RanLostConnectionHandler.Handle - RAN name: %s - Received lost connection notification", ranName)
|
||||
|
||||
_ = h.ranDisconnectionManager.DisconnectRan(ranName)
|
||||
}
|
@@ -0,0 +1,133 @@
|
||||
//// 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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"e2mgr/clients"
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/models"
|
||||
"e2mgr/services"
|
||||
"encoding/json"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
"github.com/pkg/errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const ranName = "test"
|
||||
const e2tAddress = "10.10.2.15:9800"
|
||||
|
||||
func TestLostConnectionHandlerSuccess(t *testing.T) {
|
||||
logger, _ := logger.InitLogger(logger.InfoLevel)
|
||||
|
||||
notificationRequest := models.NotificationRequest{RanName: ranName}
|
||||
ranDisconnectionManagerMock := &mocks.RanDisconnectionManagerMock{}
|
||||
ranDisconnectionManagerMock.On("DisconnectRan", ranName).Return(nil)
|
||||
handler := NewRanLostConnectionHandler(logger, ranDisconnectionManagerMock)
|
||||
handler.Handle(¬ificationRequest)
|
||||
ranDisconnectionManagerMock.AssertCalled(t, "DisconnectRan", ranName)
|
||||
}
|
||||
|
||||
func TestLostConnectionHandlerFailure(t *testing.T) {
|
||||
logger, _ := logger.InitLogger(logger.InfoLevel)
|
||||
|
||||
notificationRequest := models.NotificationRequest{RanName: ranName}
|
||||
ranDisconnectionManagerMock := &mocks.RanDisconnectionManagerMock{}
|
||||
ranDisconnectionManagerMock.On("DisconnectRan", ranName).Return(errors.New("error"))
|
||||
handler := NewRanLostConnectionHandler(logger, ranDisconnectionManagerMock)
|
||||
handler.Handle(¬ificationRequest)
|
||||
ranDisconnectionManagerMock.AssertCalled(t, "DisconnectRan", ranName)
|
||||
}
|
||||
|
||||
func setupLostConnectionHandlerTestWithRealDisconnectionManager(t *testing.T, isSuccessfulHttpPost bool) (RanLostConnectionHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
|
||||
logger, _ := logger.InitLogger(logger.InfoLevel)
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
|
||||
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
|
||||
httpClientMock := &mocks.HttpClientMock{}
|
||||
routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClientMock)
|
||||
e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient)
|
||||
ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager)
|
||||
handler := NewRanLostConnectionHandler(logger, ranDisconnectionManager)
|
||||
|
||||
origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, AssociatedE2TInstanceAddress: e2tAddress}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
|
||||
updatedNodebInfo1 := *origNodebInfo
|
||||
updatedNodebInfo1.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
writerMock.On("UpdateNodebInfo", &updatedNodebInfo1).Return(rnibErr)
|
||||
updatedNodebInfo2 := *origNodebInfo
|
||||
updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
|
||||
updatedNodebInfo2.AssociatedE2TInstanceAddress = ""
|
||||
writerMock.On("UpdateNodebInfo", &updatedNodebInfo2).Return(rnibErr)
|
||||
e2tInstance := &entities.E2TInstance{Address: e2tAddress, AssociatedRanList: []string{ranName}}
|
||||
readerMock.On("GetE2TInstance", e2tAddress).Return(e2tInstance, nil)
|
||||
e2tInstanceToSave := *e2tInstance
|
||||
e2tInstanceToSave.AssociatedRanList = []string{}
|
||||
writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil)
|
||||
mockHttpClient(httpClientMock, isSuccessfulHttpPost)
|
||||
|
||||
return handler, readerMock, writerMock, httpClientMock
|
||||
}
|
||||
|
||||
func mockHttpClient(httpClientMock *mocks.HttpClientMock, isSuccessful bool) {
|
||||
data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(e2tAddress, RanName)}
|
||||
marshaled, _ := json.Marshal(data)
|
||||
body := bytes.NewBuffer(marshaled)
|
||||
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
|
||||
var respStatusCode int
|
||||
if isSuccessful {
|
||||
respStatusCode = http.StatusCreated
|
||||
} else {
|
||||
respStatusCode = http.StatusBadRequest
|
||||
}
|
||||
httpClientMock.On("Post", clients.DissociateRanE2TInstanceApiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
|
||||
}
|
||||
|
||||
func TestLostConnectionHandlerFailureWithRealDisconnectionManager(t *testing.T) {
|
||||
handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTestWithRealDisconnectionManager(t, false)
|
||||
|
||||
notificationRequest := models.NotificationRequest{RanName: ranName}
|
||||
handler.Handle(¬ificationRequest)
|
||||
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
|
||||
}
|
||||
|
||||
func TestLostConnectionHandlerSuccessWithRealDisconnectionManager(t *testing.T) {
|
||||
handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTestWithRealDisconnectionManager(t, true)
|
||||
|
||||
notificationRequest := models.NotificationRequest{RanName: ranName}
|
||||
handler.Handle(¬ificationRequest)
|
||||
|
||||
readerMock.AssertExpectations(t)
|
||||
writerMock.AssertExpectations(t)
|
||||
httpClientMock.AssertExpectations(t)
|
||||
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/enums"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"e2mgr/utils"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
)
|
||||
|
||||
type SetupResponseNotificationHandler struct {
|
||||
logger *logger.Logger
|
||||
rnibDataService services.RNibDataService
|
||||
setupResponseManager managers.ISetupResponseManager
|
||||
ranStatusChangeManager managers.IRanStatusChangeManager
|
||||
msgType int
|
||||
}
|
||||
|
||||
var msgTypeToMsgName = map[int]string{
|
||||
rmrCgo.RIC_X2_SETUP_RESP: "X2 Setup Response",
|
||||
rmrCgo.RIC_X2_SETUP_FAILURE: "X2 Setup Failure Response",
|
||||
rmrCgo.RIC_ENDC_X2_SETUP_RESP: "ENDC Setup Response",
|
||||
rmrCgo.RIC_ENDC_X2_SETUP_FAILURE: "ENDC Setup Failure Response",
|
||||
}
|
||||
|
||||
func NewSetupResponseNotificationHandler(logger *logger.Logger, rnibDataService services.RNibDataService, setupResponseManager managers.ISetupResponseManager, ranStatusChangeManager managers.IRanStatusChangeManager, msgType int) SetupResponseNotificationHandler {
|
||||
return SetupResponseNotificationHandler{
|
||||
logger: logger,
|
||||
rnibDataService: rnibDataService,
|
||||
setupResponseManager: setupResponseManager,
|
||||
ranStatusChangeManager: ranStatusChangeManager,
|
||||
msgType: msgType,
|
||||
}
|
||||
}
|
||||
|
||||
func (h SetupResponseNotificationHandler) Handle(request *models.NotificationRequest) {
|
||||
msgName := msgTypeToMsgName[h.msgType]
|
||||
h.logger.Infof("#SetupResponseNotificationHandler - RAN name: %s - Received %s notification", request.RanName, msgName)
|
||||
|
||||
inventoryName := request.RanName
|
||||
|
||||
nodebInfo, rnibErr := h.rnibDataService.GetNodeb(inventoryName)
|
||||
|
||||
if rnibErr != nil {
|
||||
h.logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Error fetching RAN from rNib: %v", request.RanName, rnibErr)
|
||||
return
|
||||
}
|
||||
|
||||
if !isConnectionStatusValid(nodebInfo.ConnectionStatus) {
|
||||
h.logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Invalid RAN connection status: %s", request.RanName, nodebInfo.ConnectionStatus)
|
||||
return
|
||||
}
|
||||
|
||||
nbIdentity := &entities.NbIdentity{InventoryName: inventoryName}
|
||||
err := h.setupResponseManager.PopulateNodebByPdu(h.logger, nbIdentity, nodebInfo, request.Payload)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rnibErr = h.rnibDataService.SaveNodeb(nbIdentity, nodebInfo)
|
||||
|
||||
if rnibErr != nil {
|
||||
h.logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Error saving RAN to rNib: %v", request.RanName, rnibErr)
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Infof("#SetupResponseNotificationHandler - RAN name: %s - Successfully saved RAN to rNib", request.RanName)
|
||||
h.logger.Infof("#SetupResponseNotificationHandler - Summary: elapsed time for receiving and handling setup response message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
|
||||
if !isSuccessSetupResponseMessage(h.msgType) {
|
||||
return
|
||||
}
|
||||
|
||||
_ = h.ranStatusChangeManager.Execute(rmrCgo.RAN_CONNECTED, enums.RIC_TO_RAN, nodebInfo)
|
||||
}
|
||||
|
||||
func isConnectionStatusValid(connectionStatus entities.ConnectionStatus) bool {
|
||||
return connectionStatus == entities.ConnectionStatus_CONNECTING || connectionStatus == entities.ConnectionStatus_CONNECTED
|
||||
}
|
||||
|
||||
func isSuccessSetupResponseMessage(msgType int) bool {
|
||||
return msgType == rmrCgo.RIC_X2_SETUP_RESP || msgType == rmrCgo.RIC_ENDC_X2_SETUP_RESP
|
||||
}
|
@@ -0,0 +1,339 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/converters"
|
||||
"e2mgr/e2managererrors"
|
||||
"e2mgr/enums"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"e2mgr/services/rmrsender"
|
||||
"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/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
RanName = "test"
|
||||
X2SetupResponsePackedPdu = "2006002a000002001500080002f82900007a8000140017000000630002f8290007ab50102002f829000001000133"
|
||||
EndcSetupResponsePackedPdu = "202400808e00000100f600808640000200fc00090002f829504a952a0a00fd007200010c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a000211e148033e4e5e4c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a00021a0044033e4e5e000000002c001e3f271f2e3d4ff0031e3f274400010000150400000a00020000"
|
||||
X2SetupFailureResponsePackedPdu = "4006001a0000030005400200000016400100001140087821a00000008040"
|
||||
EndcSetupFailureResponsePackedPdu = "4024001a0000030005400200000016400100001140087821a00000008040"
|
||||
)
|
||||
|
||||
type setupSuccessResponseTestCase struct {
|
||||
packedPdu string
|
||||
setupResponseManager managers.ISetupResponseManager
|
||||
msgType int
|
||||
saveNodebMockError error
|
||||
sendMsgError error
|
||||
statusChangeMbuf *rmrCgo.MBuf
|
||||
}
|
||||
|
||||
type setupFailureResponseTestCase struct {
|
||||
packedPdu string
|
||||
setupResponseManager managers.ISetupResponseManager
|
||||
msgType int
|
||||
saveNodebMockError error
|
||||
}
|
||||
|
||||
type setupResponseTestContext struct {
|
||||
logger *logger.Logger
|
||||
readerMock *mocks.RnibReaderMock
|
||||
writerMock *mocks.RnibWriterMock
|
||||
rnibDataService services.RNibDataService
|
||||
setupResponseManager managers.ISetupResponseManager
|
||||
ranStatusChangeManager managers.IRanStatusChangeManager
|
||||
rmrSender *rmrsender.RmrSender
|
||||
rmrMessengerMock *mocks.RmrMessengerMock
|
||||
}
|
||||
|
||||
func NewSetupResponseTestContext(manager managers.ISetupResponseManager) *setupResponseTestContext {
|
||||
logger, _ := logger.InitLogger(logger.InfoLevel)
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
writerMock := &mocks.RnibWriterMock{}
|
||||
|
||||
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
|
||||
|
||||
rmrMessengerMock := &mocks.RmrMessengerMock{}
|
||||
rmrSender := initRmrSender(rmrMessengerMock, logger)
|
||||
|
||||
ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
|
||||
|
||||
return &setupResponseTestContext{
|
||||
logger: logger,
|
||||
readerMock: readerMock,
|
||||
writerMock: writerMock,
|
||||
rnibDataService: rnibDataService,
|
||||
setupResponseManager: manager,
|
||||
ranStatusChangeManager: ranStatusChangeManager,
|
||||
rmrMessengerMock: rmrMessengerMock,
|
||||
rmrSender: rmrSender,
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupResponseGetNodebFailure(t *testing.T) {
|
||||
notificationRequest := models.NotificationRequest{RanName: RanName}
|
||||
testContext := NewSetupResponseTestContext(nil)
|
||||
handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, &managers.X2SetupResponseManager{}, testContext.ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)
|
||||
testContext.readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewInternalError(errors.New("Error")))
|
||||
handler.Handle(¬ificationRequest)
|
||||
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
|
||||
testContext.writerMock.AssertNotCalled(t, "SaveNodeb")
|
||||
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func TestSetupResponseInvalidConnectionStatus(t *testing.T) {
|
||||
ranName := "test"
|
||||
notificationRequest := models.NotificationRequest{RanName: ranName}
|
||||
testContext := NewSetupResponseTestContext(nil)
|
||||
handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, &managers.X2SetupResponseManager{}, testContext.ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)
|
||||
var rnibErr error
|
||||
testContext.readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN}, rnibErr)
|
||||
handler.Handle(¬ificationRequest)
|
||||
testContext.readerMock.AssertCalled(t, "GetNodeb", ranName)
|
||||
testContext.writerMock.AssertNotCalled(t, "SaveNodeb")
|
||||
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func executeHandleSetupSuccessResponse(t *testing.T, tc setupSuccessResponseTestCase) (*setupResponseTestContext, *entities.NodebInfo) {
|
||||
var payload []byte
|
||||
_, err := fmt.Sscanf(tc.packedPdu, "%x", &payload)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
|
||||
}
|
||||
|
||||
notificationRequest := models.NotificationRequest{RanName: RanName, Payload: payload}
|
||||
testContext := NewSetupResponseTestContext(tc.setupResponseManager)
|
||||
|
||||
handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, testContext.setupResponseManager, testContext.ranStatusChangeManager, tc.msgType)
|
||||
|
||||
var rnibErr error
|
||||
|
||||
nodebInfo := &entities.NodebInfo{
|
||||
ConnectionStatus: entities.ConnectionStatus_CONNECTING,
|
||||
RanName: RanName,
|
||||
Ip: "10.0.2.2",
|
||||
Port: 1231,
|
||||
}
|
||||
|
||||
testContext.readerMock.On("GetNodeb", RanName).Return(nodebInfo, rnibErr)
|
||||
testContext.writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(tc.saveNodebMockError)
|
||||
testContext.rmrMessengerMock.On("SendMsg", tc.statusChangeMbuf, true).Return(&rmrCgo.MBuf{}, tc.sendMsgError)
|
||||
handler.Handle(¬ificationRequest)
|
||||
|
||||
return testContext, nodebInfo
|
||||
}
|
||||
|
||||
func getRanConnectedMbuf(nodeType entities.Node_Type) *rmrCgo.MBuf {
|
||||
var xAction []byte
|
||||
resourceStatusPayload := models.NewResourceStatusPayload(nodeType, enums.RIC_TO_RAN)
|
||||
resourceStatusJson, _ := json.Marshal(resourceStatusPayload)
|
||||
var msgSrc unsafe.Pointer
|
||||
return rmrCgo.NewMBuf(rmrCgo.RAN_CONNECTED, len(resourceStatusJson), RanName, &resourceStatusJson, &xAction, msgSrc)
|
||||
}
|
||||
|
||||
func executeHandleSetupFailureResponse(t *testing.T, tc setupFailureResponseTestCase) (*setupResponseTestContext, *entities.NodebInfo) {
|
||||
var payload []byte
|
||||
_, err := fmt.Sscanf(tc.packedPdu, "%x", &payload)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
|
||||
}
|
||||
|
||||
notificationRequest := models.NotificationRequest{RanName: RanName, Payload: payload}
|
||||
testContext := NewSetupResponseTestContext(tc.setupResponseManager)
|
||||
|
||||
handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, testContext.setupResponseManager, testContext.ranStatusChangeManager, tc.msgType)
|
||||
|
||||
var rnibErr error
|
||||
|
||||
nodebInfo := &entities.NodebInfo{
|
||||
ConnectionStatus: entities.ConnectionStatus_CONNECTING,
|
||||
RanName: RanName,
|
||||
Ip: "10.0.2.2",
|
||||
Port: 1231,
|
||||
}
|
||||
|
||||
testContext.readerMock.On("GetNodeb", RanName).Return(nodebInfo, rnibErr)
|
||||
testContext.writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(tc.saveNodebMockError)
|
||||
handler.Handle(¬ificationRequest)
|
||||
|
||||
return testContext, nodebInfo
|
||||
}
|
||||
|
||||
func TestX2SetupResponse(t *testing.T) {
|
||||
logger := initLog(t)
|
||||
var saveNodebMockError error
|
||||
var sendMsgError error
|
||||
tc := setupSuccessResponseTestCase{
|
||||
X2SetupResponsePackedPdu,
|
||||
managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)),
|
||||
rmrCgo.RIC_X2_SETUP_RESP,
|
||||
saveNodebMockError,
|
||||
sendMsgError,
|
||||
getRanConnectedMbuf(entities.Node_ENB),
|
||||
}
|
||||
|
||||
testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
|
||||
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
|
||||
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
|
||||
assert.EqualValues(t, entities.ConnectionStatus_CONNECTED, nodebInfo.ConnectionStatus)
|
||||
assert.EqualValues(t, entities.Node_ENB, nodebInfo.NodeType)
|
||||
|
||||
assert.IsType(t, &entities.NodebInfo_Enb{}, nodebInfo.Configuration)
|
||||
i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Enb)
|
||||
assert.NotNil(t, i.Enb)
|
||||
testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf, true)
|
||||
}
|
||||
|
||||
func TestX2SetupFailureResponse(t *testing.T) {
|
||||
logger := initLog(t)
|
||||
var saveNodebMockError error
|
||||
tc := setupFailureResponseTestCase{
|
||||
X2SetupFailureResponsePackedPdu,
|
||||
managers.NewX2SetupFailureResponseManager(converters.NewX2SetupFailureResponseConverter(logger)),
|
||||
rmrCgo.RIC_X2_SETUP_FAILURE,
|
||||
saveNodebMockError,
|
||||
}
|
||||
|
||||
testContext, nodebInfo := executeHandleSetupFailureResponse(t, tc)
|
||||
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
|
||||
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
|
||||
assert.EqualValues(t, entities.ConnectionStatus_CONNECTED_SETUP_FAILED, nodebInfo.ConnectionStatus)
|
||||
assert.EqualValues(t, entities.Failure_X2_SETUP_FAILURE, nodebInfo.FailureType)
|
||||
assert.NotNil(t, nodebInfo.SetupFailure)
|
||||
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func TestEndcSetupResponse(t *testing.T) {
|
||||
logger := initLog(t)
|
||||
var saveNodebMockError error
|
||||
var sendMsgError error
|
||||
tc := setupSuccessResponseTestCase{
|
||||
EndcSetupResponsePackedPdu,
|
||||
managers.NewEndcSetupResponseManager(converters.NewEndcSetupResponseConverter(logger)),
|
||||
rmrCgo.RIC_ENDC_X2_SETUP_RESP,
|
||||
saveNodebMockError,
|
||||
sendMsgError,
|
||||
getRanConnectedMbuf(entities.Node_GNB),
|
||||
}
|
||||
|
||||
testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
|
||||
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
|
||||
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
|
||||
assert.EqualValues(t, entities.ConnectionStatus_CONNECTED, nodebInfo.ConnectionStatus)
|
||||
assert.EqualValues(t, entities.Node_GNB, nodebInfo.NodeType)
|
||||
assert.IsType(t, &entities.NodebInfo_Gnb{}, nodebInfo.Configuration)
|
||||
|
||||
i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Gnb)
|
||||
assert.NotNil(t, i.Gnb)
|
||||
testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf, true)
|
||||
}
|
||||
|
||||
func TestEndcSetupFailureResponse(t *testing.T) {
|
||||
logger := initLog(t)
|
||||
var saveNodebMockError error
|
||||
tc := setupFailureResponseTestCase{
|
||||
EndcSetupFailureResponsePackedPdu,
|
||||
managers.NewEndcSetupFailureResponseManager(converters.NewEndcSetupFailureResponseConverter(logger)),
|
||||
rmrCgo.RIC_ENDC_X2_SETUP_FAILURE,
|
||||
saveNodebMockError,
|
||||
}
|
||||
|
||||
testContext, nodebInfo := executeHandleSetupFailureResponse(t, tc)
|
||||
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
|
||||
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
|
||||
assert.EqualValues(t, entities.ConnectionStatus_CONNECTED_SETUP_FAILED, nodebInfo.ConnectionStatus)
|
||||
assert.EqualValues(t, entities.Failure_ENDC_X2_SETUP_FAILURE, nodebInfo.FailureType)
|
||||
assert.NotNil(t, nodebInfo.SetupFailure)
|
||||
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func TestSetupResponseInvalidPayload(t *testing.T) {
|
||||
logger := initLog(t)
|
||||
ranName := "test"
|
||||
notificationRequest := models.NotificationRequest{RanName: ranName, Payload: []byte("123")}
|
||||
testContext := NewSetupResponseTestContext(nil)
|
||||
handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)), testContext.ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)
|
||||
var rnibErr error
|
||||
testContext.readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING}, rnibErr)
|
||||
handler.Handle(¬ificationRequest)
|
||||
testContext.readerMock.AssertCalled(t, "GetNodeb", ranName)
|
||||
testContext.writerMock.AssertNotCalled(t, "SaveNodeb")
|
||||
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func TestSetupResponseSaveNodebFailure(t *testing.T) {
|
||||
logger := initLog(t)
|
||||
saveNodebMockError := common.NewInternalError(errors.New("Error"))
|
||||
var sendMsgError error
|
||||
tc := setupSuccessResponseTestCase{
|
||||
X2SetupResponsePackedPdu,
|
||||
managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)),
|
||||
rmrCgo.RIC_X2_SETUP_RESP,
|
||||
saveNodebMockError,
|
||||
sendMsgError,
|
||||
getRanConnectedMbuf(entities.Node_ENB),
|
||||
}
|
||||
|
||||
testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
|
||||
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
|
||||
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
|
||||
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func TestSetupResponseStatusChangeSendFailure(t *testing.T) {
|
||||
logger := initLog(t)
|
||||
var saveNodebMockError error
|
||||
sendMsgError := e2managererrors.NewRmrError()
|
||||
tc := setupSuccessResponseTestCase{
|
||||
X2SetupResponsePackedPdu,
|
||||
managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)),
|
||||
rmrCgo.RIC_X2_SETUP_RESP,
|
||||
saveNodebMockError,
|
||||
sendMsgError,
|
||||
getRanConnectedMbuf(entities.Node_ENB),
|
||||
}
|
||||
|
||||
testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
|
||||
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
|
||||
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
|
||||
assert.EqualValues(t, entities.ConnectionStatus_CONNECTED, nodebInfo.ConnectionStatus)
|
||||
assert.EqualValues(t, entities.Node_ENB, nodebInfo.NodeType)
|
||||
|
||||
assert.IsType(t, &entities.NodebInfo_Enb{}, nodebInfo.Configuration)
|
||||
i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Enb)
|
||||
assert.NotNil(t, i.Enb)
|
||||
testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf, true)
|
||||
}
|
@@ -0,0 +1,87 @@
|
||||
//
|
||||
// Copyright 2019 AT&T Intellectual Property
|
||||
// Copyright 2019 Nokia
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
|
||||
// platform project (RICP).
|
||||
|
||||
|
||||
package rmrmsghandlers
|
||||
|
||||
// #cgo CFLAGS: -I../../3rdparty/asn1codec/inc/ -I../../3rdparty/asn1codec/e2ap_engine/
|
||||
// #cgo LDFLAGS: -L ../../3rdparty/asn1codec/lib/ -L../../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
|
||||
// #include <asn1codec_utils.h>
|
||||
// #include <x2reset_response_wrapper.h>
|
||||
import "C"
|
||||
import (
|
||||
"e2mgr/e2pdus"
|
||||
"e2mgr/enums"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"e2mgr/services/rmrsender"
|
||||
"e2mgr/utils"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
)
|
||||
|
||||
type X2ResetRequestNotificationHandler struct {
|
||||
logger *logger.Logger
|
||||
rnibDataService services.RNibDataService
|
||||
ranStatusChangeManager managers.IRanStatusChangeManager
|
||||
rmrSender *rmrsender.RmrSender
|
||||
}
|
||||
|
||||
func NewX2ResetRequestNotificationHandler(logger *logger.Logger, rnibDataService services.RNibDataService, ranStatusChangeManager managers.IRanStatusChangeManager, rmrSender *rmrsender.RmrSender) X2ResetRequestNotificationHandler {
|
||||
return X2ResetRequestNotificationHandler{
|
||||
logger: logger,
|
||||
rnibDataService: rnibDataService,
|
||||
ranStatusChangeManager: ranStatusChangeManager,
|
||||
rmrSender: rmrSender,
|
||||
}
|
||||
}
|
||||
|
||||
func (h X2ResetRequestNotificationHandler) Handle(request *models.NotificationRequest) {
|
||||
|
||||
h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Ran name: %s", request.RanName)
|
||||
|
||||
nb, rNibErr := h.rnibDataService.GetNodeb(request.RanName)
|
||||
if rNibErr != nil {
|
||||
h.logger.Errorf("#X2ResetRequestNotificationHandler.Handle - failed to retrieve nodeB entity. RanName: %s. Error: %s", request.RanName, rNibErr.Error())
|
||||
h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Debugf("#X2ResetRequestNotificationHandler.Handle - nodeB entity retrieved. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
|
||||
|
||||
if nb.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
|
||||
h.logger.Warnf("#X2ResetRequestNotificationHandler.Handle - nodeB entity in incorrect state. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
|
||||
h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
return
|
||||
}
|
||||
|
||||
if nb.ConnectionStatus != entities.ConnectionStatus_CONNECTED {
|
||||
h.logger.Errorf("#X2ResetRequestNotificationHandler.Handle - nodeB entity in incorrect state. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
|
||||
h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
return
|
||||
}
|
||||
|
||||
msg := models.NewRmrMessage(rmrCgo.RIC_X2_RESET_RESP, request.RanName, e2pdus.PackedX2ResetResponse, request.TransactionId, request.GetMsgSrc())
|
||||
|
||||
_ = h.rmrSender.Send(msg)
|
||||
h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
_ = h.ranStatusChangeManager.Execute(rmrCgo.RAN_RESTARTED, enums.RAN_TO_RIC, nb)
|
||||
}
|
@@ -0,0 +1,132 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/e2pdus"
|
||||
"e2mgr/enums"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"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"
|
||||
"testing"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func initX2ResetRequestNotificationHandlerTest(t *testing.T) (X2ResetRequestNotificationHandler, *mocks.RnibReaderMock, *mocks.RmrMessengerMock) {
|
||||
log := initLog(t)
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
|
||||
rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
|
||||
|
||||
rmrMessengerMock := &mocks.RmrMessengerMock{}
|
||||
rmrSender := initRmrSender(rmrMessengerMock, log)
|
||||
ranStatusChangeManager := managers.NewRanStatusChangeManager(log, rmrSender)
|
||||
h := NewX2ResetRequestNotificationHandler(log, rnibDataService, ranStatusChangeManager, rmrSender)
|
||||
return h, readerMock, rmrMessengerMock
|
||||
}
|
||||
|
||||
func getRanRestartedMbuf(nodeType entities.Node_Type, messageDirection enums.MessageDirection) *rmrCgo.MBuf {
|
||||
var xAction []byte
|
||||
resourceStatusPayload := models.NewResourceStatusPayload(nodeType, messageDirection)
|
||||
resourceStatusJson, _ := json.Marshal(resourceStatusPayload)
|
||||
var msgSrc unsafe.Pointer
|
||||
return rmrCgo.NewMBuf(rmrCgo.RAN_RESTARTED, len(resourceStatusJson), RanName, &resourceStatusJson, &xAction, msgSrc)
|
||||
}
|
||||
|
||||
func TestHandleX2ResetRequestNotificationSuccess(t *testing.T) {
|
||||
h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
|
||||
ranName := "test"
|
||||
xAction := []byte("123456aa")
|
||||
notificationRequest := models.NewNotificationRequest(ranName, []byte{}, time.Now(), xAction, nil)
|
||||
|
||||
nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
|
||||
var err error
|
||||
readerMock.On("GetNodeb", ranName).Return(nb, err)
|
||||
var msgSrc unsafe.Pointer
|
||||
resetResponseMbuf := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET_RESP, len(e2pdus.PackedX2ResetResponse), ranName, &e2pdus.PackedX2ResetResponse, &xAction, msgSrc)
|
||||
rmrMessengerMock.On("SendMsg", resetResponseMbuf, true).Return(&rmrCgo.MBuf{}, err)
|
||||
ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RAN_TO_RIC)
|
||||
rmrMessengerMock.On("SendMsg", ranRestartedMbuf, true).Return(&rmrCgo.MBuf{}, err)
|
||||
h.Handle(notificationRequest)
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", resetResponseMbuf, true)
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf, true)
|
||||
}
|
||||
|
||||
func TestHandleX2ResetRequestNotificationShuttingDownStatus(t *testing.T) {
|
||||
h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
|
||||
var payload []byte
|
||||
|
||||
xAction := []byte("123456aa")
|
||||
var msgSrc unsafe.Pointer
|
||||
mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xAction, msgSrc)
|
||||
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
|
||||
StartTime: time.Now(), TransactionId: xAction}
|
||||
|
||||
nb := &entities.NodebInfo{RanName: mBuf.Meid, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
|
||||
var rnibErr error
|
||||
|
||||
readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
|
||||
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func TestHandleX2ResetRequestNotificationDisconnectStatus(t *testing.T) {
|
||||
h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
|
||||
var payload []byte
|
||||
xAction := []byte("123456aa")
|
||||
var msgSrc unsafe.Pointer
|
||||
mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xAction, msgSrc)
|
||||
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now(), TransactionId: xAction}
|
||||
nb := &entities.NodebInfo{RanName: mBuf.Meid, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
|
||||
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func TestHandleX2ResetRequestNotificationGetNodebFailed(t *testing.T) {
|
||||
|
||||
h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
|
||||
var payload []byte
|
||||
var xAction []byte
|
||||
var msgSrc unsafe.Pointer
|
||||
mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xAction, msgSrc)
|
||||
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
|
||||
StartTime: time.Now(), TransactionId: xAction}
|
||||
|
||||
var nb *entities.NodebInfo
|
||||
rnibErr := &common.ResourceNotFoundError{}
|
||||
readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
|
||||
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
@@ -0,0 +1,104 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
// #cgo CFLAGS: -I../../3rdparty/asn1codec/inc/ -I../../3rdparty/asn1codec/e2ap_engine/
|
||||
// #cgo LDFLAGS: -L ../../3rdparty/asn1codec/lib/ -L../../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
|
||||
// #include <asn1codec_utils.h>
|
||||
import "C"
|
||||
import (
|
||||
"e2mgr/converters"
|
||||
"e2mgr/enums"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services"
|
||||
"e2mgr/utils"
|
||||
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
|
||||
)
|
||||
|
||||
type X2ResetResponseHandler struct {
|
||||
logger *logger.Logger
|
||||
rnibDataService services.RNibDataService
|
||||
ranStatusChangeManager managers.IRanStatusChangeManager
|
||||
extractor converters.IX2ResetResponseExtractor
|
||||
}
|
||||
|
||||
func NewX2ResetResponseHandler(logger *logger.Logger, rnibDataService services.RNibDataService, ranStatusChangeManager managers.IRanStatusChangeManager, x2ResetResponseExtractor converters.IX2ResetResponseExtractor) X2ResetResponseHandler {
|
||||
return X2ResetResponseHandler{
|
||||
logger: logger,
|
||||
rnibDataService: rnibDataService,
|
||||
ranStatusChangeManager: ranStatusChangeManager,
|
||||
extractor: x2ResetResponseExtractor,
|
||||
}
|
||||
}
|
||||
|
||||
func (h X2ResetResponseHandler) Handle(request *models.NotificationRequest) {
|
||||
ranName := request.RanName
|
||||
h.logger.Infof("#X2ResetResponseHandler.Handle - RAN name: %s - received reset response. Payload: %x", ranName, request.Payload)
|
||||
|
||||
nodebInfo, err := h.rnibDataService.GetNodeb(ranName)
|
||||
if err != nil {
|
||||
h.logger.Errorf("#x2ResetResponseHandler.Handle - RAN name: %s - failed to retrieve nodebInfo entity. Error: %s", ranName, err)
|
||||
return
|
||||
}
|
||||
|
||||
if nodebInfo.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
|
||||
h.logger.Warnf("#X2ResetResponseHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", nodebInfo.RanName, nodebInfo.ConnectionStatus)
|
||||
h.logger.Infof("#X2ResetResponseHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
return
|
||||
}
|
||||
|
||||
if nodebInfo.ConnectionStatus != entities.ConnectionStatus_CONNECTED {
|
||||
h.logger.Errorf("#X2ResetResponseHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", nodebInfo.RanName, nodebInfo.ConnectionStatus)
|
||||
h.logger.Infof("#X2ResetResponseHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
return
|
||||
}
|
||||
|
||||
isSuccessfulResetResponse, err := h.isSuccessfulResetResponse(ranName, request.Payload)
|
||||
|
||||
h.logger.Infof("#X2ResetResponseHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
|
||||
if err != nil || !isSuccessfulResetResponse {
|
||||
return
|
||||
}
|
||||
|
||||
_ = h.ranStatusChangeManager.Execute(rmrCgo.RAN_RESTARTED, enums.RIC_TO_RAN, nodebInfo)
|
||||
}
|
||||
|
||||
func (h X2ResetResponseHandler) isSuccessfulResetResponse(ranName string, packedBuffer []byte) (bool, error) {
|
||||
|
||||
criticalityDiagnostics, err := h.extractor.ExtractCriticalityDiagnosticsFromPdu(packedBuffer)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Errorf("#X2ResetResponseHandler.isSuccessfulResetResponse - RAN name: %s - Failed extracting pdu: %s", ranName, err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
if criticalityDiagnostics != nil {
|
||||
h.logger.Errorf("#X2ResetResponseHandler.isSuccessfulResetResponse - RAN name: %s - Unsuccessful RESET response message. Criticality diagnostics: %s", ranName, criticalityDiagnostics)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
h.logger.Infof("#X2ResetResponseHandler.isSuccessfulResetResponse - RAN name: %s - Successful RESET response message", ranName)
|
||||
return true, nil
|
||||
}
|
@@ -0,0 +1,185 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/configuration"
|
||||
"e2mgr/converters"
|
||||
"e2mgr/enums"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/managers"
|
||||
"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"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
SuccessfulX2ResetResponsePackedPdu = "200700080000010011400100"
|
||||
SuccessfulX2ResetResponsePackedPduEmptyIEs = "20070003000000"
|
||||
UnsuccessfulX2ResetResponsePackedPdu = "2007000d00000100114006080000000d00"
|
||||
)
|
||||
|
||||
func initX2ResetResponseHandlerTest(t *testing.T) (X2ResetResponseHandler, *mocks.RnibReaderMock, *mocks.RmrMessengerMock) {
|
||||
log, err := logger.InitLogger(logger.InfoLevel)
|
||||
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
|
||||
if err != nil {
|
||||
t.Errorf("#initX2ResetResponseHandlerTest - failed to initialize logger, error: %s", err)
|
||||
}
|
||||
readerMock := &mocks.RnibReaderMock{}
|
||||
|
||||
rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
|
||||
|
||||
rmrMessengerMock := &mocks.RmrMessengerMock{}
|
||||
rmrSender := initRmrSender(rmrMessengerMock, log)
|
||||
ranStatusChangeManager := managers.NewRanStatusChangeManager(log, rmrSender)
|
||||
|
||||
h := NewX2ResetResponseHandler(log, rnibDataService, ranStatusChangeManager, converters.NewX2ResetResponseExtractor(log))
|
||||
return h, readerMock, rmrMessengerMock
|
||||
}
|
||||
|
||||
func TestX2ResetResponseSuccess(t *testing.T) {
|
||||
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
|
||||
var payload []byte
|
||||
_, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
|
||||
}
|
||||
|
||||
var xAction []byte
|
||||
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
|
||||
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
|
||||
ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RIC_TO_RAN)
|
||||
rmrMessengerMock.On("SendMsg", ranRestartedMbuf, true).Return(&rmrCgo.MBuf{}, err)
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf, true)
|
||||
}
|
||||
|
||||
func TestX2ResetResponseSuccessEmptyIEs(t *testing.T) {
|
||||
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
|
||||
var payload []byte
|
||||
_, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPduEmptyIEs, "%x", &payload)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
|
||||
}
|
||||
|
||||
var xAction []byte
|
||||
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
|
||||
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
|
||||
ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RIC_TO_RAN)
|
||||
rmrMessengerMock.On("SendMsg", ranRestartedMbuf, true).Return(&rmrCgo.MBuf{}, err)
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf, true)
|
||||
}
|
||||
|
||||
func TestX2ResetResponseShuttingDown(t *testing.T) {
|
||||
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
|
||||
var payload []byte
|
||||
_, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
|
||||
}
|
||||
|
||||
var xAction []byte
|
||||
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
|
||||
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, NodeType: entities.Node_ENB}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func TestX2ResetResponseInvalidConnectionStatus(t *testing.T) {
|
||||
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
|
||||
var payload []byte
|
||||
_, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
|
||||
}
|
||||
|
||||
var xAction []byte
|
||||
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
|
||||
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, NodeType: entities.Node_ENB}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func TestX2ResetResponseError(t *testing.T) {
|
||||
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
|
||||
var payload []byte
|
||||
_, err := fmt.Sscanf(UnsuccessfulX2ResetResponsePackedPdu, "%x", &payload)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
|
||||
}
|
||||
|
||||
var xAction []byte
|
||||
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
|
||||
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func TestX2ResetResponseGetNodebFailure(t *testing.T) {
|
||||
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
|
||||
|
||||
var payload []byte
|
||||
_, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
|
||||
}
|
||||
|
||||
var xAction []byte
|
||||
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
|
||||
|
||||
var nb *entities.NodebInfo
|
||||
rnibErr := common.NewResourceNotFoundError("nodeb not found")
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
|
||||
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
||||
|
||||
func TestX2ResetResponseUnpackFailure(t *testing.T) {
|
||||
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
|
||||
|
||||
payload := []byte("Invalid payload")
|
||||
var xAction []byte
|
||||
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
|
||||
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
|
||||
var rnibErr error
|
||||
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
|
||||
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
// #cgo CFLAGS: -I../../3rdparty/asn1codec/inc/ -I../../3rdparty/asn1codec/e2ap_engine/
|
||||
// #cgo LDFLAGS: -L ../../3rdparty/asn1codec/lib/ -L../../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
|
||||
// #include <asn1codec_utils.h>
|
||||
// #include <configuration_update_wrapper.h>
|
||||
import "C"
|
||||
import (
|
||||
"e2mgr/converters"
|
||||
"e2mgr/e2pdus"
|
||||
"e2mgr/logger"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"e2mgr/services/rmrsender"
|
||||
"e2mgr/utils"
|
||||
)
|
||||
|
||||
type X2EnbConfigurationUpdateHandler struct {
|
||||
logger *logger.Logger
|
||||
rmrSender *rmrsender.RmrSender
|
||||
}
|
||||
|
||||
func NewX2EnbConfigurationUpdateHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender) X2EnbConfigurationUpdateHandler {
|
||||
return X2EnbConfigurationUpdateHandler{
|
||||
logger: logger,
|
||||
rmrSender: rmrSender,
|
||||
}
|
||||
}
|
||||
|
||||
func (h X2EnbConfigurationUpdateHandler) Handle(request *models.NotificationRequest) {
|
||||
|
||||
refinedMessage, err := converters.UnpackX2apPduAndRefine(h.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
|
||||
|
||||
if err != nil {
|
||||
h.logger.Errorf("#x2enb_configuration_update_handler.Handle - unpack failed. Error: %v", err)
|
||||
|
||||
msg := models.NewRmrMessage(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_FAILURE, request.RanName, e2pdus.PackedX2EnbConfigurationUpdateFailure, request.TransactionId, request.GetMsgSrc())
|
||||
_ = h.rmrSender.Send(msg)
|
||||
|
||||
h.logger.Infof("#X2EnbConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling enb configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
return
|
||||
}
|
||||
|
||||
h.logger.Infof("#x2enb_configuration_update_handler.Handle - Enb configuration update initiating message received")
|
||||
h.logger.Debugf("#x2enb_configuration_update_handler.Handle - Enb configuration update initiating message payload: %s", refinedMessage.PduPrint)
|
||||
|
||||
msg := models.NewRmrMessage(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_ACK, request.RanName, e2pdus.PackedX2EnbConfigurationUpdateAck,request.TransactionId, request.GetMsgSrc())
|
||||
_ = h.rmrSender.Send(msg)
|
||||
|
||||
h.logger.Infof("#X2EnbConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling enb configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// 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 rmrmsghandlers
|
||||
|
||||
import (
|
||||
"e2mgr/mocks"
|
||||
"e2mgr/models"
|
||||
"e2mgr/rmrCgo"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const PackedX2EnbConfigurationUpdateAck = "200800080000010011400100"
|
||||
const PackedX2EnbConfigurationUpdateFailure = "400800080000010005400142"
|
||||
|
||||
func initX2EnbConfigurationUpdateHandlerTest(t *testing.T) (X2EnbConfigurationUpdateHandler, *mocks.RmrMessengerMock) {
|
||||
log := initLog(t)
|
||||
rmrMessengerMock := &mocks.RmrMessengerMock{}
|
||||
rmrSender := initRmrSender(rmrMessengerMock, log)
|
||||
h := NewX2EnbConfigurationUpdateHandler(log, rmrSender)
|
||||
return h, rmrMessengerMock
|
||||
}
|
||||
|
||||
func TestHandleX2EnbConfigUpdateSuccess(t *testing.T) {
|
||||
h, rmrMessengerMock := initX2EnbConfigurationUpdateHandlerTest(t)
|
||||
|
||||
ranName := "test"
|
||||
xAction := []byte("123456aa")
|
||||
var payload []byte
|
||||
_, _ = fmt.Sscanf(PackedX2EnbConfigurationUpdateAck, "%x", &payload)
|
||||
var msgSrc unsafe.Pointer
|
||||
|
||||
mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_ACK, len(payload), ranName, &payload, &xAction, msgSrc)
|
||||
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
|
||||
StartTime: time.Now(), TransactionId:xAction}
|
||||
var err error
|
||||
rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, err)
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
|
||||
}
|
||||
|
||||
func TestHandleX2EnbConfigUpdateFailure(t *testing.T) {
|
||||
h, rmrMessengerMock := initX2EnbConfigurationUpdateHandlerTest(t)
|
||||
|
||||
ranName := "test"
|
||||
xAction := []byte("123456aa")
|
||||
|
||||
var payload []byte
|
||||
_, _ = fmt.Sscanf(PackedX2EnbConfigurationUpdateFailure, "%x", &payload)
|
||||
var msgSrc unsafe.Pointer
|
||||
|
||||
mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_FAILURE, len(payload), ranName, &payload, &xAction, msgSrc)
|
||||
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: 0, Payload: []byte{0},
|
||||
StartTime: time.Now(), TransactionId:xAction}
|
||||
rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, fmt.Errorf("send failure"))
|
||||
h.Handle(¬ificationRequest)
|
||||
rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
|
||||
}
|
Reference in New Issue
Block a user