From: Lott, Christopher (cl778h) Date: Fri, 10 May 2019 19:38:32 +0000 (-0400) Subject: Add ANR xApp controller X-Git-Tag: R2~111 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;ds=sidebyside;h=c535d05d9cf44ecee863387b8536211937f9a039;p=portal%2Fric-dashboard.git Add ANR xApp controller 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) --- diff --git a/docs/release-notes.rst b/docs/release-notes.rst index c4960108..8e42eac1 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -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 ------------------------- diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/A1MediatorMockConfiguration.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/A1MediatorMockConfiguration.java index 69e5d4bf..485597a8 100644 --- a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/A1MediatorMockConfiguration.java +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/A1MediatorMockConfiguration.java @@ -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 index 00000000..3a2e810b --- /dev/null +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AnrXappConfiguration.java @@ -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 index 00000000..32b507fa --- /dev/null +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AnrXappMockConfiguration.java @@ -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; + } + +} diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerConfiguration.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerConfiguration.java index 9416c67e..00cd9390 100644 --- a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerConfiguration.java +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerConfiguration.java @@ -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()); } } diff --git a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerMockConfiguration.java b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerMockConfiguration.java index 59f5095a..d4a228e4 100644 --- a/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerMockConfiguration.java +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerMockConfiguration.java @@ -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 index 00000000..36543568 --- /dev/null +++ b/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AnrXappController.java @@ -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()); + } +} diff --git a/webapp-backend/src/main/resources/application.properties b/webapp-backend/src/main/resources/application.properties index c4bd7f5b..8c48e96a 100644 --- a/webapp-backend/src/main/resources/application.properties +++ b/webapp-backend/src/main/resources/application.properties @@ -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