From 9377e3df9b861e512df33d8596a868b9e5e34e94 Mon Sep 17 00:00:00 2001 From: Irina Date: Mon, 13 Jul 2020 13:15:03 +0300 Subject: [PATCH] RIC-432 - Support Update eNB REST API Change-Id: I024eef6c21fb3a74c3fbc8351701a1e8ecae63bc Signed-off-by: Irina --- E2Manager/container-tag.yaml | 2 +- E2Manager/controllers/nodeb_controller.go | 27 +- E2Manager/controllers/nodeb_controller_test.go | 311 ++++++++++++++++++++- .../update_nodeb_request_handler.go | 5 +- E2Manager/managers/i_update_nodeb_manager.go | 4 +- E2Manager/managers/update_enb_manager.go | 40 ++- E2Manager/models/update_enb_request.go | 38 ++- E2Manager/models/update_nodeb_request.go | 28 -- E2Manager/rNibWriter/rNibWriter_test.go | 60 +++- 9 files changed, 448 insertions(+), 67 deletions(-) delete mode 100644 E2Manager/models/update_nodeb_request.go diff --git a/E2Manager/container-tag.yaml b/E2Manager/container-tag.yaml index 91e8f86..6c99a8d 100644 --- a/E2Manager/container-tag.yaml +++ b/E2Manager/container-tag.yaml @@ -1,4 +1,4 @@ # The Jenkins job requires a tag to build the Docker image. # Global-JJB script assumes this file is in the repo root. --- -tag: 5.2.10 +tag: 5.2.11 diff --git a/E2Manager/controllers/nodeb_controller.go b/E2Manager/controllers/nodeb_controller.go index 71b1160..809c5b3 100644 --- a/E2Manager/controllers/nodeb_controller.go +++ b/E2Manager/controllers/nodeb_controller.go @@ -101,20 +101,31 @@ func (c *NodebController) UpdateGnb(writer http.ResponseWriter, r *http.Request) func (c *NodebController) UpdateEnb(writer http.ResponseWriter, r *http.Request) { c.logger.Infof("[Client -> E2 Manager] #NodebController.UpdateEnb - request: %v", c.prettifyRequest(r)) - vars := mux.Vars(r) - ranName := vars[ParamRanName] - request := models.UpdateNodebRequest{} + defer r.Body.Close() + body, err := ioutil.ReadAll(r.Body) + + if err != nil { + c.logger.Errorf("[Client -> E2 Manager] #NodebController.UpdateEnb - unable to read request body - error: %s", err) + c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer) + return + } - enb := entities.Enb{} + updateEnbRequest := models.UpdateEnbRequest{} + err = json.Unmarshal(body, &updateEnbRequest) - if !c.extractRequestBodyToProto(r, &enb, writer) { + if err != nil { + c.logger.Errorf("[Client -> E2 Manager] #NodebController.UpdateEnb - unable to unmarshal json - error: %s", err) + c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer) return } - request.Enb = &enb - request.RanName = ranName - c.handleRequest(writer, &r.Header, httpmsghandlerprovider.UpdateEnbRequest, request, true, http.StatusOK) + vars := mux.Vars(r) + ranName := vars[ParamRanName] + + updateEnbRequest.RanName = ranName + + c.handleRequest(writer, &r.Header, httpmsghandlerprovider.UpdateEnbRequest, &updateEnbRequest, true, http.StatusOK) } func (c *NodebController) AddEnb(writer http.ResponseWriter, r *http.Request) { diff --git a/E2Manager/controllers/nodeb_controller_test.go b/E2Manager/controllers/nodeb_controller_test.go index d128dad..79df8ce 100644 --- a/E2Manager/controllers/nodeb_controller_test.go +++ b/E2Manager/controllers/nodeb_controller_test.go @@ -67,6 +67,7 @@ var ( ServedNrCellInformationRequiredFields = []string{"cellId", "choiceNrMode", "nrMode", "servedPlmns"} NrNeighbourInformationRequiredFields = []string{"nrCgi", "choiceNrMode", "nrMode"} AddEnbRequestRequiredFields = []string{"ranName", "enb", "globalNbId"} + UpdateEnbRequestRequiredFields = []string{"enb"} GlobalIdRequiredFields = []string{"plmnId", "nbId"} EnbRequiredFields = []string{"enbType", "servedCells"} ServedCellRequiredFields = []string{"broadcastPlmns", "cellId", "choiceEutraMode", "eutraMode", "tac"} @@ -96,17 +97,35 @@ type updateGnbCellsParams struct { err error } +type updateEnbCellsParams struct { + err error +} + type saveNodebParams struct { nodebInfo *entities.NodebInfo nbIdentity *entities.NbIdentity err error } +type removeServedCellsParams struct { + servedCellInfo []*entities.ServedCellInfo + err error +} + type removeServedNrCellsParams struct { servedNrCells []*entities.ServedNRCell err error } +type controllerUpdateEnbTestContext struct { + getNodebInfoResult *getNodebInfoResult + removeServedCellsParams *removeServedCellsParams + updateEnbCellsParams *updateEnbCellsParams + requestBody map[string]interface{} + expectedStatusCode int + expectedJsonResponse string +} + type controllerUpdateGnbTestContext struct { getNodebInfoResult *getNodebInfoResult removeServedNrCellsParams *removeServedNrCellsParams @@ -151,6 +170,24 @@ func generateServedNrCells(cellIds ...string) []*entities.ServedNRCell { return servedNrCells } +func generateServedCells(cellIds ...string) []*entities.ServedCellInfo { + + var servedCells []*entities.ServedCellInfo + + for i, v := range cellIds { + servedCells = append(servedCells, &entities.ServedCellInfo{ + CellId: v, + ChoiceEutraMode: &entities.ChoiceEUTRAMode{ + Fdd: &entities.FddInfo{}, + }, + Pci: uint32(i + 1), + BroadcastPlmns: []string{"whatever"}, + }) + } + + return servedCells +} + func buildNrNeighbourInformation(propToOmit string) map[string]interface{} { ret := map[string]interface{}{ "nrCgi": "whatever", @@ -209,6 +246,19 @@ func buildServedCell(propToOmit string) map[string]interface{} { return ret } +func getUpdateEnbRequest(propToOmit string) map[string]interface{} { + ret := map[string]interface{}{ + "enb": buildEnb(propToOmit), + } + + if len(propToOmit) != 0 { + delete(ret, propToOmit) + } + + return ret +} + + func getAddEnbRequest(propToOmit string) map[string]interface{} { ret := map[string]interface{}{ "ranName": RanName, @@ -345,6 +395,23 @@ func controllerGetNodebIdListTestExecuter(t *testing.T, context *controllerGetNo assert.Equal(t, context.expectedJsonResponse, string(bodyBytes)) } +func activateControllerUpdateEnbMocks(context *controllerUpdateEnbTestContext, readerMock *mocks.RnibReaderMock, writerMock *mocks.RnibWriterMock,updateEnbRequest *models.UpdateEnbRequest) { + if context.getNodebInfoResult != nil { + readerMock.On("GetNodeb", RanName).Return(context.getNodebInfoResult.nodebInfo, context.getNodebInfoResult.rnibError) + } + + if context.removeServedCellsParams != nil { + writerMock.On("RemoveServedCells", RanName, context.removeServedCellsParams.servedCellInfo).Return(context.removeServedCellsParams.err) + } + + if context.updateEnbCellsParams != nil { + updatedNodebInfo := *context.getNodebInfoResult.nodebInfo + updatedNodebInfo.Configuration = &entities.NodebInfo_Enb{Enb: updateEnbRequest.Enb} + + writerMock.On("UpdateEnb", &updatedNodebInfo, updateEnbRequest.Enb.ServedCells).Return(context.updateEnbCellsParams.err) + } +} + func activateControllerUpdateGnbMocks(context *controllerUpdateGnbTestContext, readerMock *mocks.RnibReaderMock, writerMock *mocks.RnibWriterMock) { if context.getNodebInfoResult != nil { readerMock.On("GetNodeb", RanName).Return(context.getNodebInfoResult.nodebInfo, context.getNodebInfoResult.rnibError) @@ -372,6 +439,14 @@ func assertControllerUpdateGnb(t *testing.T, context *controllerUpdateGnbTestCon writerMock.AssertExpectations(t) } +func assertControllerUpdateEnb(t *testing.T, context *controllerUpdateEnbTestContext, writer *httptest.ResponseRecorder, readerMock *mocks.RnibReaderMock, writerMock *mocks.RnibWriterMock) { + assert.Equal(t, context.expectedStatusCode, writer.Result().StatusCode) + bodyBytes, _ := ioutil.ReadAll(writer.Body) + assert.Equal(t, context.expectedJsonResponse, string(bodyBytes)) + readerMock.AssertExpectations(t) + writerMock.AssertExpectations(t) +} + func assertControllerAddEnb(t *testing.T, context *controllerAddEnbTestContext, writer *httptest.ResponseRecorder, readerMock *mocks.RnibReaderMock, writerMock *mocks.RnibWriterMock) { assert.Equal(t, context.expectedStatusCode, writer.Result().StatusCode) bodyBytes, _ := ioutil.ReadAll(writer.Body) @@ -388,6 +463,15 @@ func assertControllerDeleteEnb(t *testing.T, context *controllerDeleteEnbTestCon writerMock.AssertExpectations(t) } +func buildUpdateEnbRequest(context *controllerUpdateEnbTestContext) *http.Request { + updateEnbUrl := fmt.Sprintf("/nodeb/enb/%s", RanName) + requestBody := getJsonRequestAsBuffer(context.requestBody) + req, _ := http.NewRequest(http.MethodPut, updateEnbUrl, requestBody) + req.Header.Set("Content-Type", "application/json") + req = mux.SetURLVars(req, map[string]string{"ranName": RanName}) + return req +} + func buildUpdateGnbRequest(context *controllerUpdateGnbTestContext) *http.Request { updateGnbUrl := fmt.Sprintf("/nodeb/%s/update", RanName) requestBody := getJsonRequestAsBuffer(context.requestBody) @@ -404,6 +488,25 @@ func buildAddEnbRequest(context *controllerAddEnbTestContext) *http.Request { return req } +func controllerUpdateEnbTestExecuter(t *testing.T, context *controllerUpdateEnbTestContext) { + controller, readerMock, writerMock, _, _ := setupControllerTest(t) + writer := httptest.NewRecorder() + + r := buildUpdateEnbRequest(context) + body, _ := ioutil.ReadAll(io.LimitReader(r.Body, LimitRequest)) + + updateEnbRequest := models.UpdateEnbRequest{} + _ = json.Unmarshal(body, &updateEnbRequest) + + activateControllerUpdateEnbMocks(context, readerMock, writerMock, &updateEnbRequest) + r = buildUpdateEnbRequest(context) + defer r.Body.Close() + + controller.UpdateEnb(writer, r) + + assertControllerUpdateEnb(t, context, writer, readerMock, writerMock) +} + func controllerUpdateGnbTestExecuter(t *testing.T, context *controllerUpdateGnbTestContext) { controller, readerMock, writerMock, _, _ := setupControllerTest(t) writer := httptest.NewRecorder() @@ -752,6 +855,187 @@ func TestControllerUpdateGnbSuccess(t *testing.T) { controllerUpdateGnbTestExecuter(t, &context) } +func TestControllerUpdateEnbInvalidRequest(t *testing.T) { + controller, _, _, _, _ := setupControllerTest(t) + + writer := httptest.NewRecorder() + invalidJson := strings.NewReader("{enb:\"whatever\"") + + updateEnbUrl := fmt.Sprintf("/nodeb/enb/%s", RanName) + req, _ := http.NewRequest(http.MethodPut, updateEnbUrl, invalidJson) + req.Header.Set("Content-Type", "application/json") + req = mux.SetURLVars(req, map[string]string{"ranName": RanName}) + + controller.UpdateEnb(writer, req) + + assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode) + bodyBytes, _ := ioutil.ReadAll(writer.Body) + assert.Equal(t, CorruptedJson, string(bodyBytes)) +} + +func TestControllerUpdateEnbEmptyEnbType(t *testing.T) { + context := controllerUpdateEnbTestContext{ + getNodebInfoResult: nil, + requestBody: getUpdateEnbRequest(EnbRequiredFields[0]), + expectedStatusCode: http.StatusBadRequest, + expectedJsonResponse: ValidationFailureJson, + } + + controllerUpdateEnbTestExecuter(t, &context) +} + +func TestControllerUpdateEnbEmptyServedCells(t *testing.T) { + context := controllerUpdateEnbTestContext{ + getNodebInfoResult: nil, + requestBody: getUpdateEnbRequest(EnbRequiredFields[1]), + expectedStatusCode: http.StatusBadRequest, + expectedJsonResponse: ValidationFailureJson, + } + + controllerUpdateEnbTestExecuter(t, &context) +} + +func TestControllerUpdateEnbMissingEnb(t *testing.T) { + context := controllerUpdateEnbTestContext{ + getNodebInfoResult: nil, + requestBody: getUpdateEnbRequest(UpdateEnbRequestRequiredFields[0]), + expectedStatusCode: http.StatusBadRequest, + expectedJsonResponse: ValidationFailureJson, + } + + controllerUpdateEnbTestExecuter(t, &context) +} + +func TestControllerUpdateEnbValidServedCellsGetNodebNotFound(t *testing.T) { + context := controllerUpdateEnbTestContext{ + getNodebInfoResult: &getNodebInfoResult{ + nodebInfo: nil, + rnibError: common.NewResourceNotFoundError("#reader.GetNodeb - Not found Error"), + }, + requestBody: getUpdateEnbRequest(""), + expectedStatusCode: http.StatusNotFound, + expectedJsonResponse: ResourceNotFoundJson, + } + + controllerUpdateEnbTestExecuter(t, &context) +} + +func TestControllerUpdateEnbValidServedCellsGetNodebInternalError(t *testing.T) { + context := controllerUpdateEnbTestContext{ + getNodebInfoResult: &getNodebInfoResult{ + nodebInfo: nil, + rnibError: common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")), + }, + requestBody: getUpdateEnbRequest(""), + expectedStatusCode: http.StatusInternalServerError, + expectedJsonResponse: RnibErrorJson, + } + + controllerUpdateEnbTestExecuter(t, &context) +} + +func TestControllerUpdateEnbGetNodebSuccessGnbTypeFailure(t *testing.T) { + oldServedCells := generateServedCells("whatever1", "whatever2") + context := controllerUpdateEnbTestContext{ + getNodebInfoResult: &getNodebInfoResult{ + nodebInfo: &entities.NodebInfo{ + RanName: RanName, + ConnectionStatus: entities.ConnectionStatus_CONNECTED, + AssociatedE2TInstanceAddress: AssociatedE2TInstanceAddress, + NodeType: entities.Node_GNB, + Configuration: &entities.NodebInfo_Enb{Enb: &entities.Enb{ServedCells: oldServedCells}}, + }, + rnibError: nil, + }, + requestBody: getUpdateEnbRequest(""), + expectedStatusCode: http.StatusBadRequest, + expectedJsonResponse: ValidationFailureJson, + } + + controllerUpdateEnbTestExecuter(t, &context) +} + +func TestControllerUpdateEnbGetNodebSuccessRemoveServedCellsFailure(t *testing.T) { + oldServedCells := generateServedCells("whatever1", "whatever2") + context := controllerUpdateEnbTestContext{ + removeServedCellsParams: &removeServedCellsParams{ + err: common.NewInternalError(errors.New("#writer.RemoveServedCells - Internal Error")), + servedCellInfo: oldServedCells, + }, + 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}}, + }, + rnibError: nil, + }, + requestBody: getUpdateEnbRequest(""), + expectedStatusCode: http.StatusInternalServerError, + expectedJsonResponse: RnibErrorJson, + } + + controllerUpdateEnbTestExecuter(t, &context) +} + +func TestControllerUpdateEnbGetNodebSuccessUpdateEnbFailure(t *testing.T) { + oldServedCells := generateServedCells("whatever1", "whatever2") + context := controllerUpdateEnbTestContext{ + removeServedCellsParams: &removeServedCellsParams{ + err: nil, + servedCellInfo: oldServedCells, + }, + updateEnbCellsParams: &updateEnbCellsParams{ + err: common.NewInternalError(errors.New("#writer.UpdateEnb - Internal Error")), + }, + 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_ENB}}, + }, + rnibError: nil, + }, + requestBody: getUpdateEnbRequest(""), + expectedStatusCode: http.StatusInternalServerError, + expectedJsonResponse: RnibErrorJson, + } + + controllerUpdateEnbTestExecuter(t, &context) +} + +func TestControllerUpdateEnbSuccess(t *testing.T) { + oldServedCells := generateServedCells("whatever1", "whatever2") + context := controllerUpdateEnbTestContext{ + removeServedCellsParams: &removeServedCellsParams{ + err: nil, + servedCellInfo: oldServedCells, + }, + updateEnbCellsParams: &updateEnbCellsParams{ + err: 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_ENB}}, + }, + rnibError: nil, + }, + requestBody: getUpdateEnbRequest(""), + expectedStatusCode: http.StatusOK, + expectedJsonResponse: "{\"ranName\":\"test\",\"connectionStatus\":\"CONNECTED\",\"nodeType\":\"ENB\",\"enb\":{\"enbType\":\"MACRO_ENB\",\"servedCells\":[{\"pci\":1,\"cellId\":\"whatever\",\"tac\":\"whatever3\",\"broadcastPlmns\":[\"whatever\"],\"choiceEutraMode\":{\"fdd\":{}},\"eutraMode\":\"FDD\"}]},\"associatedE2tInstanceAddress\":\"10.0.2.15:38000\"}", + } + + controllerUpdateEnbTestExecuter(t, &context) +} + func TestControllerAddEnbGetNodebInternalError(t *testing.T) { context := controllerAddEnbTestContext{ getNodebInfoResult: &getNodebInfoResult{ @@ -859,6 +1143,29 @@ func TestControllerAddEnbMissingRequiredEnbProps(t *testing.T) { } } +func TestControllerUpdateEnbMissingRequiredServedCellProps(t *testing.T) { + + r := getUpdateEnbRequest("") + + for _, v := range ServedCellRequiredFields { + enb := r["enb"] + + enbMap, _ := enb.(map[string]interface{}) + + enbMap["servedCells"] = []interface{}{ + buildServedCell(v), + } + + context := controllerUpdateEnbTestContext{ + requestBody: r, + expectedStatusCode: http.StatusBadRequest, + expectedJsonResponse: ValidationFailureJson, + } + + controllerUpdateEnbTestExecuter(t, &context) + } +} + func TestControllerAddEnbMissingRequiredServedCellProps(t *testing.T) { r := getAddEnbRequest("") @@ -917,7 +1224,7 @@ func TestControllerDeleteEnbGetNodebInternalError(t *testing.T) { nodebInfo: nil, rnibError: common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")), }, - expectedStatusCode: http.StatusInternalServerError, + expectedStatusCode: http.StatusInternalServerError, expectedJsonResponse: RnibErrorJson, } @@ -956,7 +1263,7 @@ func TestControllerDeleteEnbSuccess(t *testing.T) { nodebInfo: &entities.NodebInfo{RanName: "ran1", NodeType: entities.Node_ENB, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}, rnibError: nil, }, - expectedStatusCode: http.StatusNoContent, + expectedStatusCode: http.StatusNoContent, expectedJsonResponse: "", } controllerDeleteEnbTestExecuter(t, &context) diff --git a/E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler.go b/E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler.go index 6afe87a..dae272a 100644 --- a/E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler.go +++ b/E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler.go @@ -44,7 +44,10 @@ func NewUpdateNodebRequestHandler(logger *logger.Logger, rNibDataService service func (h *UpdateNodebRequestHandler) Handle(request models.Request) (models.IResponse, error) { - updateNodebRequest := request.(*models.UpdateNodebRequest) + updateNodebRequest, ok := request.(*models.UpdateEnbRequest) + if ok != true { + //TODO updateNodebRequest := request.(*models.UpdateGnbRequest) + } h.logger.Infof("#UpdateNodebRequestHandler.Handle - Ran name: %s", updateNodebRequest.RanName) diff --git a/E2Manager/managers/i_update_nodeb_manager.go b/E2Manager/managers/i_update_nodeb_manager.go index 0828ce1..4f911f3 100644 --- a/E2Manager/managers/i_update_nodeb_manager.go +++ b/E2Manager/managers/i_update_nodeb_manager.go @@ -25,8 +25,8 @@ import ( ) type IUpdateNodebManager interface { - Validate(request *models.UpdateNodebRequest) error + Validate(request models.Request) error RemoveNodebCells(nodeb *entities.NodebInfo) error - SetNodeb(nodeb *entities.NodebInfo, request *models.UpdateNodebRequest) error + SetNodeb(nodeb *entities.NodebInfo, request models.Request) error UpdateNodeb(nodeb *entities.NodebInfo) error } diff --git a/E2Manager/managers/update_enb_manager.go b/E2Manager/managers/update_enb_manager.go index 6c9ae14..005e9bb 100644 --- a/E2Manager/managers/update_enb_manager.go +++ b/E2Manager/managers/update_enb_manager.go @@ -25,6 +25,7 @@ import ( "e2mgr/models" "e2mgr/services" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" + "github.com/pkg/errors" ) type UpdateEnbManager struct { @@ -41,12 +42,15 @@ func NewUpdateEnbManager(logger *logger.Logger, rnibDataService services.RNibDat } } -func (h *UpdateEnbManager) Validate(request *models.UpdateNodebRequest) error { +func (h *UpdateEnbManager) Validate(request models.Request) error { - h.logger.Infof("#UpdateEnbManager.Validate - Validate incoming request, ran name: %s", request.RanName) + updateEnbRequest := request.(*models.UpdateEnbRequest) - if err := h.nodebValidator.IsEnbValid(request.Enb); err != nil { - //TODO add log + h.logger.Infof("#UpdateEnbManager.Validate - Validate incoming request, ran name: %s", updateEnbRequest.RanName) + + + if err := h.validateRequestBody(updateEnbRequest); err != nil { + h.logger.Errorf("#UpdateEnbManager.Validate - validation failure: %s is a mandatory field and cannot be empty", err) return err } @@ -55,6 +59,11 @@ func (h *UpdateEnbManager) Validate(request *models.UpdateNodebRequest) error { func (h *UpdateEnbManager) RemoveNodebCells(nodeb *entities.NodebInfo) error { + if nodeb.NodeType != entities.Node_ENB { + h.logger.Errorf("#UpdateEnbManager.RemoveNodebCells - RAN name: %s - nodeb missing eNB configuration", nodeb.GetRanName()) + return e2managererrors.NewRequestValidationError() + } + err := h.rnibDataService.RemoveServedCells(nodeb.GetRanName(), nodeb.GetEnb().GetServedCells()) if err != nil { h.logger.Errorf("#UpdateEnbManager.RemoveNodebCells - RAN name: %s - Failed removing eNB served cells", nodeb.GetRanName()) @@ -65,15 +74,11 @@ func (h *UpdateEnbManager) RemoveNodebCells(nodeb *entities.NodebInfo) error { return nil } -func (h *UpdateEnbManager) SetNodeb(nodeb *entities.NodebInfo, request *models.UpdateNodebRequest) error { +func (h *UpdateEnbManager) SetNodeb(nodeb *entities.NodebInfo, request models.Request) error { - ranName := nodeb.GetRanName() + updateEnbRequest := request.(*models.UpdateEnbRequest) - if nodeb.NodeType != entities.Node_ENB { - h.logger.Errorf("#UpdateEnbManager.SetNodeb - RAN name: %s - nodeb missing eNB configuration", ranName) - return e2managererrors.NewRequestValidationError() - } - nodeb.Configuration = &entities.NodebInfo_Enb{Enb: request.Enb} + nodeb.Configuration = &entities.NodebInfo_Enb{Enb: updateEnbRequest.Enb} return nil } @@ -89,3 +94,16 @@ func (h *UpdateEnbManager) UpdateNodeb(nodeb *entities.NodebInfo) error { return nil } + +func (h *UpdateEnbManager) validateRequestBody(request *models.UpdateEnbRequest) error { + + if request.Enb == nil { + return errors.New("enb") + } + + if err := h.nodebValidator.IsEnbValid(request.Enb); err != nil { + return err + } + + return nil +} \ No newline at end of file diff --git a/E2Manager/models/update_enb_request.go b/E2Manager/models/update_enb_request.go index 1d6a63a..79d970c 100644 --- a/E2Manager/models/update_enb_request.go +++ b/E2Manager/models/update_enb_request.go @@ -19,10 +19,40 @@ package models -import "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" +import ( + "encoding/json" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" + "github.com/golang/protobuf/jsonpb" +) + +type UpdateEnbRawRequest struct { + RanName string + Enb json.RawMessage +} type UpdateEnbRequest struct { - RanName string - *entities.Enb - *entities.Gnb + RanName string + Enb *entities.Enb +} + +func (r *UpdateEnbRequest) UnmarshalJSON(data []byte) error { + updateEnbRawRequest := UpdateEnbRawRequest{} + err := json.Unmarshal(data, &updateEnbRawRequest) + + if err != nil { + return err + } + + if updateEnbRawRequest.Enb != nil { + enb := entities.Enb{} + err = jsonpb.UnmarshalString(string(updateEnbRawRequest.Enb), &enb) + + if err != nil { + return err + } + + r.Enb = &enb + } + + return nil } \ No newline at end of file diff --git a/E2Manager/models/update_nodeb_request.go b/E2Manager/models/update_nodeb_request.go deleted file mode 100644 index ad351bb..0000000 --- a/E2Manager/models/update_nodeb_request.go +++ /dev/null @@ -1,28 +0,0 @@ -// -// 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 models - -import "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" - -type UpdateNodebRequest struct { - RanName string - *entities.Enb - *entities.Gnb -} \ No newline at end of file diff --git a/E2Manager/rNibWriter/rNibWriter_test.go b/E2Manager/rNibWriter/rNibWriter_test.go index 75cf7b0..0685743 100644 --- a/E2Manager/rNibWriter/rNibWriter_test.go +++ b/E2Manager/rNibWriter/rNibWriter_test.go @@ -157,6 +157,34 @@ func TestUpdateGnbCellsInvalidCellFailure(t *testing.T) { assert.IsType(t, &common.ValidationError{}, rNibErr) } +func getUpdateEnbCellsSetExpected(t *testing.T, nodebInfo *entities.NodebInfo, servedCells []*entities.ServedCellInfo) []interface{} { + + nodebInfoData, err := proto.Marshal(nodebInfo) + if err != nil { + t.Fatalf("#rNibWriter_test.getUpdateEnbCellsSetExpected - Failed to marshal NodeB entity. Error: %s", err) + } + + nodebNameKey, _ := common.ValidateAndBuildNodeBNameKey(nodebInfo.RanName) + nodebIdKey, _ := common.ValidateAndBuildNodeBIdKey(nodebInfo.NodeType.String(), nodebInfo.GlobalNbId.PlmnId, nodebInfo.GlobalNbId.NbId) + setExpected := []interface{}{nodebNameKey, nodebInfoData, nodebIdKey, nodebInfoData} + + for _, cell := range servedCells { + + cellEntity := entities.Cell{Type: entities.Cell_LTE_CELL, Cell: &entities.Cell_ServedCellInfo{ServedCellInfo: cell}} + cellData, err := proto.Marshal(&cellEntity) + + if err != nil { + t.Fatalf("#rNibWriter_test.getUpdateEnbCellsSetExpected - Failed to marshal cell entity. Error: %s", err) + } + + nrCellIdKey, _ := common.ValidateAndBuildCellIdKey(cell.GetCellId()) + cellNamePciKey, _ := common.ValidateAndBuildCellNamePciKey(nodebInfo.RanName, cell.GetPci()) + setExpected = append(setExpected, nrCellIdKey, cellData, cellNamePciKey, cellData) + } + + return setExpected +} + func getUpdateGnbCellsSetExpected(t *testing.T, nodebInfo *entities.NodebInfo, servedNrCells []*entities.ServedNRCell) []interface{} { nodebInfoData, err := proto.Marshal(nodebInfo) @@ -884,6 +912,18 @@ func TestSaveGeneralConfigurationDbError(t *testing.T) { assert.NotNil(t, rNibErr) } + +func TestRemoveServedCellsFailure(t *testing.T) { + w, sdlInstanceMock := initSdlInstanceMock(namespace) + servedCellsToRemove := generateServedCells("whatever1", "whatever2") + expectedErr := errors.New("expected error") + sdlInstanceMock.On("Remove", buildServedCellInfoKeysToRemove(RanName, servedCellsToRemove)).Return(expectedErr) + + rNibErr := w.RemoveServedCells(RanName, servedCellsToRemove) + + assert.NotNil(t, rNibErr) +} + func TestRemoveServedCellsSuccess(t *testing.T) { w, sdlInstanceMock := initSdlInstanceMock(namespace) servedCellsToRemove := generateServedCells("whatever1", "whatever2") @@ -914,35 +954,35 @@ func TestUpdateEnbInvalidCellFailure(t *testing.T) { assert.IsType(t, &common.ValidationError{}, rNibErr) } -/*func TestUpdateEnbSdlFailure(t *testing.T) { - inventoryName := "ranName" +func TestUpdateEnbSdlFailure(t *testing.T) { + inventoryName := "name" plmnId := "02f829" nbId := "4a952a0a" w, sdlInstanceMock := initSdlInstanceMock(namespace) servedCells := generateServedCells("test1", "test2") - nodebInfo := generateNodebInfo(inventoryName, entities.Node_GNB, plmnId, nbId) + nodebInfo := generateNodebInfo(inventoryName, entities.Node_ENB, plmnId, nbId) nodebInfo.GetEnb().ServedCells = servedCells - setExpected := getUpdateEnbSetExpected(t, nodebInfo, servedCells) + setExpected := getUpdateEnbCellsSetExpected(t, nodebInfo, servedCells) sdlInstanceMock.On("SetAndPublish", []string{"RAN_MANIPULATION", inventoryName + "_" + RanUpdatedEvent}, []interface{}{setExpected}).Return(errors.New("expected error")) rNibErr := w.UpdateEnb(nodebInfo, servedCells) assert.IsType(t, &common.InternalError{}, rNibErr) -}*/ +} -/*func TestUpdateEnbSuccess(t *testing.T) { - inventoryName := "ranName" +func TestUpdateEnbSuccess(t *testing.T) { + inventoryName := "name" plmnId := "02f829" nbId := "4a952a0a" w, sdlInstanceMock := initSdlInstanceMock(namespace) servedCells := generateServedCells("test1", "test2") - nodebInfo := generateNodebInfo(inventoryName, entities.Node_GNB, plmnId, nbId) + nodebInfo := generateNodebInfo(inventoryName, entities.Node_ENB, plmnId, nbId) nodebInfo.GetEnb().ServedCells = servedCells - setExpected := getUpdateEnbSetExpected(t, nodebInfo, servedCells) + setExpected := getUpdateEnbCellsSetExpected(t, nodebInfo, servedCells) var e error sdlInstanceMock.On("SetAndPublish", []string{"RAN_MANIPULATION", inventoryName + "_" + RanUpdatedEvent}, []interface{}{setExpected}).Return(e) rNibErr := w.UpdateEnb(nodebInfo, servedCells) assert.Nil(t, rNibErr) -}*/ +} func getUpdateEnbSetExpected(t *testing.T, nodebInfo *entities.NodebInfo, servedCells []*entities.ServedCellInfo) []interface{} { -- 2.16.6