Add ANR xApp controller 39/139/2
authorLott, Christopher (cl778h) <cl778h@att.com>
Fri, 10 May 2019 19:38:32 +0000 (15:38 -0400)
committerLott, Christopher (cl778h) <cl778h@att.com>
Fri, 10 May 2019 19:45:18 +0000 (15:45 -0400)
Proxy requests for the automatic neighbor relation
table over to the ANR xApp's REST API.

Change-Id: I6f602b023884b4014ad8bb757eb54547470d0019
Issue-Id: RICPLT-1251
Signed-off-by: Lott, Christopher (cl778h) <cl778h@att.com>
docs/release-notes.rst
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/A1MediatorMockConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AnrXappConfiguration.java [new file with mode: 0644]
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AnrXappMockConfiguration.java [new file with mode: 0644]
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerMockConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AnrXappController.java [new file with mode: 0644]
webapp-backend/src/main/resources/application.properties

index c496010..8e42eac 100644 (file)
@@ -26,6 +26,7 @@ Version 1.0.2, 10 May 2019
 * Add E2 response message with timestamp and status code
 * Fetch xAPP instance status information from xAPP Manager and display in dashboard
 * Allow the user to initiate an E2 (X2) connection between RIC and gNB/eNB
+* Add ANR xApp backend with mock implementation
 
 Version 1.0.1, 6 May 2019
 -------------------------
index 69e5d4b..485597a 100644 (file)
@@ -36,7 +36,7 @@ import org.springframework.context.annotation.Profile;
 import org.springframework.http.HttpStatus;
 
 /**
- * Creates a mock implementation of the E2 manager client API.
+ * Creates a mock implementation of the A1 mediator client API.
  */
 @Profile("mock")
 @Configuration
diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AnrXappConfiguration.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AnrXappConfiguration.java
new file mode 100644 (file)
index 0000000..3a2e810
--- /dev/null
@@ -0,0 +1,72 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2019 AT&T Intellectual Property and 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.
+ * ========================LICENSE_END===================================
+ */
+package org.oransc.ric.portal.dashboard.config;
+
+import java.lang.invoke.MethodHandles;
+
+import org.oransc.ric.anrxapp.client.api.HealthApi;
+import org.oransc.ric.anrxapp.client.api.NcrtApi;
+import org.oransc.ric.anrxapp.client.invoker.ApiClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.util.Assert;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * Creates instances of the ANR xApp client APIs.
+ */
+@Configuration
+@Profile("!mock")
+public class AnrXappConfiguration {
+
+       private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+       // Populated by the autowired constructor
+       private final String anrXappBasepath;
+
+       @Autowired
+       public AnrXappConfiguration(@Value("${anrxapp.basepath}") final String anrXappBasepath) {
+               Assert.notNull(anrXappBasepath, "base path must not be null");
+               logger.info("Configuring ANR client at base path {}", anrXappBasepath);
+               this.anrXappBasepath = anrXappBasepath;
+       }
+
+       private ApiClient apiClient() {
+               ApiClient apiClient = new ApiClient(new RestTemplate());
+               apiClient.setBasePath(anrXappBasepath);
+               return apiClient;
+       }
+
+       @Bean
+       public HealthApi anrHealthApi() {
+               return new HealthApi(apiClient());
+       }
+
+       @Bean
+       public NcrtApi anrNcrtApi() {
+               return new NcrtApi(apiClient());
+       }
+
+}
diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AnrXappMockConfiguration.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AnrXappMockConfiguration.java
new file mode 100644 (file)
index 0000000..32b507f
--- /dev/null
@@ -0,0 +1,109 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2019 AT&T Intellectual Property and 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.
+ * ========================LICENSE_END===================================
+ */
+package org.oransc.ric.portal.dashboard.config;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.lang.invoke.MethodHandles;
+
+import org.oransc.ric.anrxapp.client.api.HealthApi;
+import org.oransc.ric.anrxapp.client.api.NcrtApi;
+import org.oransc.ric.anrxapp.client.invoker.ApiClient;
+import org.oransc.ric.anrxapp.client.model.NeighborCellRelation;
+import org.oransc.ric.anrxapp.client.model.NeighborCellRelationDelTable;
+import org.oransc.ric.anrxapp.client.model.NeighborCellRelationModTable;
+import org.oransc.ric.anrxapp.client.model.NeighborCellRelationTable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.http.HttpStatus;
+
+/**
+ * Creates a mock implementation of the ANR xApp client APIs.
+ */
+@Profile("mock")
+@Configuration
+public class AnrXappMockConfiguration {
+
+       private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+       public AnrXappMockConfiguration() {
+               logger.info("Configuring mock ANR xApp client");
+       }
+
+       private ApiClient apiClient() {
+               ApiClient mockClient = mock(ApiClient.class);
+               when(mockClient.getStatusCode()).thenReturn(HttpStatus.OK);
+               return mockClient;
+       }
+
+       @Bean
+       public HealthApi anrHealthMockApi() {
+               ApiClient mockClient = mock(ApiClient.class);
+               when(mockClient.getStatusCode()).thenReturn(HttpStatus.OK);
+               HealthApi mockApi = mock(HealthApi.class);
+               when(mockApi.getApiClient()).thenReturn(mockClient);
+               doAnswer(i -> {
+                       return null;
+               }).when(mockApi).getHealthAlive();
+               doAnswer(i -> {
+                       return null;
+               }).when(mockApi).getHealthReady();
+               return mockApi;
+       }
+
+       @Bean
+       public NcrtApi ncrtPapi() {
+               ApiClient apiClient = apiClient();
+               NcrtApi mockApi = mock(NcrtApi.class);
+               when(mockApi.getApiClient()).thenReturn(apiClient);
+
+               NeighborCellRelation a = new NeighborCellRelation().cellIdentifierNrcgi("A12345")
+                               .neighborCellIdentifierNrpci("A123456").neighborCellIdentifierNrcgi("A12347").flagNoHo(true)
+                               .flagNoXn(true).flagNoRemove(true);
+               NeighborCellRelation e = new NeighborCellRelation().cellIdentifierNrcgi("E12345")
+                               .neighborCellIdentifierNrpci("E123456").neighborCellIdentifierNrcgi("E12347").flagNoHo(true)
+                               .flagNoXn(true).flagNoRemove(true);
+               NeighborCellRelationTable ncrt = new NeighborCellRelationTable().addNcrtRelationsItem(a)
+                               .addNcrtRelationsItem(e);
+
+               when(mockApi.getNcrtInfo(any(String.class), any(String.class), any(Integer.class))).thenReturn(ncrt);
+               when(mockApi.getCellNcrtInfo(any(String.class), any(String.class), any(Integer.class), any(String.class),
+                               any(String.class))).thenReturn(ncrt);
+
+               doAnswer(i -> {
+                       return null;
+               }).when(mockApi).deleteNcrt(any(String.class), any(NeighborCellRelationDelTable.class), any(String.class),
+                               any(Integer.class), any(String.class), any(String.class));
+
+               doAnswer(i -> {
+                       return null;
+               }).when(mockApi).modifyNCRT(any(String.class), any(NeighborCellRelationModTable.class), any(String.class),
+                               any(Integer.class), any(String.class), any(String.class));
+
+               return mockApi;
+       }
+
+}
index 9416c67..00cd939 100644 (file)
@@ -54,22 +54,25 @@ public class XappManagerConfiguration {
                this.xappMgrBasepath = xappMgrBasepath;
        }
 
+       private ApiClient apiClient() {
+               ApiClient apiClient = new ApiClient(new RestTemplate());
+               apiClient.setBasePath(xappMgrBasepath);
+               return apiClient;
+       }
+
        /**
         * @return A HealthApi with an ApiClient configured from properties
         */
        @Bean
        public HealthApi xappHealthApi() {
-               ApiClient apiClient = new ApiClient(new RestTemplate());
-               apiClient.setBasePath(xappMgrBasepath);
-               return new HealthApi(apiClient);
+               return new HealthApi(apiClient());
        }
+
        /**
         * @return An XappApi with an ApiClient configured from properties
         */
        @Bean
        public XappApi xappMgrApi() {
-               ApiClient apiClient = new ApiClient(new RestTemplate());
-               apiClient.setBasePath(xappMgrBasepath);
-               return new XappApi(apiClient);
+               return new XappApi(apiClient());
        }
 }
index 59f5095..d4a228e 100644 (file)
@@ -104,7 +104,6 @@ public class XappManagerMockConfiguration {
 
                when(mockApi.getAllXapps()).thenReturn(allXapps);
 
-
                Xapp xappByName = new Xapp().name("name").status(StatusEnum.UNKNOWN).version("v1");
                when(mockApi.getXappByName(any(String.class))).thenReturn(xappByName);
 
diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AnrXappController.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AnrXappController.java
new file mode 100644 (file)
index 0000000..3654356
--- /dev/null
@@ -0,0 +1,134 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2019 AT&T Intellectual Property and 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.
+ * ========================LICENSE_END===================================
+ */
+package org.oransc.ric.portal.dashboard.controller;
+
+import java.lang.invoke.MethodHandles;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.oransc.ric.anrxapp.client.api.HealthApi;
+import org.oransc.ric.anrxapp.client.api.NcrtApi;
+import org.oransc.ric.anrxapp.client.model.NeighborCellRelationDelTable;
+import org.oransc.ric.anrxapp.client.model.NeighborCellRelationModTable;
+import org.oransc.ric.anrxapp.client.model.NeighborCellRelationTable;
+import org.oransc.ric.portal.dashboard.DashboardConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * Provides methods to contact the ANR xApp which manages a Neighbor Cell
+ * Relation Table (NCRT).
+ */
+@Configuration
+@RestController
+@RequestMapping(value = DashboardConstants.ENDPOINT_PREFIX + "/ncrt", produces = MediaType.APPLICATION_JSON_VALUE)
+public class AnrXappController {
+
+       private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+       private static final String CELL_ID = "cellIdentifier";
+       private static final String GGNBID = "ggnbId";
+       private static final String START_INDEX = "startIndex";
+       private static final String LIMIT = "limit";
+       private static final String NRPCI = "neighborCellIdentifierNrpci";
+       private static final String NRCGI = "neighborCellIdentifierNrcgi";
+
+       // Populated by the autowired constructor
+       private final HealthApi healthApi;
+       private final NcrtApi ncrtApi;
+
+       @Autowired
+       public AnrXappController(final HealthApi healthApi, final NcrtApi ncrtApi) {
+               Assert.notNull(healthApi, "API must not be null");
+               Assert.notNull(ncrtApi, "API must not be null");
+               this.healthApi = healthApi;
+               this.ncrtApi = ncrtApi;
+       }
+
+       @ApiOperation(value = "Performs a liveness probe on the ANR xApp, result expressed as the response code.")
+       @RequestMapping(value = "/health/alive", method = RequestMethod.GET)
+       public void getHealthAlive(HttpServletResponse response) {
+               logger.debug("getHealthAlive");
+               healthApi.getHealthAlive();
+               response.setStatus(healthApi.getApiClient().getStatusCode().value());
+       }
+
+       @ApiOperation(value = "Performs a readiness probe on the ANR xApp, result expressed as the response code.")
+       @RequestMapping(value = "/health/ready", method = RequestMethod.GET)
+       public void getHealthReady(HttpServletResponse response) {
+               logger.debug("getHealthReady");
+               healthApi.getHealthReady();
+               response.setStatus(healthApi.getApiClient().getStatusCode().value());
+       }
+
+       @ApiOperation(value = "Query NCRT of all cells, all or one gNB(s)", response = NeighborCellRelationTable.class)
+       @RequestMapping(value = "/cell", method = RequestMethod.GET)
+       public NeighborCellRelationTable queryNcrtAllCells( //
+                       @RequestParam(name = GGNBID, required = false) String ggnbId, //
+                       @RequestParam(name = START_INDEX, required = false) String startIndex, //
+                       @RequestParam(name = LIMIT, required = false) Integer limit) {
+               logger.debug("queryNcrtAllCells: ggnbid {}, startIndex {} limit {}", ggnbId, startIndex, limit);
+               return ncrtApi.getNcrtInfo(ggnbId, startIndex, limit);
+       }
+
+       @ApiOperation(value = "Query NCRT of a single serving cell", response = NeighborCellRelationTable.class)
+       @RequestMapping(value = "/cell/" + CELL_ID + "/{" + CELL_ID + "}", method = RequestMethod.GET)
+       public NeighborCellRelationTable queryNcrtServingCell(@PathVariable(CELL_ID) String cellIdentifier, //
+                       @RequestParam(name = START_INDEX, required = false) String startIndex, //
+                       @RequestParam(name = LIMIT, required = false) Integer limit,
+                       @RequestParam(name = NRPCI, required = false) String nrpci,
+                       @RequestParam(name = NRCGI, required = false) String nrcgi) {
+               logger.debug("queryNcrtAllCells: cellIdentifier {}, startIndex {} limit {} nrpci {} nrcgi {}", cellIdentifier,
+                               startIndex, limit, nrpci, nrcgi);
+               return ncrtApi.getCellNcrtInfo(cellIdentifier, startIndex, limit, nrpci, nrcgi);
+       }
+
+       @ApiOperation(value = "Modify neighbor cell relation based on Source Cell NR CGI and Target Cell NR PCI / NR CGI")
+       @RequestMapping(value = "/cell/" + CELL_ID + "/{" + CELL_ID + "}", method = RequestMethod.PUT)
+       public void modifyNcrt(@PathVariable(CELL_ID) String cellIdentifier, //
+                       @RequestBody NeighborCellRelationModTable ncrtModTable, //
+                       HttpServletResponse response) {
+               logger.debug("modifyNcrt: cellIdentifier {} modTable {}", cellIdentifier, ncrtModTable);
+               ncrtApi.modifyNCRT(cellIdentifier, ncrtModTable, null, null, null, null);
+               response.setStatus(healthApi.getApiClient().getStatusCode().value());
+       }
+
+       @ApiOperation(value = "Delete neighbor cell relation based on Source Cell NR CGI and Target Cell NR PCI / NR CGI")
+       @RequestMapping(value = "/cell/" + CELL_ID + "/{" + CELL_ID + "}", method = RequestMethod.DELETE)
+       public void modifyNcrt(@PathVariable(CELL_ID) String cellIdentifier, //
+                       @RequestBody NeighborCellRelationDelTable ncrtDelTable, //
+                       HttpServletResponse response) {
+               logger.debug("modifyNcrt: cellIdentifier {} delTable {}", cellIdentifier, ncrtDelTable);
+               ncrtApi.deleteNcrt(cellIdentifier, ncrtDelTable, null, null, null, null);
+               response.setStatus(healthApi.getApiClient().getStatusCode().value());
+       }
+}
index c4bd7f5..8c48e96 100644 (file)
@@ -30,6 +30,9 @@ a1med.delaypath   = /a1ric/delay
 a1med.loadpath    = /a1ric/load
 a1med.metricspath = /a1ric/metrics
 
+# ANR xApp
+anrxapp.basepath = http://localhost:23456
+
 # E2 Manager
 e2mgr.basepath = http://localhost:30098