* 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
-------------------------
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
--- /dev/null
+/*-
+ * ========================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());
+ }
+
+}
--- /dev/null
+/*-
+ * ========================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;
+ }
+
+}
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());
}
}
when(mockApi.getAllXapps()).thenReturn(allXapps);
-
Xapp xappByName = new Xapp().name("name").status(StatusEnum.UNKNOWN).version("v1");
when(mockApi.getXappByName(any(String.class))).thenReturn(xappByName);
--- /dev/null
+/*-
+ * ========================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());
+ }
+}
a1med.loadpath = /a1ric/load
a1med.metricspath = /a1ric/metrics
+# ANR xApp
+anrxapp.basepath = http://localhost:23456
+
# E2 Manager
e2mgr.basepath = http://localhost:30098