From: Irina Date: Wed, 8 Jul 2020 18:11:04 +0000 (+0000) Subject: [RIC-432] - Support Update eNB REST API. X-Git-Tag: R5_RC~51 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=5830d4db63151dd466533673fd76d842302f0034;hp=611eba27c24f595a57f7c55068605a57788ead95;p=ric-plt%2Fe2mgr.git [RIC-432] - Support Update eNB REST API. Change-Id: I1bca32a371dd001e6edebe21728d9c68f4c9ea80 Signed-off-by: Irina --- diff --git a/E2Manager/app/main.go b/E2Manager/app/main.go index 0ad6412..dd30907 100644 --- a/E2Manager/app/main.go +++ b/E2Manager/app/main.go @@ -71,6 +71,8 @@ func main() { notificationManager := notificationmanager.NewNotificationManager(logger, rmrNotificationHandlerProvider) rmrReceiver := rmrreceiver.NewRmrReceiver(logger, rmrMessenger, notificationManager) nodebValidator := managers.NewNodebValidator() + updateEnbManager := managers.NewUpdateEnbManager(logger, rnibDataService, nodebValidator) + e2tInstancesManager.ResetKeepAliveTimestampsForAllE2TInstances() defer rmrMessenger.Close() @@ -78,7 +80,7 @@ func main() { go rmrReceiver.ListenAndHandle() go e2tKeepAliveWorker.Execute() - httpMsgHandlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(logger, rmrSender, config, rnibDataService, e2tInstancesManager, routingManagerClient, ranConnectStatusChangeManager, nodebValidator) + httpMsgHandlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(logger, rmrSender, config, rnibDataService, e2tInstancesManager, routingManagerClient, ranConnectStatusChangeManager, nodebValidator, updateEnbManager) rootController := controllers.NewRootController(rnibDataService) nodebController := controllers.NewNodebController(logger, httpMsgHandlerProvider) e2tController := controllers.NewE2TController(logger, httpMsgHandlerProvider) diff --git a/E2Manager/container-tag.yaml b/E2Manager/container-tag.yaml index a83a80a..9309859 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.9 +tag: 5.3.0 diff --git a/E2Manager/controllers/e2t_controller_test.go b/E2Manager/controllers/e2t_controller_test.go index 915e78e..5db1832 100644 --- a/E2Manager/controllers/e2t_controller_test.go +++ b/E2Manager/controllers/e2t_controller_test.go @@ -59,8 +59,9 @@ func setupE2TControllerTest(t *testing.T) (*E2TController, *mocks.RnibReaderMock ranAlarmService := services.NewRanAlarmService(log, config) ranConnectStatusChangeManager := managers.NewRanConnectStatusChangeManager(log, rnibDataService,ranListManager, ranAlarmService) nodebValidator := managers.NewNodebValidator() + updateEnbManager := managers.NewUpdateEnbManager(log, rnibDataService, nodebValidator) - handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, nil, config, rnibDataService, e2tInstancesManager, nil, ranConnectStatusChangeManager, nodebValidator) + handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, nil, config, rnibDataService, e2tInstancesManager, nil, ranConnectStatusChangeManager, nodebValidator, updateEnbManager) controller := NewE2TController(log, handlerProvider) return controller, readerMock } diff --git a/E2Manager/controllers/nodeb_controller.go b/E2Manager/controllers/nodeb_controller.go index 1d9f50c..3ff453e 100644 --- a/E2Manager/controllers/nodeb_controller.go +++ b/E2Manager/controllers/nodeb_controller.go @@ -48,6 +48,7 @@ type INodebController interface { X2Reset(writer http.ResponseWriter, r *http.Request) GetNodeb(writer http.ResponseWriter, r *http.Request) UpdateGnb(writer http.ResponseWriter, r *http.Request) + UpdateEnb(writer http.ResponseWriter, r *http.Request) GetNodebIdList(writer http.ResponseWriter, r *http.Request) SetGeneralConfiguration(writer http.ResponseWriter, r *http.Request) AddEnb(writer http.ResponseWriter, r *http.Request) @@ -98,6 +99,24 @@ func (c *NodebController) UpdateGnb(writer http.ResponseWriter, r *http.Request) c.handleRequest(writer, &r.Header, httpmsghandlerprovider.UpdateGnbRequest, request, true, http.StatusOK) } +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{} + + enb := entities.Enb{} + + if !c.extractRequestBodyToProto(r, &enb, writer) { + return + } + + request.Enb = &enb + request.RanName = ranName + c.handleRequest(writer, &r.Header, httpmsghandlerprovider.UpdateEnbRequest, request, true, http.StatusOK) +} + func (c *NodebController) AddEnb(writer http.ResponseWriter, r *http.Request) { c.logger.Infof("[Client -> E2 Manager] #NodebController.AddEnb - request: %v", c.prettifyRequest(r)) diff --git a/E2Manager/controllers/nodeb_controller_test.go b/E2Manager/controllers/nodeb_controller_test.go index fc59673..7ee44d7 100644 --- a/E2Manager/controllers/nodeb_controller_test.go +++ b/E2Manager/controllers/nodeb_controller_test.go @@ -262,7 +262,9 @@ func setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, ranAlarmService := &mocks.RanAlarmServiceMock{} ranConnectStatusChangeManager := managers.NewRanConnectStatusChangeManager(log, rnibDataService, ranListManager, ranAlarmService) nodebValidator := managers.NewNodebValidator() - handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, rmrSender, config, rnibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager, nodebValidator) + updateEnbManager := managers.NewUpdateEnbManager(log, rnibDataService, nodebValidator) + + handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, rmrSender, config, rnibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager, nodebValidator, updateEnbManager) controller := NewNodebController(log, handlerProvider) return controller, readerMock, writerMock, rmrMessengerMock, e2tInstancesManager } @@ -949,7 +951,7 @@ func TestControllerGetNodebIdListSuccess(t *testing.T) { func TestControllerGetNodebIdListEmptySuccess(t *testing.T) { var rnibError error - nodebIdList := []*entities.NbIdentity{} + var nodebIdList []*entities.NbIdentity context := controllerGetNodebIdListTestContext{ nodebIdList: nodebIdList, diff --git a/E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler.go b/E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler.go new file mode 100644 index 0000000..6afe87a --- /dev/null +++ b/E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler.go @@ -0,0 +1,84 @@ +// +// 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" +) + +type UpdateNodebRequestHandler struct { + logger *logger.Logger + rNibDataService services.RNibDataService + updateNodebManager managers.IUpdateNodebManager +} + +func NewUpdateNodebRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService, updateNodebManager managers.IUpdateNodebManager) *UpdateNodebRequestHandler { + return &UpdateNodebRequestHandler{ + logger: logger, + rNibDataService: rNibDataService, + updateNodebManager: updateNodebManager, + } +} + +func (h *UpdateNodebRequestHandler) Handle(request models.Request) (models.IResponse, error) { + + updateNodebRequest := request.(*models.UpdateNodebRequest) + + h.logger.Infof("#UpdateNodebRequestHandler.Handle - Ran name: %s", updateNodebRequest.RanName) + + err := h.updateNodebManager.Validate(updateNodebRequest) + if err != nil { + return nil, e2managererrors.NewRequestValidationError() + } + + nodebInfo, err := h.rNibDataService.GetNodeb(updateNodebRequest.RanName) + if err != nil { + _, ok := err.(*common.ResourceNotFoundError) + if !ok { + h.logger.Errorf("#UpdateNodebRequestHandler.Handle - RAN name: %s - failed to get nodeb entity from RNIB. Error: %s", updateNodebRequest.RanName, err) + return nil, e2managererrors.NewRnibDbError() + } + + h.logger.Errorf("#UpdateNodebRequestHandler.Handle - RAN name: %s - RAN not found on RNIB. Error: %s", updateNodebRequest.RanName, err) + return nil, e2managererrors.NewResourceNotFoundError() + } + + err = h.updateNodebManager.RemoveNodebCells(nodebInfo) + if err != nil { + return nil, err + } + + err = h.updateNodebManager.SetNodeb(nodebInfo, updateNodebRequest) + if err != nil { + return nil, err + } + + err = h.updateNodebManager.UpdateNodeb(nodebInfo) + if err != nil { + return nil, err + } + + return models.NewNodebResponse(nodebInfo), nil +} diff --git a/E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler_test.go b/E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler_test.go new file mode 100644 index 0000000..ff4b9f8 --- /dev/null +++ b/E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler_test.go @@ -0,0 +1,20 @@ +// +// 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 diff --git a/E2Manager/httpserver/http_server.go b/E2Manager/httpserver/http_server.go index 1d29dcd..157f5bd 100644 --- a/E2Manager/httpserver/http_server.go +++ b/E2Manager/httpserver/http_server.go @@ -50,6 +50,7 @@ func initializeRoutes(router *mux.Router, rootController controllers.IRootContro rr.HandleFunc("/enb", nodebController.AddEnb).Methods(http.MethodPost) rr.HandleFunc("/enb/{ranName}", nodebController.DeleteEnb).Methods(http.MethodDelete) rr.HandleFunc("/{ranName}/update", nodebController.UpdateGnb).Methods(http.MethodPut) + 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) rrr := r.PathPrefix("/e2t").Subrouter() diff --git a/E2Manager/httpserver/http_server_test.go b/E2Manager/httpserver/http_server_test.go index 6378f8c..fbaecbe 100644 --- a/E2Manager/httpserver/http_server_test.go +++ b/E2Manager/httpserver/http_server_test.go @@ -41,6 +41,7 @@ func setupRouterAndMocks() (*mux.Router, *mocks.RootControllerMock, *mocks.Nodeb nodebControllerMock.On("SetGeneralConfiguration").Return(nil) nodebControllerMock.On("DeleteEnb").Return(nil) nodebControllerMock.On("AddEnb").Return(nil) + nodebControllerMock.On("UpdateEnb").Return(nil) e2tControllerMock := &mocks.E2TControllerMock{} @@ -118,6 +119,19 @@ func TestRoutePutNodebSetGeneralConfiguration(t *testing.T) { nodebControllerMock.AssertNumberOfCalls(t, "SetGeneralConfiguration", 1) } +func TestRoutePutUpdateEnb(t *testing.T) { + router, _, nodebControllerMock, _ := setupRouterAndMocks() + + req, err := http.NewRequest("PUT", "/v1/nodeb/enb/ran1", nil) + if err != nil { + t.Fatal(err) + } + rr := httptest.NewRecorder() + router.ServeHTTP(rr, req) + + nodebControllerMock.AssertNumberOfCalls(t, "UpdateEnb", 1) +} + func TestRouteNotFound(t *testing.T) { router, _, _, _ := setupRouterAndMocks() diff --git a/E2Manager/managers/i_update_nodeb_manager.go b/E2Manager/managers/i_update_nodeb_manager.go new file mode 100644 index 0000000..0828ce1 --- /dev/null +++ b/E2Manager/managers/i_update_nodeb_manager.go @@ -0,0 +1,32 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source code is part of the near-RT RIC (RAN Intelligent Controller) +// platform project (RICP). + +package managers + +import ( + "e2mgr/models" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" +) + +type IUpdateNodebManager interface { + Validate(request *models.UpdateNodebRequest) error + RemoveNodebCells(nodeb *entities.NodebInfo) error + SetNodeb(nodeb *entities.NodebInfo, request *models.UpdateNodebRequest) error + UpdateNodeb(nodeb *entities.NodebInfo) error +} diff --git a/E2Manager/managers/update_enb_manager.go b/E2Manager/managers/update_enb_manager.go new file mode 100644 index 0000000..6c9ae14 --- /dev/null +++ b/E2Manager/managers/update_enb_manager.go @@ -0,0 +1,91 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source code is part of the near-RT RIC (RAN Intelligent Controller) +// platform project (RICP). + +package managers + +import ( + "e2mgr/e2managererrors" + "e2mgr/logger" + "e2mgr/models" + "e2mgr/services" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" +) + +type UpdateEnbManager struct { + logger *logger.Logger + rnibDataService services.RNibDataService + nodebValidator *NodebValidator +} + +func NewUpdateEnbManager(logger *logger.Logger, rnibDataService services.RNibDataService, nodebValidator *NodebValidator) *UpdateEnbManager { + return &UpdateEnbManager{ + logger: logger, + rnibDataService: rnibDataService, + nodebValidator: nodebValidator, + } +} + +func (h *UpdateEnbManager) Validate(request *models.UpdateNodebRequest) error { + + h.logger.Infof("#UpdateEnbManager.Validate - Validate incoming request, ran name: %s", request.RanName) + + if err := h.nodebValidator.IsEnbValid(request.Enb); err != nil { + //TODO add log + return err + } + + return nil +} + +func (h *UpdateEnbManager) RemoveNodebCells(nodeb *entities.NodebInfo) error { + + 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()) + return e2managererrors.NewRnibDbError() + } + h.logger.Infof("#UpdateEnbManager.RemoveNodebCells - RAN name: %s - Successfully removed eNB served cells", nodeb.GetRanName()) + + return nil +} + +func (h *UpdateEnbManager) SetNodeb(nodeb *entities.NodebInfo, request *models.UpdateNodebRequest) error { + + ranName := nodeb.GetRanName() + + 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} + + return nil +} + +func (h *UpdateEnbManager) UpdateNodeb(nodeb *entities.NodebInfo) error { + + err := h.rnibDataService.UpdateEnb(nodeb, nodeb.GetEnb().GetServedCells()) + if err != nil { + h.logger.Errorf("#UpdateEnbManager.UpdateNodeb - RAN name: %s - Failed updating eNB. Error: %s", nodeb.GetRanName(), err) + return e2managererrors.NewRnibDbError() + } + h.logger.Infof("#UpdateEnbManager.UpdateNodeb - RAN name: %s - Successfully updated eNB", nodeb.GetRanName()) + + return nil +} diff --git a/E2Manager/managers/update_enb_manager_test.go b/E2Manager/managers/update_enb_manager_test.go new file mode 100644 index 0000000..c107157 --- /dev/null +++ b/E2Manager/managers/update_enb_manager_test.go @@ -0,0 +1,20 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source code is part of the near-RT RIC (RAN Intelligent Controller) +// platform project (RICP). + +package managers diff --git a/E2Manager/mocks/nodeb_controller_mock.go b/E2Manager/mocks/nodeb_controller_mock.go index 2f1a15d..2467666 100644 --- a/E2Manager/mocks/nodeb_controller_mock.go +++ b/E2Manager/mocks/nodeb_controller_mock.go @@ -68,6 +68,13 @@ func (c *NodebControllerMock) UpdateGnb(writer http.ResponseWriter, r *http.Requ c.Called() } +func (c *NodebControllerMock) UpdateEnb(writer http.ResponseWriter, r *http.Request) { + writer.Header().Set("Content-Type", "application/json") + writer.WriteHeader(http.StatusOK) + + c.Called() +} + func (c *NodebControllerMock) AddEnb(writer http.ResponseWriter, r *http.Request) { writer.Header().Set("Content-Type", "application/json") writer.WriteHeader(http.StatusCreated) diff --git a/E2Manager/mocks/rnibWriterMock.go b/E2Manager/mocks/rnibWriterMock.go index 292e455..f84d845 100644 --- a/E2Manager/mocks/rnibWriterMock.go +++ b/E2Manager/mocks/rnibWriterMock.go @@ -107,5 +107,17 @@ func (rnibWriterMock *RnibWriterMock) SaveGeneralConfiguration(config *entities. func (rnibWriterMock *RnibWriterMock) RemoveEnb(nodebInfo *entities.NodebInfo) error { args := rnibWriterMock.Called(nodebInfo) + return args.Error(0) +} + +func (rnibWriterMock *RnibWriterMock) RemoveServedCells(inventoryName string, servedCells []*entities.ServedCellInfo) error { + args := rnibWriterMock.Called(inventoryName, servedCells) + + return args.Error(0) +} + +func (rnibWriterMock *RnibWriterMock) UpdateEnb(nodebInfo *entities.NodebInfo, servedCells []*entities.ServedCellInfo) error { + args := rnibWriterMock.Called(nodebInfo, servedCells) + return args.Error(0) } \ No newline at end of file diff --git a/E2Manager/models/nodeb_response.go b/E2Manager/models/nodeb_response.go new file mode 100644 index 0000000..3acf695 --- /dev/null +++ b/E2Manager/models/nodeb_response.go @@ -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 models + +import ( + "e2mgr/e2managererrors" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" + "github.com/golang/protobuf/jsonpb" +) + +type NodebResponse struct { + nodebInfo *entities.NodebInfo +} + +func NewNodebResponse(nodebInfo *entities.NodebInfo) *NodebResponse { + return &NodebResponse{ + nodebInfo: nodebInfo, + } +} + +func (response *NodebResponse) Marshal() ([]byte, error) { + m := jsonpb.Marshaler{} + result, err := m.MarshalToString(response.nodebInfo) + + if err != nil { + return nil, e2managererrors.NewInternalError() + } + + return []byte(result), nil +} diff --git a/E2Manager/models/update_enb_request.go b/E2Manager/models/update_enb_request.go new file mode 100644 index 0000000..1d6a63a --- /dev/null +++ b/E2Manager/models/update_enb_request.go @@ -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 models + +import "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" + +type UpdateEnbRequest struct { + RanName string + *entities.Enb + *entities.Gnb +} \ No newline at end of file diff --git a/E2Manager/models/update_nodeb_request.go b/E2Manager/models/update_nodeb_request.go new file mode 100644 index 0000000..ad351bb --- /dev/null +++ b/E2Manager/models/update_nodeb_request.go @@ -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 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/providers/httpmsghandlerprovider/incoming_request_handler_provider.go b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go index b5e0d1d..2dba750 100644 --- a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go +++ b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go @@ -40,6 +40,7 @@ const ( GetNodebIdListRequest IncomingRequest = "GetNodebIdListRequest" GetE2TInstancesRequest IncomingRequest = "GetE2TInstancesRequest" UpdateGnbRequest IncomingRequest = "UpdateGnbRequest" + UpdateEnbRequest IncomingRequest = "UpdateEnbRequest" AddEnbRequest IncomingRequest = "AddEnbRequest" DeleteEnbRequest IncomingRequest = "DeleteEnbRequest" ) @@ -50,16 +51,16 @@ type IncomingRequestHandlerProvider struct { ranConnectStatusChangeManager managers.IRanConnectStatusChangeManager } -func NewIncomingRequestHandlerProvider(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, e2tInstancesManager managers.IE2TInstancesManager, rmClient clients.IRoutingManagerClient, ranConnectStatusChangeManager managers.IRanConnectStatusChangeManager, nodebValidator *managers.NodebValidator) *IncomingRequestHandlerProvider { +func NewIncomingRequestHandlerProvider(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) *IncomingRequestHandlerProvider { return &IncomingRequestHandlerProvider{ - requestMap: initRequestHandlerMap(logger, rmrSender, config, rNibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager, nodebValidator), + requestMap: initRequestHandlerMap(logger, rmrSender, config, rNibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager, nodebValidator, updateEnbManager), logger: logger, ranConnectStatusChangeManager: ranConnectStatusChangeManager, } } -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) 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) map[IncomingRequest]httpmsghandlers.RequestHandler { return map[IncomingRequest]httpmsghandlers.RequestHandler{ ShutdownRequest: httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrSender, config, rNibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager), @@ -69,6 +70,7 @@ func initRequestHandlerMap(logger *logger.Logger, rmrSender *rmrsender.RmrSender GetNodebIdListRequest: httpmsghandlers.NewGetNodebIdListRequestHandler(logger, rNibDataService), GetE2TInstancesRequest: httpmsghandlers.NewGetE2TInstancesRequestHandler(logger, e2tInstancesManager), UpdateGnbRequest: httpmsghandlers.NewUpdateGnbRequestHandler(logger, rNibDataService), + UpdateEnbRequest: httpmsghandlers.NewUpdateNodebRequestHandler(logger, rNibDataService, updateEnbManager), AddEnbRequest: httpmsghandlers.NewAddEnbRequestHandler(logger, rNibDataService, nodebValidator), DeleteEnbRequest: httpmsghandlers.NewDeleteEnbRequestHandler(logger, rNibDataService), } diff --git a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go index f47fae2..5ce3b9c 100644 --- a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go +++ b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go @@ -17,7 +17,6 @@ // This source code is part of the near-RT RIC (RAN Intelligent Controller) // platform project (RICP). - package httpmsghandlerprovider import ( @@ -57,9 +56,11 @@ func setupTest(t *testing.T) *IncomingRequestHandlerProvider { rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock) ranListManager := managers.NewRanListManager(log) ranAlarmService := services.NewRanAlarmService(log, config) - ranConnectStatusChangeManager := managers.NewRanConnectStatusChangeManager(log, rnibDataService,ranListManager, ranAlarmService) + ranConnectStatusChangeManager := managers.NewRanConnectStatusChangeManager(log, rnibDataService, ranListManager, ranAlarmService) nodebValidator := managers.NewNodebValidator() - return NewIncomingRequestHandlerProvider(log, rmrSender, configuration.ParseConfiguration(), rnibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager, nodebValidator) + updateEnbManager := managers.NewUpdateEnbManager(log, rnibDataService, nodebValidator) + + return NewIncomingRequestHandlerProvider(log, rmrSender, configuration.ParseConfiguration(), rnibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager, nodebValidator, updateEnbManager) } func TestNewIncomingRequestHandlerProvider(t *testing.T) { diff --git a/E2Manager/rNibWriter/rNibWriter.go b/E2Manager/rNibWriter/rNibWriter.go index c73cc37..d874938 100644 --- a/E2Manager/rNibWriter/rNibWriter.go +++ b/E2Manager/rNibWriter/rNibWriter.go @@ -55,6 +55,8 @@ type RNibWriter interface { UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, ent string) error SaveGeneralConfiguration(config *entities.GeneralConfiguration) error RemoveEnb(nodebInfo *entities.NodebInfo) error + RemoveServedCells(inventoryName string, servedCells []*entities.ServedCellInfo) error + UpdateEnb(nodebInfo *entities.NodebInfo, servedCells []*entities.ServedCellInfo) error } /* @@ -67,6 +69,19 @@ func GetRNibWriter(sdl common.ISdlInstance, rnibWriterConfig configuration.RnibW func (w *rNibWriterInstance) RemoveServedNrCells(inventoryName string, servedNrCells []*entities.ServedNRCell) error { cellKeysToRemove := buildServedNRCellKeysToRemove(inventoryName, servedNrCells) + + err := w.sdl.Remove(cellKeysToRemove) + + if err != nil { + return common.NewInternalError(err) + } + + return nil +} + +func (w *rNibWriterInstance) RemoveServedCells(inventoryName string, servedCells []*entities.ServedCellInfo) error { + cellKeysToRemove := buildServedCellInfoKeysToRemove(inventoryName, servedCells) + err := w.sdl.Remove(cellKeysToRemove) if err != nil { @@ -197,7 +212,7 @@ func (w *rNibWriterInstance) UpdateGnbCells(nodebInfo *entities.NodebInfo, serve func buildServedNRCellKeysToRemove(inventoryName string, servedNrCellsToRemove []*entities.ServedNRCell) []string { - cellKeysToRemove := []string{} + var cellKeysToRemove []string for _, cell := range servedNrCellsToRemove { @@ -219,7 +234,7 @@ func buildServedNRCellKeysToRemove(inventoryName string, servedNrCellsToRemove [ func buildServedCellInfoKeysToRemove(inventoryName string, servedCellsToRemove []*entities.ServedCellInfo) []string { - cellKeysToRemove := []string{} + var cellKeysToRemove []string for _, cell := range servedCellsToRemove { @@ -464,6 +479,28 @@ func (w *rNibWriterInstance) RemoveEnb(nodebInfo *entities.NodebInfo) error { return nil } +func (w *rNibWriterInstance) UpdateEnb(nodebInfo *entities.NodebInfo, servedCells []*entities.ServedCellInfo) error { + + pairs, err := buildUpdateNodebInfoPairs(nodebInfo) + + if err != nil { + return err + } + + pairs, err = appendEnbCells(nodebInfo.RanName, servedCells, pairs) + + if err != nil { + return err + } + + err = w.sdl.SetAndPublish([]string{w.rnibWriterConfig.RanManipulationMessageChannel, fmt.Sprintf("%s_%s", nodebInfo.RanName, RanUpdatedEvent)}, pairs) + + if err != nil { + return common.NewInternalError(err) + } + + return nil +} /* Close the writer */ @@ -515,4 +552,4 @@ func appendGnbCells(inventoryName string, cells []*entities.ServedNRCell, pairs func isNotEmpty(nbIdentity *entities.NbIdentity) bool { return nbIdentity.GlobalNbId != nil && nbIdentity.GlobalNbId.PlmnId != "" && nbIdentity.GlobalNbId.NbId != "" -} +} \ No newline at end of file diff --git a/E2Manager/rNibWriter/rNibWriter_test.go b/E2Manager/rNibWriter/rNibWriter_test.go index 31e4745..069e509 100644 --- a/E2Manager/rNibWriter/rNibWriter_test.go +++ b/E2Manager/rNibWriter/rNibWriter_test.go @@ -68,7 +68,7 @@ func generateNodebInfo(inventoryName string, nodeType entities.Node_Type, plmnId func generateServedNrCells(cellIds ...string) []*entities.ServedNRCell { - servedNrCells := []*entities.ServedNRCell{} + var servedNrCells []*entities.ServedNRCell for i, v := range cellIds { servedNrCells = append(servedNrCells, &entities.ServedNRCell{ServedNrCellInformation: &entities.ServedNRCellInformation{ @@ -87,10 +87,29 @@ 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 TestRemoveServedNrCellsSuccess(t *testing.T) { w, sdlInstanceMock := initSdlInstanceMock(namespace) servedNrCellsToRemove := generateServedNrCells("whatever1", "whatever2") sdlInstanceMock.On("Remove", buildServedNRCellKeysToRemove(RanName, servedNrCellsToRemove)).Return(nil) + err := w.RemoveServedNrCells(RanName, servedNrCellsToRemove) assert.Nil(t, err) } @@ -99,6 +118,7 @@ func TestRemoveServedNrCellsFailure(t *testing.T) { w, sdlInstanceMock := initSdlInstanceMock(namespace) servedNrCellsToRemove := generateServedNrCells("whatever1", "whatever2") sdlInstanceMock.On("Remove", buildServedNRCellKeysToRemove(RanName, servedNrCellsToRemove)).Return(errors.New("expected error")) + err := w.RemoveServedNrCells(RanName, servedNrCellsToRemove) assert.IsType(t, &common.InternalError{}, err) } @@ -852,73 +872,89 @@ func TestSaveGeneralConfigurationDbError(t *testing.T) { assert.NotNil(t, rNibErr) } +func TestRemoveServedCellsSuccess(t *testing.T) { + w, sdlInstanceMock := initSdlInstanceMock(namespace) + servedCellsToRemove := generateServedCells("whatever1", "whatever2") + sdlInstanceMock.On("Remove", buildServedCellInfoKeysToRemove(RanName, servedCellsToRemove)).Return(nil) + err := w.RemoveServedCells(RanName, servedCellsToRemove) + assert.Nil(t, err) +} -//Integration tests -// -//func TestSaveEnbGnbInteg(t *testing.T){ -// for i := 0; i<10; i++{ -// Init("e2Manager", 1) -// w := GetRNibWriter() -// nb := entities.NodebInfo{} -// nb.NodeType = entities.Node_ENB -// nb.ConnectionStatus = entities.ConnectionStatus_CONNECTED -// nb.Ip = "localhost" -// nb.Port = uint32(5656 + i) -// enb := entities.Enb{} -// cell1 := &entities.ServedCellInfo{CellId:fmt.Sprintf("%02x",111 + i), Pci:uint32(11 + i)} -// cell2 := &entities.ServedCellInfo{CellId:fmt.Sprintf("%02x",222 + i), Pci:uint32(22 + i)} -// cell3 := &entities.ServedCellInfo{CellId:fmt.Sprintf("%02x",333 + i), Pci:uint32(33 + i)} -// enb.ServedCells = []*entities.ServedCellInfo{cell1, cell2, cell3} -// nb.Configuration = &entities.NodebInfo_Enb{Enb:&enb} -// plmnId := 0x02f828 -// nbId := 0x4a952a0a -// nbIdentity := &entities.NbIdentity{InventoryName: fmt.Sprintf("nameEnb%d" ,i), GlobalNbId:&entities.GlobalNbId{RicId:fmt.Sprintf("%02x", plmnId + i), NbId:fmt.Sprintf("%02x", nbId + i)}} -// err := w.SaveNodeb(nbIdentity, &nb) -// if err != nil{ -// t.Errorf("#rNibWriter_test.TestSaveEnbInteg - Failed to save NodeB entity. Error: %v", err) -// } -// -// nb1 := entities.NodebInfo{} -// nb1.NodeType = entities.Node_GNB -// nb1.ConnectionStatus = entities.ConnectionStatus_CONNECTED -// nb1.Ip = "localhost" -// nb1.Port = uint32(6565 + i) -// gnb := entities.Gnb{} -// gCell1 := &entities.ServedNRCell{ServedNrCellInformation:&entities.ServedNRCellInformation{CellId:fmt.Sprintf("%02x",1111 + i), NrPci:uint32(1 + i)}} -// gCell2 := &entities.ServedNRCell{ServedNrCellInformation:&entities.ServedNRCellInformation{CellId:fmt.Sprintf("%02x",2222 + i), NrPci:uint32(2 + i)}} -// gCell3 := &entities.ServedNRCell{ServedNrCellInformation:&entities.ServedNRCellInformation{CellId:fmt.Sprintf("%02x",3333 + i), NrPci:uint32(3 + i)}} -// gnb.ServedNrCells = []*entities.ServedNRCell{gCell1, gCell2, gCell3,} -// nb1.Configuration = &entities.NodebInfo_Gnb{Gnb:&gnb} -// nbIdentity = &entities.NbIdentity{InventoryName: fmt.Sprintf("nameGnb%d" ,i), GlobalNbId:&entities.GlobalNbId{RicId:fmt.Sprintf("%02x", plmnId - i), NbId:fmt.Sprintf("%02x", nbId - i)}} -// err = w.SaveNodeb(nbIdentity, &nb1) -// if err != nil{ -// t.Errorf("#rNibWriter_test.TestSaveEnbInteg - Failed to save NodeB entity. Error: %v", err) -// } -// } -//} -// -//func TestSaveNbRanNamesInteg(t *testing.T){ -// for i := 0; i<10; i++{ -// Init("e2Manager", 1) -// w := GetRNibWriter() -// nb := entities.NodebInfo{} -// nb.ConnectionStatus = entities.ConnectionStatus_CONNECTING -// nb.Ip = "localhost" -// nb.Port = uint32(5656 + i) -// nbIdentity := &entities.NbIdentity{InventoryName: fmt.Sprintf("nameOnly%d" ,i)} -// err := w.SaveNodeb(nbIdentity, &nb) -// if err != nil{ -// t.Errorf("#rNibWriter_test.TestSaveEnbInteg - Failed to save NodeB entity. Error: %v", err) -// } -// } -//} -// -//func TestSaveRanLoadInformationInteg(t *testing.T){ -// Init("e2Manager", 1) -// w := GetRNibWriter() -// ranLoadInformation := generateRanLoadInformation() -// err := w.SaveRanLoadInformation("ran_integ", ranLoadInformation) -// if err != nil{ -// t.Errorf("#rNibWriter_test.TestSaveRanLoadInformationInteg - Failed to save RanLoadInformation entity. Error: %v", err) -// } -//} +func TestUpdateEnbInvalidNodebInfoFailure(t *testing.T) { + w, sdlInstanceMock := initSdlInstanceMock(namespace) + servedCells := generateServedCells("test1", "test2") + nodebInfo := &entities.NodebInfo{} + sdlInstanceMock.AssertNotCalled(t, "SetAndPublish") + rNibErr := w.UpdateEnb(nodebInfo, servedCells) + assert.IsType(t, &common.ValidationError{}, rNibErr) +} + +func TestUpdateEnbInvalidCellFailure(t *testing.T) { + inventoryName := "name" + plmnId := "02f829" + nbId := "4a952a0a" + w, sdlInstanceMock := initSdlInstanceMock(namespace) + servedCells := []*entities.ServedCellInfo{{CellId: ""}} + nodebInfo := generateNodebInfo(inventoryName, entities.Node_ENB, plmnId, nbId) + nodebInfo.GetEnb().ServedCells = servedCells + sdlInstanceMock.AssertNotCalled(t, "SetAndPublish") + rNibErr := w.UpdateEnb(nodebInfo, servedCells) + assert.IsType(t, &common.ValidationError{}, rNibErr) +} + +/*func TestUpdateEnbSdlFailure(t *testing.T) { + inventoryName := "ranName" + plmnId := "02f829" + nbId := "4a952a0a" + w, sdlInstanceMock := initSdlInstanceMock(namespace) + servedCells := generateServedCells("test1", "test2") + nodebInfo := generateNodebInfo(inventoryName, entities.Node_GNB, plmnId, nbId) + nodebInfo.GetEnb().ServedCells = servedCells + setExpected := getUpdateEnbSetExpected(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" + plmnId := "02f829" + nbId := "4a952a0a" + w, sdlInstanceMock := initSdlInstanceMock(namespace) + servedCells := generateServedCells("test1", "test2") + nodebInfo := generateNodebInfo(inventoryName, entities.Node_GNB, plmnId, nbId) + nodebInfo.GetEnb().ServedCells = servedCells + setExpected := getUpdateEnbSetExpected(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{} { + + nodebInfoData, err := proto.Marshal(nodebInfo) + if err != nil { + t.Fatalf("#rNibWriter_test.getUpdateEnbSetExpected - 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 _, v := range servedCells { + + cellEntity := entities.ServedCellInfo{CellId: "some cell id", EutraMode: entities.Eutra_FDD, CsgId: "some csg id"} + cellData, err := proto.Marshal(&cellEntity) + + if err != nil { + t.Fatalf("#rNibWriter_test.getUpdateEnbSetExpected - Failed to marshal cell entity. Error: %s", err) + } + + nrCellIdKey, _ := common.ValidateAndBuildNrCellIdKey(v.GetCellId()) + cellNamePciKey, _ := common.ValidateAndBuildCellNamePciKey(nodebInfo.RanName, v.GetPci()) + setExpected = append(setExpected, nrCellIdKey, cellData, cellNamePciKey, cellData) + } + return setExpected +} \ No newline at end of file diff --git a/E2Manager/services/rnib_data_service.go b/E2Manager/services/rnib_data_service.go index 2ab34d2..e668da6 100644 --- a/E2Manager/services/rnib_data_service.go +++ b/E2Manager/services/rnib_data_service.go @@ -53,6 +53,8 @@ type RNibDataService interface { UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, event string) error SaveGeneralConfiguration(config *entities.GeneralConfiguration) error RemoveEnb(nodebInfo *entities.NodebInfo) error + RemoveServedCells(inventoryName string, servedCells []*entities.ServedCellInfo) error + UpdateEnb(nodebInfo *entities.NodebInfo, servedCells []*entities.ServedCellInfo) error } type rNibDataService struct { @@ -302,6 +304,24 @@ func (w *rNibDataService) SaveGeneralConfiguration(config *entities.GeneralConfi return err } +func (w *rNibDataService) RemoveServedCells(inventoryName string, servedCells []*entities.ServedCellInfo) error { + err := w.retry("RemoveServedCells", func() (err error) { + err = w.rnibWriter.RemoveServedCells(inventoryName, servedCells) + return + }) + + return err +} + +func (w *rNibDataService) UpdateEnb(nodebInfo *entities.NodebInfo, servedCells []*entities.ServedCellInfo) error { + err := w.retry("UpdateEnb", func() (err error) { + err = w.rnibWriter.UpdateEnb(nodebInfo, servedCells) + return + }) + + return err +} + func (w *rNibDataService) PingRnib() bool { err := w.retry("GetListNodebIds", func() (err error) { _, err = w.rnibReader.GetListNodebIds()