[RIC-432] - Support Update eNB REST API. 55/4355/1
authorIrina <ib565x@intl.att.com>
Wed, 8 Jul 2020 18:11:04 +0000 (18:11 +0000)
committerIrina <ib565x@intl.att.com>
Wed, 8 Jul 2020 18:11:25 +0000 (18:11 +0000)
Change-Id: I1bca32a371dd001e6edebe21728d9c68f4c9ea80
Signed-off-by: Irina <ib565x@intl.att.com>
22 files changed:
E2Manager/app/main.go
E2Manager/container-tag.yaml
E2Manager/controllers/e2t_controller_test.go
E2Manager/controllers/nodeb_controller.go
E2Manager/controllers/nodeb_controller_test.go
E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler.go [new file with mode: 0644]
E2Manager/handlers/httpmsghandlers/update_nodeb_request_handler_test.go [new file with mode: 0644]
E2Manager/httpserver/http_server.go
E2Manager/httpserver/http_server_test.go
E2Manager/managers/i_update_nodeb_manager.go [new file with mode: 0644]
E2Manager/managers/update_enb_manager.go [new file with mode: 0644]
E2Manager/managers/update_enb_manager_test.go [new file with mode: 0644]
E2Manager/mocks/nodeb_controller_mock.go
E2Manager/mocks/rnibWriterMock.go
E2Manager/models/nodeb_response.go [new file with mode: 0644]
E2Manager/models/update_enb_request.go [new file with mode: 0644]
E2Manager/models/update_nodeb_request.go [new file with mode: 0644]
E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go
E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go
E2Manager/rNibWriter/rNibWriter.go
E2Manager/rNibWriter/rNibWriter_test.go
E2Manager/services/rnib_data_service.go

index 0ad6412..dd30907 100644 (file)
@@ -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)
index a83a80a..9309859 100644 (file)
@@ -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
index 915e78e..5db1832 100644 (file)
@@ -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
 }
index 1d9f50c..3ff453e 100644 (file)
@@ -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))
 
index fc59673..7ee44d7 100644 (file)
@@ -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 (file)
index 0000000..6afe87a
--- /dev/null
@@ -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 (file)
index 0000000..ff4b9f8
--- /dev/null
@@ -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
index 1d29dcd..157f5bd 100644 (file)
@@ -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()
index 6378f8c..fbaecbe 100644 (file)
@@ -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 (file)
index 0000000..0828ce1
--- /dev/null
@@ -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 (file)
index 0000000..6c9ae14
--- /dev/null
@@ -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 (file)
index 0000000..c107157
--- /dev/null
@@ -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
index 2f1a15d..2467666 100644 (file)
@@ -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)
index 292e455..f84d845 100644 (file)
@@ -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 (file)
index 0000000..3acf695
--- /dev/null
@@ -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 (file)
index 0000000..1d6a63a
--- /dev/null
@@ -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 (file)
index 0000000..ad351bb
--- /dev/null
@@ -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
index b5e0d1d..2dba750 100644 (file)
@@ -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),
        }
index f47fae2..5ce3b9c 100644 (file)
@@ -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) {
index c73cc37..d874938 100644 (file)
@@ -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
index 31e4745..069e509 100644 (file)
@@ -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
index 2ab34d2..e668da6 100644 (file)
@@ -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()