# The Jenkins job requires a tag to build the Docker image.
# Global-JJB script assumes this file is in the repo root.
---
-tag: 5.4.7
+tag: 5.4.8
SetGeneralConfiguration(writer http.ResponseWriter, r *http.Request)
AddEnb(writer http.ResponseWriter, r *http.Request)
DeleteEnb(writer http.ResponseWriter, r *http.Request)
+ HealthCheckRequest(writer http.ResponseWriter, r *http.Request)
}
type NodebController struct {
c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ResetRequest, request, false, http.StatusNoContent)
}
+func (c *NodebController) HealthCheckRequest(writer http.ResponseWriter, r *http.Request) {
+ c.logger.Infof("[Client -> E2 Manager] #NodebController.HealthCheckRequest - request: %v", c.prettifyRequest(r))
+
+ request := models.HealthCheckRequest{}
+
+ if err := c.extractJsonBody(r, &request); err != nil {
+ c.handleErrorResponse(err, writer)
+ return
+ }
+
+ c.handleRequest(writer, &r.Header, httpmsghandlerprovider.HealthCheckRequest, request, true, http.StatusNoContent)
+}
+
func (c *NodebController) extractRequestBodyToProto(r *http.Request, pb proto.Message, writer http.ResponseWriter) bool {
defer r.Body.Close()
e2Error, _ := err.(*e2managererrors.NodebExistsError)
errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
httpError = http.StatusBadRequest
+ case *e2managererrors.NoConnectedRanError:
+ e2Error, _ := err.(*e2managererrors.NoConnectedRanError)
+ errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+ httpError = http.StatusNotFound
default:
e2Error := e2managererrors.NewInternalError()
errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
servedNrCells = append(servedNrCells, &entities.ServedNRCell{ServedNrCellInformation: &entities.ServedNRCellInformation{
CellId: v,
ChoiceNrMode: &entities.ServedNRCellInformation_ChoiceNRMode{
- Fdd: &entities.ServedNRCellInformation_ChoiceNRMode_FddInfo{
-
- },
+ Fdd: &entities.ServedNRCellInformation_ChoiceNRMode_FddInfo{},
},
NrMode: entities.Nr_FDD,
NrPci: 5,
context := controllerUpdateGnbTestContext{
getNodebInfoResult: nil,
requestBody: map[string]interface{}{
- "servedNrCells": []interface{}{
- },
+ "servedNrCells": []interface{}{},
},
expectedStatusCode: http.StatusBadRequest,
expectedJsonResponse: ValidationFailureJson,
oldServedCells := generateServedCells("whatever1", "whatever2")
context := controllerUpdateEnbTestContext{
- getNodebInfoResult: &getNodebInfoResult{
- nodebInfo: &entities.NodebInfo{
- RanName: RanName,
- ConnectionStatus: entities.ConnectionStatus_CONNECTED,
- AssociatedE2TInstanceAddress: AssociatedE2TInstanceAddress,
- NodeType: entities.Node_ENB,
- Configuration: &entities.NodebInfo_Enb{Enb: &entities.Enb{ServedCells: oldServedCells, EnbType: entities.EnbType_MACRO_NG_ENB}},
- },
- rnibError: nil,
- },
+ getNodebInfoResult: &getNodebInfoResult{
+ nodebInfo: &entities.NodebInfo{
+ RanName: RanName,
+ ConnectionStatus: entities.ConnectionStatus_CONNECTED,
+ AssociatedE2TInstanceAddress: AssociatedE2TInstanceAddress,
+ NodeType: entities.Node_ENB,
+ Configuration: &entities.NodebInfo_Enb{Enb: &entities.Enb{ServedCells: oldServedCells, EnbType: entities.EnbType_MACRO_NG_ENB}},
+ },
+ rnibError: nil,
+ },
requestBody: requestBody,
expectedStatusCode: http.StatusBadRequest,
expectedJsonResponse: ValidationFailureJson,
controller.handleErrorResponse(e2managererrors.NewRmrError(), writer)
assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
+ writer = httptest.NewRecorder()
+ controller.handleErrorResponse(e2managererrors.NewNoConnectedRanError(), writer)
+ assert.Equal(t, http.StatusNotFound, writer.Result().StatusCode)
+
writer = httptest.NewRecorder()
controller.handleErrorResponse(e2managererrors.NewResourceNotFoundError(), writer)
assert.Equal(t, http.StatusNotFound, writer.Result().StatusCode)
--- /dev/null
+//
+// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.
+//
+// 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 e2managererrors
+
+type NoConnectedRanError struct {
+ *BaseError
+}
+
+func NewNoConnectedRanError() *NoConnectedRanError {
+ return &NoConnectedRanError{
+ &BaseError{
+ Code: 406,
+ Message: "No RAN in Connected State",
+ },
+ }
+}
+
+func (e *NoConnectedRanError) Error() string {
+ return e.Message
+}
--- /dev/null
+//
+// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.
+//
+// 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"
+ "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"
+ // "github.com/pkg/errors"
+)
+
+type HealthCheckRequestHandler struct {
+ logger *logger.Logger
+ rNibDataService services.RNibDataService
+ ranListManager managers.RanListManager
+ rmrsender *rmrsender.RmrSender
+}
+
+func NewHealthCheckRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService, ranListManager managers.RanListManager, rmrsender *rmrsender.RmrSender) *HealthCheckRequestHandler {
+ return &HealthCheckRequestHandler{
+ logger: logger,
+ rNibDataService: rNibDataService,
+ ranListManager: ranListManager,
+ rmrsender: rmrsender,
+ }
+}
+
+func (h *HealthCheckRequestHandler) Handle(request models.Request) (models.IResponse, error) {
+ ranNameList := h.getRanNameList(request)
+ isAtleastOneRanConnected := false
+
+ for _, ranName := range ranNameList {
+ nodebInfo, err := h.rNibDataService.GetNodeb(ranName) //This method is needed for getting RAN functions with later commits
+ if err != nil {
+ _, ok := err.(*common.ResourceNotFoundError)
+ if !ok {
+ h.logger.Errorf("#HealthCheckRequest.Handle - failed to get nodeBInfo entity for ran name: %v from RNIB. Error: %s", ranName, err)
+ return nil, e2managererrors.NewRnibDbError()
+ }
+ continue
+ }
+ if nodebInfo.ConnectionStatus == entities.ConnectionStatus_CONNECTED {
+ isAtleastOneRanConnected = true
+
+ }
+ }
+ if isAtleastOneRanConnected == false {
+ return nil, e2managererrors.NewNoConnectedRanError()
+ }
+
+ return nil, nil
+}
+
+func (h *HealthCheckRequestHandler) getRanNameList(request models.Request) []string {
+ healthCheckRequest := request.(models.HealthCheckRequest)
+ if request != nil && len(healthCheckRequest.RanList) != 0 {
+ return healthCheckRequest.RanList
+ }
+ nodeIds := h.ranListManager.GetNbIdentityList()
+
+ var ranNameList []string
+ for _, nbIdentity := range nodeIds {
+ if nbIdentity.ConnectionStatus == entities.ConnectionStatus_CONNECTED {
+ ranNameList = append(ranNameList, nbIdentity.InventoryName)
+ }
+ }
+ return ranNameList
+}
--- /dev/null
+//
+// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.
+//
+// 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/services"
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func setupHealthCheckHandlerTest(t *testing.T) (*HealthCheckRequestHandler, services.RNibDataService, *mocks.RnibReaderMock, *mocks.RanListManagerMock) {
+ logger := initLog(t)
+ config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+
+ readerMock := &mocks.RnibReaderMock{}
+ writerMock := &mocks.RnibWriterMock{}
+
+ rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
+ rmrMessengerMock := &mocks.RmrMessengerMock{}
+ ranListManagerMock := &mocks.RanListManagerMock{}
+
+ rmrSender := getRmrSender(rmrMessengerMock, logger)
+ handler := NewHealthCheckRequestHandler(logger, rnibDataService, ranListManagerMock, rmrSender)
+
+ return handler, rnibDataService, readerMock, ranListManagerMock
+}
+
+func TestHealthCheckRequestHandlerArguementHasRanNameSuccess(t *testing.T) {
+ handler, _, readerMock, _ := setupHealthCheckHandlerTest(t)
+
+ nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED}
+ ranNames := []string{"RanName_1"}
+
+ readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+
+ _, err := handler.Handle(models.HealthCheckRequest{ranNames})
+
+ assert.Nil(t, err)
+ readerMock.AssertExpectations(t)
+}
+
+func TestHealthCheckRequestHandlerArguementHasNoRanNameSuccess(t *testing.T) {
+ handler, _, readerMock, ranListManagerMock := setupHealthCheckHandlerTest(t)
+
+ nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED},
+ {InventoryName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}}
+
+ ranListManagerMock.On("GetNbIdentityList").Return(nbIdentityList)
+
+ nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED}
+ readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+
+ nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
+ readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
+
+ _, err := handler.Handle(models.HealthCheckRequest{[]string{}})
+
+ assert.Nil(t, err)
+
+}
+
+func TestHealthCheckRequestHandlerArguementHasNoRanConnectedFailure(t *testing.T) {
+ handler, _, readerMock, ranListManagerMock := setupHealthCheckHandlerTest(t)
+
+ nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED},
+ {InventoryName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}}
+ ranListManagerMock.On("GetNbIdentityList").Return(nbIdentityList)
+
+ nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
+ readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+
+ nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
+ readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
+
+ _, err := handler.Handle(models.HealthCheckRequest{[]string{}})
+
+ assert.IsType(t, &e2managererrors.NoConnectedRanError{}, err)
+
+}
+
+func TestHealthCheckRequestHandlerArguementHasRanNameDBErrorFailure(t *testing.T) {
+ handler, _, readerMock, _ := setupHealthCheckHandlerTest(t)
+
+ ranNames := []string{"RanName_1"}
+ readerMock.On("GetNodeb", "RanName_1").Return(&entities.NodebInfo{}, errors.New("error"))
+
+ _, err := handler.Handle(models.HealthCheckRequest{ranNames})
+
+ assert.IsType(t, &e2managererrors.RnibDbError{}, err)
+ readerMock.AssertExpectations(t)
+}
rr.HandleFunc("/enb/{ranName}", nodebController.UpdateEnb).Methods(http.MethodPut)
rr.HandleFunc("/shutdown", nodebController.Shutdown).Methods(http.MethodPut)
rr.HandleFunc("/parameters", nodebController.SetGeneralConfiguration).Methods(http.MethodPut)
+ rr.HandleFunc("/health", nodebController.HealthCheckRequest).Methods(http.MethodPut)
rrr := r.PathPrefix("/e2t").Subrouter()
rrr.HandleFunc("/list", e2tController.GetE2TInstances).Methods(http.MethodGet)
}
nodebControllerMock.On("DeleteEnb").Return(nil)
nodebControllerMock.On("AddEnb").Return(nil)
nodebControllerMock.On("UpdateEnb").Return(nil)
+ nodebControllerMock.On("HealthCheckRequest").Return(nil)
e2tControllerMock := &mocks.E2TControllerMock{}
nodebControllerMock.AssertNumberOfCalls(t, "Shutdown", 1)
}
+func TestHealthCheckRequest(t *testing.T) {
+ router, _, nodebControllerMock, _ := setupRouterAndMocks()
+
+ req, err := http.NewRequest("PUT", "/v1/nodeb/health", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ rr := httptest.NewRecorder()
+ router.ServeHTTP(rr, req)
+
+ nodebControllerMock.AssertNumberOfCalls(t, "HealthCheckRequest", 1)
+}
+
func TestRoutePutNodebSetGeneralConfiguration(t *testing.T) {
router, _, nodebControllerMock, _ := setupRouterAndMocks()
c.Called()
}
+
+func (c *NodebControllerMock) HealthCheckRequest(writer http.ResponseWriter, r *http.Request) {
+ writer.Header().Set("Content-Type", "application/json")
+ writer.WriteHeader(http.StatusOK)
+
+ c.Called()
+}
--- /dev/null
+//
+// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.
+//
+// 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 models
+
+type HealthCheckRequest struct {
+ RanList []string
+}
UpdateEnbRequest IncomingRequest = "UpdateEnbRequest"
AddEnbRequest IncomingRequest = "AddEnbRequest"
DeleteEnbRequest IncomingRequest = "DeleteEnbRequest"
+ HealthCheckRequest IncomingRequest = "HealthCheckRequest"
)
type IncomingRequestHandlerProvider struct {
}
}
-func initRequestHandlerMap(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, e2tInstancesManager managers.IE2TInstancesManager, rmClient clients.IRoutingManagerClient, ranConnectStatusChangeManager managers.IRanConnectStatusChangeManager, nodebValidator *managers.NodebValidator, updateEnbManager managers.IUpdateNodebManager, updateGnbManager managers.IUpdateNodebManager, ranListManager managers.RanListManager) map[IncomingRequest]httpmsghandlers.RequestHandler {
+func initRequestHandlerMap(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, e2tInstancesManager managers.IE2TInstancesManager, rmClient clients.IRoutingManagerClient, ranConnectStatusChangeManager managers.IRanConnectStatusChangeManager, nodebValidator *managers.NodebValidator, updateEnbManager managers.IUpdateNodebManager, updateGnbManager managers.IUpdateNodebManager, ranListManager managers.RanListManager) map[IncomingRequest]httpmsghandlers.RequestHandler {
return map[IncomingRequest]httpmsghandlers.RequestHandler{
ShutdownRequest: httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrSender, config, rNibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager, ranListManager),
UpdateEnbRequest: httpmsghandlers.NewUpdateNodebRequestHandler(logger, rNibDataService, updateEnbManager),
AddEnbRequest: httpmsghandlers.NewAddEnbRequestHandler(logger, rNibDataService, nodebValidator, ranListManager),
DeleteEnbRequest: httpmsghandlers.NewDeleteEnbRequestHandler(logger, rNibDataService, ranListManager),
+ HealthCheckRequest: httpmsghandlers.NewHealthCheckRequestHandler(logger, rNibDataService, ranListManager, rmrSender),
}
}
assert.True(t, ok)
}
+func TestHealthCheckRequest(t *testing.T) {
+ provider := setupTest(t)
+ handler, err := provider.GetHandler(HealthCheckRequest)
+
+ assert.NotNil(t, provider)
+ assert.Nil(t, err)
+
+ _, ok := handler.(*httpmsghandlers.HealthCheckRequestHandler)
+
+ assert.True(t, ok)
+}
+
func TestGetShutdownHandlerFailure(t *testing.T) {
provider := setupTest(t)
_, actual := provider.GetHandler("test")