diff options
Diffstat (limited to 'ms')
8 files changed, 1627 insertions, 0 deletions
diff --git a/ms/generic-resource-api/pom.xml b/ms/generic-resource-api/pom.xml index cc6471d..6a34388 100644 --- a/ms/generic-resource-api/pom.xml +++ b/ms/generic-resource-api/pom.xml @@ -169,6 +169,13 @@ <artifactId>derby</artifactId> <scope>test</scope> </dependency> + <!-- Necessary to run tests with coverage in IntelliJ --> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-launcher</artifactId> + <version>1.6.2</version> + <scope>test</scope> + </dependency> </dependencies> <build> diff --git a/ms/generic-resource-api/src/main/java/org/onap/sdnc/apps/ms/gra/controllers/ConfigApiController.java b/ms/generic-resource-api/src/main/java/org/onap/sdnc/apps/ms/gra/controllers/ConfigApiController.java index 5695cfc..26b6dcf 100644 --- a/ms/generic-resource-api/src/main/java/org/onap/sdnc/apps/ms/gra/controllers/ConfigApiController.java +++ b/ms/generic-resource-api/src/main/java/org/onap/sdnc/apps/ms/gra/controllers/ConfigApiController.java @@ -44,11 +44,14 @@ import org.springframework.stereotype.Controller; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; +import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; +import java.util.stream.Stream; @Controller @ComponentScan(basePackages = {"org.onap.sdnc.apps.ms.gra.*"}) @@ -797,4 +800,706 @@ public class ConfigApiController implements ConfigApi { } } + /** + * Deletes VNF data from the Config table specified Service Instance. + * <p> + * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/ + * @param serviceInstanceId the Service Instance ID to perform the delete on + * @param vnfId the VNF ID of the VNF to delete + * @return HttpStatus.NO_CONTENT (204) on successful delete + * <p> + * HttpStatus.BAD_REQUEST (400) if unmarshalling Service Data from + * the database fails, there is no VNF data for {@code vnfId}, or + * writing Service Data back to the database fails. + * <p> + * HttpStatus.NOT_FOUND (404) if {@code serviceInstanceId} does + * not exist. + */ + @Override + public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdDelete(String serviceInstanceId, String vnfId) throws RestException { + log.info("DELETE | VNF Data for ({})", vnfId); + + /* The logic may need to be moved inside of this check or this check + * may need to be removed. + */ + if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) { + log.info("Something with header."); + } else { + log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated"); + } + + List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId); + ConfigServices data; + if((services == null) || (services.isEmpty())) { + log.info("Could not find data for ({}).", serviceInstanceId); + // Or throw the data not found error? + throw new RestProtocolException("data-missing", "Service Instance ID not found.", HttpStatus.NOT_FOUND.value()); + } else { + data = services.get(0); + } + + GenericResourceApiServicedataServiceData svcData; + try { + svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class); + } catch(JsonProcessingException e) { + // Or throw the data not found error? + log.error("Could not map service data for ({})", serviceInstanceId); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + if(svcData == null) { + // Or throw the data not found error? + log.info("Could not find Service Data for ({}).", serviceInstanceId); + throw new RestProtocolException("data-missing", "Service data not found.", HttpStatus.NOT_FOUND.value()); + } + + GenericResourceApiServicedataServicedataVnfs vnfs = svcData.getVnfs(); + if(vnfs == null) { + // Or throw the data not found error? + log.info("VNF List not found for ({}).", serviceInstanceId); + throw new RestProtocolException("data-missing", "VNFs not found.", HttpStatus.NOT_FOUND.value()); + } + + Stream<GenericResourceApiServicedataServicedataVnfsVnf> vnfStream = svcData.getVnfs().getVnf().stream(); + if(vnfStream.noneMatch(targetVnf -> targetVnf.getVnfId().equals(vnfId))) { + // Data was not found + log.error("Did not find VNF ({}) in data.", vnfId); + throw new RestProtocolException("data-missing", "VNF ID not found.", HttpStatus.NOT_FOUND.value()); + } + // Recreate the stream per Sonar? + vnfStream = svcData.getVnfs().getVnf().stream(); + svcData.getVnfs().setVnf(vnfStream.filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId)).collect(Collectors.toList())); + + // Map and save the new data + try { + data.setSvcData(objectMapper.writeValueAsString(svcData)); + configServicesRepository.save(data); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } catch(JsonProcessingException e) { + log.error("Error mapping object to JSON", e); + // Should probably be a 500 INTERNAL_SERVICE_ERROR + throw new RestProtocolException("internal-service-error", "Failed to save data.", HttpStatus.BAD_REQUEST.value()); + } + } + + /** + * Extracts VNF data from the Config table specified Service Instance. + * <p> + * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/ + * @param serviceInstanceId the Service Instance ID to lookup data for + * @param vnfId the VNF ID of the VNF to return + * @return HttpStatus.OK (200) if the data is found. + * @throws RestException if the data does not exist. + */ + @Override + public ResponseEntity<GenericResourceApiServicedataServicedataVnfsVnf> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdGet(String serviceInstanceId, String vnfId) throws RestException { + log.info("GET | VNF Data for ({})", vnfId); + if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) { + if(getAcceptHeader().get().contains("application/json")) { + } + } else { + log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated"); + } + List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId); + if((services == null) || (services.isEmpty())) { + throw new RestProtocolException("data-missing", "No service entry found", HttpStatus.NOT_FOUND.value()); + } + + Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnf = getVnfObject(services.get(0), vnfId); + if(vnf.isPresent()) { + return new ResponseEntity<>(vnf.get(), HttpStatus.OK); + } else { + log.info("No information found for {}", vnfId); + throw new RestApplicationException("data-missing", "Request could not be completed because the relevant data model content does not exist", HttpStatus.NOT_FOUND.value()); + } + } + + /** + * Creates or updates VNF data in the Config table for a specified Service + * Instance. If it is a new Service Instance or a new VNF, creates all + * necessary parent data containers, then performs the updates. + * <p> + * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/ + * @param serviceInstanceId the Service Instance ID to perform the delete on + * @param vnfId the VNF ID of the VNF to delete + * @param genericResourceApiServicedataServicedataVnfsVnfBodyParam the playload + * @return HttpStatus.CREATED (201) on successful create + * <p> + * HttpStatus.NO_CONTENT (204) on successful update + * <p> + * HttpStatus.BAD_REQUEST (400) if {@code vnfId} does not match + * what is specified in the + * {@code genericResourceApiServicedataServicedataVnfsVnfBodyParam} + * , or if updating the database fails. + * @throws RestException + */ + @Override + public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdPut(String serviceInstanceId, String vnfId, GenericResourceApiServicedataServicedataVnfsVnf genericResourceApiServicedataServicedataVnfsVnfBodyParam) throws RestException { + log.info("PUT | VNF Data for ({})", vnfId); + if(!vnfId.equals(genericResourceApiServicedataServicedataVnfsVnfBodyParam.getVnfId())) { + throw new RestProtocolException("bad-attribute", "vnf-id mismatch", HttpStatus.BAD_REQUEST.value()); + } + if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) { + log.info("Something with header"); + } else { + log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated"); + } + + List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId); + ConfigServices data; + if((services == null) || (services.isEmpty())) { + log.info("Could not find data for ({}). Creating new Service Object.", serviceInstanceId); + data = new ConfigServices(); + data.setSvcInstanceId(serviceInstanceId); + } else { + data = services.get(0); + } + + GenericResourceApiServicedataServiceData svcData = null; + try { + svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class); + } catch(JsonProcessingException e) { + log.error("Could not map service data for ({})", serviceInstanceId); + } + if(svcData == null) { + log.info("Could not find Service Data for ({}). Creating new Service Data Container", serviceInstanceId); + svcData = new GenericResourceApiServicedataServiceData(); + } + if(svcData.getVnfs() == null) { + log.info("VNF List not found for ({}). Creating new VNF List Container.", serviceInstanceId); + svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs()); + svcData.getVnfs().setVnf(new ArrayList<>()); + } + + GenericResourceApiServicedataServicedataVnfs vnflist = new GenericResourceApiServicedataServicedataVnfs(); + HttpStatus responseStatus = HttpStatus.NO_CONTENT; + if(svcData.getVnfs().getVnf().isEmpty()) { + log.info("Creating VNF data for ({})", vnfId); + vnflist.addVnfItem(genericResourceApiServicedataServicedataVnfsVnfBodyParam); + responseStatus = HttpStatus.CREATED; + } else { + log.info("Updating VNF data for ({})", vnfId); + // Filter out all of the other vnf objects into a new VNF List + // Replace if a delete method exists + svcData.getVnfs() + .getVnf() + .stream() + .filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId)) + .forEach(vnflist::addVnfItem); + vnflist.addVnfItem(genericResourceApiServicedataServicedataVnfsVnfBodyParam); + } + svcData.setVnfs(vnflist); + // Map and save the new data + try { + data.setSvcData(objectMapper.writeValueAsString(svcData)); + configServicesRepository.save(data); + return new ResponseEntity<>(responseStatus); + } catch(JsonProcessingException e) { + log.error("Error mapping object to JSON", e); + // Should probably be a 500 INTERNAL_SERVICE_ERROR + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + /** + * Extracts VNF Topology data from the Config table specified Service + * Instance and VNF ID. + * <p> + * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/vnf-data/vnf-topology/ + * @param serviceInstanceId the Service Instance ID to lookup data for + * @param vnfId the VNF ID of the VNF to extract topology data from. + * @return HttpStatus.OK (200) if the data is found. + * @throws RestException if the data does not exist. + */ + @Override + public ResponseEntity<GenericResourceApiVnftopologyVnfTopology> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyGet(String serviceInstanceId, String vnfId) throws RestException { + log.info("GET | VNF Topology for ({})", vnfId); + if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) { + if (getAcceptHeader().get().contains("application/json")) { + + } + } else { + log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated"); + } + List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId); + if((services == null) || (services.isEmpty())) { + throw new RestProtocolException("data-missing", "No service entry found", HttpStatus.NOT_FOUND.value()); + } + + Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnf = getVnfObject(services.get(0), vnfId); + // Drill down to find the data + if(vnf.isPresent() + && vnf.get().getVnfData() != null + && vnf.get().getVnfData().getVnfTopology() != null) { + return new ResponseEntity<>(vnf.get().getVnfData().getVnfTopology(), HttpStatus.OK); + } else { + log.info("No information found for {}", vnfId); + throw new RestApplicationException("data-missing", "Request could not be completed because the relevant data model content does not exist", HttpStatus.NOT_FOUND.value()); + } + } + + /** + * Creates or updates VNF Level Operation Status data in the Config table + * for a specified Service Instance. If it is a new Service Instance or a + * new VNF, creates all necessary parent data containers, then performs the + * updates. + * <p> + * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/vnf-data/vnf-level-oper-status/ + * @param serviceInstanceId the Service Instance ID to perform the delete on + * @param vnfId the VNF ID of the VNF to delete + * @param genericResourceApiOperStatusDataBodyParam the payload + * @return HttpStatus.CREATED (201) on successful create. + * <p> + * HttpStatus.NO_CONTENT (204) on successful update. + * <p> + * HttpStatus.BAD_REQUEST (400) if updating the database fails. + * @throws RestException + */ + @Override + public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfLevelOperStatusPut(String serviceInstanceId, String vnfId, GenericResourceApiOperStatusData genericResourceApiOperStatusDataBodyParam) throws RestException { + log.info("PUT | VNF Level Oper Status ({})", vnfId); + if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) { + } else { + log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated"); + } + + List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId); + ConfigServices data; + if((services == null) || (services.isEmpty())) { + log.info("Could not find data for ({}). Creating new Service Object.", serviceInstanceId); + data = new ConfigServices(); + data.setSvcInstanceId(serviceInstanceId); + } else { + data = services.get(0); + } + + GenericResourceApiServicedataServiceData svcData = null; + try { + svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class); + } catch(JsonProcessingException e) { + log.error("Could not map service data for ({})", serviceInstanceId); + } + if(svcData == null) { + log.info("Could not find Service Data for ({}). Creating new Service Data Container", serviceInstanceId); + svcData = new GenericResourceApiServicedataServiceData(); + } + if(svcData.getVnfs() == null) { + log.info("VNF List not found for ({}). Creating new VNF List Container.", serviceInstanceId); + svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs()); + svcData.getVnfs().setVnf(new ArrayList<>()); + } + + GenericResourceApiServicedataServicedataVnfs vnflist = new GenericResourceApiServicedataServicedataVnfs(); + HttpStatus responseStatus = HttpStatus.NO_CONTENT; + if(svcData.getVnfs().getVnf().isEmpty()) { + log.info("Creating VNF data for ({})", vnfId); + GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf(); + vnf.setVnfId(vnfId); + vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData()); + vnf.getVnfData().setVnfLevelOperStatus(genericResourceApiOperStatusDataBodyParam); + vnflist.addVnfItem(vnf); + responseStatus = HttpStatus.CREATED; + } else { + log.info("Updating VNF data for ({})", vnfId); + // Filter out all of the other vnf objects into a new VNF List + // Replace if a delete method exists + svcData.getVnfs() + .getVnf() + .stream() + .filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId)) + .forEach(vnflist::addVnfItem); + GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf(); + // If the vnf exists, set it up with new data + Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnfOptional = getVnfObject(data, vnfId); + if(vnfOptional.isPresent()) { + vnf = vnfOptional.get(); + } + if(vnf.getVnfData() == null) { + vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData()); + responseStatus = HttpStatus.CREATED; + } + + vnf.getVnfData().setVnfLevelOperStatus(genericResourceApiOperStatusDataBodyParam); + vnflist.addVnfItem(vnf); + } + + svcData.setVnfs(vnflist); + // Map and save the new data + try { + data.setSvcData(objectMapper.writeValueAsString(svcData)); + configServicesRepository.save(data); + return new ResponseEntity<>(responseStatus); + } catch(JsonProcessingException e) { + log.error("Error mapping object to JSON", e); + // Should probably be a 500 INTERNAL_SERVICE_ERROR + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + /** + * Creates or updates VNF Onap Model Information data in the Config table + * for a specified Service Instance. If it is a new Service Instance or a + * new VNF, creates all necessary parent data containers, then performs the + * updates. + * <p> + * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/vnf-data/vnf-topology/onap-model-information/ + * @param serviceInstanceId the Service Instance ID to perform the delete on + * @param vnfId the VNF ID of the VNF to delete + * @param genericResourceApiOnapmodelinformationOnapModelInformationBodyParam the payload + * @return HttpStatus.CREATED (201) on successful create. + * <p> + * HttpStatus.NO_CONTENT (204) on successful update. + * <p> + * HttpStatus.BAD_REQUEST (400) if updating the database fails. + * @throws RestException + */ + @Override + public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyOnapModelInformationPut(String serviceInstanceId, String vnfId, GenericResourceApiOnapmodelinformationOnapModelInformation genericResourceApiOnapmodelinformationOnapModelInformationBodyParam) throws RestException { + log.info("PUT | VNF Topology Onap Model Information ({})", vnfId); + if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) { + } else { + log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated"); + } + + List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId); + ConfigServices data; + if((services == null) || (services.isEmpty())) { + log.info("Could not find data for ({}). Creating new Service Object.", serviceInstanceId); + data = new ConfigServices(); + data.setSvcInstanceId(serviceInstanceId); + } else { + data = services.get(0); + } + + GenericResourceApiServicedataServiceData svcData = null; + try { + svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class); + } catch(JsonProcessingException e) { + log.error("Could not map service data for ({})", serviceInstanceId); + } + if(svcData == null) { + log.info("Could not find Service Data for ({}). Creating new Service Data Container", serviceInstanceId); + svcData = new GenericResourceApiServicedataServiceData(); + } + if(svcData.getVnfs() == null) { + log.info("VNF List not found for ({}). Creating new VNF List Container.", serviceInstanceId); + svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs()); + svcData.getVnfs().setVnf(new ArrayList<>()); + } + + GenericResourceApiServicedataServicedataVnfs vnflist = new GenericResourceApiServicedataServicedataVnfs(); + HttpStatus responseStatus = HttpStatus.NO_CONTENT; + if(svcData.getVnfs().getVnf().isEmpty()) { + log.info("Creating VNF data for ({})", vnfId); + GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf(); + vnf.setVnfId(vnfId); + vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData()); + vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology()); + vnf.getVnfData().getVnfTopology().setOnapModelInformation(genericResourceApiOnapmodelinformationOnapModelInformationBodyParam); + vnflist.addVnfItem(vnf); + responseStatus = HttpStatus.CREATED; + } else { + log.info("Updating VNF data for ({})", vnfId); + // Filter out all of the other vnf objects into a new VNF List + // Replace if a delete method exists + svcData.getVnfs() + .getVnf() + .stream() + .filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId)) + .forEach(vnflist::addVnfItem); + GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf(); + // If the vnf exists, set it up with new data + Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnfOptional = getVnfObject(data, vnfId); + if(vnfOptional.isPresent()) { + vnf = vnfOptional.get(); + } + if(vnf.getVnfData() == null) { + vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData()); + } + if(vnf.getVnfData().getVnfTopology() == null) { + vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology()); + responseStatus = HttpStatus.CREATED; + } + + vnf.getVnfData().getVnfTopology().setOnapModelInformation(genericResourceApiOnapmodelinformationOnapModelInformationBodyParam); + vnflist.addVnfItem(vnf); + } + + svcData.setVnfs(vnflist); + // Map and save the new data + try { + data.setSvcData(objectMapper.writeValueAsString(svcData)); + configServicesRepository.save(data); + return new ResponseEntity<>(responseStatus); + } catch(JsonProcessingException e) { + log.error("Error mapping object to JSON", e); + // Should probably be a 500 INTERNAL_SERVICE_ERROR + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + /** + * Creates or updates VNF Network data in the Config table for a specified + * Service Instance. If it is a new Service Instance or a new VNF, creates + * all necessary parent data containers, then performs the updates. + * <p> + * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/ + * @param serviceInstanceId the Service Instance ID to perform the delete on + * @param vnfId the VNF ID of the VNF to delete + * @param genericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworksBodyParam the payload + * @return HttpStatus.CREATED (201) on successful create. + * <p> + * HttpStatus.NO_CONTENT (204) on successful update. + * <p> + * HttpStatus.BAD_REQUEST (400) if updating the database fails. + * @throws RestException + */ + @Override + public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyVnfResourceAssignmentsVnfNetworksPut(String serviceInstanceId, String vnfId, GenericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworks genericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworksBodyParam) throws RestException { + log.info("PUT | VNF Topology VNF Resource Assignments VNF Networks ({})", vnfId); + if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) { + } else { + log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated"); + } + + List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId); + ConfigServices data; + if((services == null) || (services.isEmpty())) { + log.info("Could not find data for ({}). Creating new Service Object.", serviceInstanceId); + data = new ConfigServices(); + data.setSvcInstanceId(serviceInstanceId); + } else { + data = services.get(0); + } + + GenericResourceApiServicedataServiceData svcData = null; + try { + svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class); + } catch(JsonProcessingException e) { + log.error("Could not map service data for ({})", serviceInstanceId); + } + if(svcData == null) { + log.info("Could not find Service Data for ({}). Creating new Service Data Container", serviceInstanceId); + svcData = new GenericResourceApiServicedataServiceData(); + } + if(svcData.getVnfs() == null) { + log.info("VNF List not found for ({}). Creating new VNF List Container.", serviceInstanceId); + svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs()); + svcData.getVnfs().setVnf(new ArrayList<>()); + } + + GenericResourceApiServicedataServicedataVnfs vnflist = new GenericResourceApiServicedataServicedataVnfs(); + HttpStatus responseStatus = HttpStatus.NO_CONTENT; + if(svcData.getVnfs().getVnf().isEmpty()) { + log.info("Creating VNF data for ({})", vnfId); + GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf(); + vnf.setVnfId(vnfId); + vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData()); + vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology()); + vnf.getVnfData().getVnfTopology().setVnfResourceAssignments(new GenericResourceApiVnfresourceassignmentsVnfResourceAssignments()); + vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().setVnfNetworks(genericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworksBodyParam); + vnflist.addVnfItem(vnf); + responseStatus = HttpStatus.CREATED; + } else { + log.info("Updating VNF data for ({})", vnfId); + // Filter out all of the other vnf objects into a new VNF List + // Replace if a delete method exists + svcData.getVnfs() + .getVnf() + .stream() + .filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId)) + .forEach(vnflist::addVnfItem); + GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf(); + // If the vnf exists, set it up with new data + Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnfOptional = getVnfObject(data, vnfId); + if(vnfOptional.isPresent()) { + vnf = vnfOptional.get(); + } + if(vnf.getVnfData() == null) { + vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData()); + } + if(vnf.getVnfData().getVnfTopology() == null) { + vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology()); + } + if(vnf.getVnfData().getVnfTopology().getVnfResourceAssignments() == null) { + vnf.getVnfData().getVnfTopology().setVnfResourceAssignments(new GenericResourceApiVnfresourceassignmentsVnfResourceAssignments()); + responseStatus = HttpStatus.CREATED; + } + + vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().setVnfNetworks(genericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworksBodyParam); + vnflist.addVnfItem(vnf); + } + + svcData.setVnfs(vnflist); + // Map and save the new data + try { + data.setSvcData(objectMapper.writeValueAsString(svcData)); + configServicesRepository.save(data); + return new ResponseEntity<>(responseStatus); + } catch(JsonProcessingException e) { + log.error("Error mapping object to JSON", e); + // Should probably be a 500 INTERNAL_SERVICE_ERROR + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + /** + * Creates or updates VNF Network Role data in the Config table for a + * specified Service Instance. If it is a new Service Instance or a new + * VNF, creates all necessary parent data containers, then performs the + * updates. + * <p> + * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/vnf-network/{network-role}/ + * @param serviceInstanceId the Service Instance ID to perform the delete on + * @param vnfId the VNF ID of the VNF to delete + * @param genericResourceApiVnfNetworkDataBodyParam the payload + * @return HttpStatus.CREATED (201) on successful create. + * <p> + * HttpStatus.NO_CONTENT (204) on successful update. + * <p> + * HttpStatus.BAD_REQUEST (400) if updating the database fails. + * @throws RestException + */ + @Override + public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyVnfResourceAssignmentsVnfNetworksVnfNetworkNetworkRolePut(String serviceInstanceId, String vnfId, String networkRole, GenericResourceApiVnfNetworkData genericResourceApiVnfNetworkDataBodyParam) throws RestException { + log.info("PUT | VNF Network Network Role ({})", vnfId); + if(!networkRole.equals(genericResourceApiVnfNetworkDataBodyParam.getNetworkRole())) { + throw new RestProtocolException("bad-attribute", "network-role mismatch", HttpStatus.BAD_REQUEST.value()); + } + if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) { + } else { + log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated"); + } + + List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId); + ConfigServices data; + if((services == null) || (services.isEmpty())) { + log.info("Could not find data for ({}). Creating new Service Object.", serviceInstanceId); + data = new ConfigServices(); + data.setSvcInstanceId(serviceInstanceId); + } else { + data = services.get(0); + } + + GenericResourceApiServicedataServiceData svcData = null; + try { + svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class); + } catch(JsonProcessingException e) { + log.error("Could not map service data for ({})", serviceInstanceId); + } + if(svcData == null) { + log.info("Could not find Service Data for ({}). Creating new Service Data Container", serviceInstanceId); + svcData = new GenericResourceApiServicedataServiceData(); + } + if(svcData.getVnfs() == null) { + log.info("VNF List not found for ({}). Creating new VNF List Container.", serviceInstanceId); + svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs()); + svcData.getVnfs().setVnf(new ArrayList<>()); + } + + GenericResourceApiServicedataServicedataVnfs vnflist = new GenericResourceApiServicedataServicedataVnfs(); + HttpStatus responseStatus = HttpStatus.NO_CONTENT; + if(svcData.getVnfs().getVnf().isEmpty()) { + log.info("Creating VNF data for ({})", vnfId); + GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf(); + vnf.setVnfId(vnfId); + vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData()); + vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology()); + vnf.getVnfData().getVnfTopology().setVnfResourceAssignments(new GenericResourceApiVnfresourceassignmentsVnfResourceAssignments()); + vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().setVnfNetworks(new GenericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworks()); + vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().setVnfNetwork(new ArrayList<>()); + vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().addVnfNetworkItem(genericResourceApiVnfNetworkDataBodyParam); + vnflist.addVnfItem(vnf); + responseStatus = HttpStatus.CREATED; + } else { + log.info("Updating VNF data for ({})", vnfId); + // Filter out all of the other vnf objects into a new VNF List + // Replace if a delete method exists + svcData.getVnfs() + .getVnf() + .stream() + .filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId)) + .forEach(vnflist::addVnfItem); + GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf(); + // If the vnf exists, set it up with new data + Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnfOptional = getVnfObject(data, vnfId); + if(vnfOptional.isPresent()) { + vnf = vnfOptional.get(); + } + if(vnf.getVnfData() == null) { + vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData()); + } + if(vnf.getVnfData().getVnfTopology() == null) { + vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology()); + } + if(vnf.getVnfData().getVnfTopology().getVnfResourceAssignments() == null) { + vnf.getVnfData().getVnfTopology().setVnfResourceAssignments(new GenericResourceApiVnfresourceassignmentsVnfResourceAssignments()); + } + if(vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks() == null) { + log.info("Creating new VnfNetworks"); + vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().setVnfNetworks(new GenericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworks()); + } + + GenericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworks networkList = new GenericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworks(); + if(vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().getVnfNetwork().isEmpty()) { + log.info("First entry into network info."); + vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().addVnfNetworkItem(genericResourceApiVnfNetworkDataBodyParam); + responseStatus = HttpStatus.CREATED; + } else { + log.info("Found networks. Filtering."); + vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().getVnfNetwork().stream() + .filter(targetNetwork -> !targetNetwork.getNetworkRole().equals(networkRole)) + .forEach(networkList::addVnfNetworkItem); + networkList.addVnfNetworkItem(genericResourceApiVnfNetworkDataBodyParam); + + if(networkList.getVnfNetwork().size() != vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().getVnfNetwork().size()) { + log.info("Added a new Item"); + responseStatus = HttpStatus.CREATED; + } + vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().setVnfNetworks(networkList); + } + + vnflist.addVnfItem(vnf); + } + + svcData.setVnfs(vnflist); + // Map and save the new data + try { + data.setSvcData(objectMapper.writeValueAsString(svcData)); + configServicesRepository.save(data); + return new ResponseEntity<>(responseStatus); + } catch(JsonProcessingException e) { + log.error("Error mapping object to JSON", e); + // Should probably be a 500 INTERNAL_SERVICE_ERROR + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + /** + * Extracts a VNF object from the database, + * @param configServices A Config Services option created from a Service + * Instance ID + * @param vnfId the target VNF ID + * @return An empty Optional if the Service Data does not exist, an empty + * Optional if the VNF is not found, or an optional containing the + * found VNF. + */ + private Optional<GenericResourceApiServicedataServicedataVnfsVnf> getVnfObject(ConfigServices configServices, String vnfId) { + // Map the Marshall the JSON String into a Java Object + log.info("Getting VNF Data for ({})", vnfId); + GenericResourceApiServicedataServiceData svcData; + try { + svcData = objectMapper.readValue(configServices.getSvcData(), GenericResourceApiServicedataServiceData.class); + } catch(JsonProcessingException e) { + log.error("Error", e); + return Optional.empty(); + } + + /*Get a stream of the VNF Objects and return the target if it's found, + * assuming that each VNF ID is unique within a Service Instance Object + */ + return svcData.getVnfs().getVnf() + .stream() + .filter(targetVnf -> targetVnf.getVnfId().equals(vnfId)) + .findFirst(); + } } diff --git a/ms/generic-resource-api/src/test/java/org/onap/sdnc/apps/ms/gra/controllers/ConfigApiServicesControllerTest.java b/ms/generic-resource-api/src/test/java/org/onap/sdnc/apps/ms/gra/controllers/ConfigApiServicesControllerTest.java index 609e780..7bcfefe 100644 --- a/ms/generic-resource-api/src/test/java/org/onap/sdnc/apps/ms/gra/controllers/ConfigApiServicesControllerTest.java +++ b/ms/generic-resource-api/src/test/java/org/onap/sdnc/apps/ms/gra/controllers/ConfigApiServicesControllerTest.java @@ -2,10 +2,12 @@ package org.onap.sdnc.apps.ms.gra.controllers; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; @@ -461,6 +463,192 @@ public class ConfigApiServicesControllerTest { configServicesRepository.deleteAll(); } + @Test + public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdDelete() throws Exception { + // Clean up data + configServicesRepository.deleteAll(); + + // Test with no data + MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(404, mvcResult.getResponse().getStatus()); + assertEquals(0, configServicesRepository.count()); + + // Load data + loadVnfData("src/test/resources/vnf-data.json"); + assertEquals(1, configServicesRepository.count()); + + // Test with data + mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(204, mvcResult.getResponse().getStatus()); + assertEquals(1, configServicesRepository.count()); + + configServicesRepository.deleteAll(); + loadVnfData("src/test/resources/vnf-data.json"); + assertEquals(1, configServicesRepository.count()); + mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(404, mvcResult.getResponse().getStatus()); + + configServicesRepository.deleteAll(); + createBadVnfData(true, true); + assertEquals(1, configServicesRepository.count()); + mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(404, mvcResult.getResponse().getStatus()); + + configServicesRepository.deleteAll(); + createBadVnfData(false, false); + assertEquals(1, configServicesRepository.count()); + mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(404, mvcResult.getResponse().getStatus()); + + configServicesRepository.deleteAll(); + createBadVnfData(false, true); + assertEquals(1, configServicesRepository.count()); + mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(404, mvcResult.getResponse().getStatus()); + } + + @Test + public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdGet() throws Exception { + // Clean up data + configServicesRepository.deleteAll(); + + // Test with no data + MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(404, mvcResult.getResponse().getStatus()); + assertEquals(0, configServicesRepository.count()); + + // Load data + loadVnfData("src/test/resources/vnf-data.json"); + assertEquals(1, configServicesRepository.count()); + + // Test with data + mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(200, mvcResult.getResponse().getStatus()); + + configServicesRepository.deleteAll(); + createBadVnfData(false, false); + assertEquals(1, configServicesRepository.count()); + mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(404, mvcResult.getResponse().getStatus()); + } + + @Test + public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdPut() throws Exception { + // Clean up data + configServicesRepository.deleteAll(); + assertEquals(0, configServicesRepository.count()); + MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-data.json"))) + .andReturn(); + assertEquals(201, mvcResult.getResponse().getStatus()); + assertEquals(1, configServicesRepository.count()); + + mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-data.json"))) + .andReturn(); + assertEquals(204, mvcResult.getResponse().getStatus()); + assertEquals(1, configServicesRepository.count()); + } + + @Test + public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyGet() throws Exception { + // Clean up data + configServicesRepository.deleteAll(); + + // Test with no data + MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(404, mvcResult.getResponse().getStatus()); + assertEquals(0, configServicesRepository.count()); + + // Load data + loadVnfData("src/test/resources/vnf-data.json"); + assertEquals(1, configServicesRepository.count()); + + // Test with data + mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(200, mvcResult.getResponse().getStatus()); + + configServicesRepository.deleteAll(); + createBadVnfData(false, false); + assertEquals(1, configServicesRepository.count()); + mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/").contentType(MediaType.APPLICATION_JSON).content("")) + .andReturn(); + assertEquals(404, mvcResult.getResponse().getStatus()); + } + + @Test + public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfLevelOperStatusPut() throws Exception { + // Clean up data + configServicesRepository.deleteAll(); + assertEquals(0, configServicesRepository.count()); + MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-level-oper-status/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-level-oper-status.json"))) + .andReturn(); + assertEquals(201, mvcResult.getResponse().getStatus()); + assertEquals(1, configServicesRepository.count()); + + mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-level-oper-status/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-level-oper-status.json"))) + .andReturn(); + assertEquals(204, mvcResult.getResponse().getStatus()); + assertEquals(1, configServicesRepository.count()); + } + + @Test + public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyOnapModelInformationPut() throws Exception { + // Clean up data + configServicesRepository.deleteAll(); + assertEquals(0, configServicesRepository.count()); + MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/onap-model-information/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-onap-model-info.json"))) + .andReturn(); + assertEquals(201, mvcResult.getResponse().getStatus()); + assertEquals(1, configServicesRepository.count()); + + mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/onap-model-information/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-onap-model-info.json"))) + .andReturn(); + assertEquals(204, mvcResult.getResponse().getStatus()); + assertEquals(1, configServicesRepository.count()); + } + + @Test + public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyVnfResourceAssignmentsVnfNetworksPut() throws Exception { + // Clean up data + configServicesRepository.deleteAll(); + assertEquals(0, configServicesRepository.count()); + MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-vnf-networks.json"))) + .andReturn(); + assertEquals(201, mvcResult.getResponse().getStatus()); + assertEquals(1, configServicesRepository.count()); + + mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-vnf-networks.json"))) + .andReturn(); + assertEquals(204, mvcResult.getResponse().getStatus()); + assertEquals(1, configServicesRepository.count()); + } + + @Test + public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyVnfResourceAssignmentsVnfNetworksVnfNetworkNetworkRolePut() throws Exception { + // Clean up data + configServicesRepository.deleteAll(); + assertEquals(0, configServicesRepository.count()); + MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/vnf-network/test-network-role/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-vnf-networks-network-role.json"))) + .andReturn(); + assertEquals(201, mvcResult.getResponse().getStatus()); + assertEquals(1, configServicesRepository.count()); + + mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/vnf-network/test-network-role/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-vnf-networks-network-role.json"))) + .andReturn(); + assertEquals(204, mvcResult.getResponse().getStatus()); + assertEquals(1, configServicesRepository.count()); + } + private String readFileContent(String path) throws IOException { String content = new String(Files.readAllBytes(Paths.get(path))); return content; @@ -485,4 +673,36 @@ public class ConfigApiServicesControllerTest { } } + private void loadVnfData(String path) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + String content = readFileContent(path); + GenericResourceApiServicedataServiceData svcData = new GenericResourceApiServicedataServiceData(); + GenericResourceApiServicedataServicedataVnfsVnf vnfData = objectMapper.readValue(content, GenericResourceApiServicedataServicedataVnfsVnf.class); + svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs()); + svcData.getVnfs().setVnf(new ArrayList<>()); + svcData.getVnfs().addVnfItem(vnfData); + ConfigServices newService = new ConfigServices(); + newService.setSvcData(objectMapper.writeValueAsString(svcData)); + newService.setSvcInstanceId("test-siid"); + configServicesRepository.save(newService); + } + + private void createBadVnfData(boolean useNullSvc, boolean useNullVnfs) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + ConfigServices newService = new ConfigServices(); + GenericResourceApiServicedataServiceData svcData = useNullSvc ? null : new GenericResourceApiServicedataServiceData(); + GenericResourceApiServicedataServicedataVnfs vnfs = useNullVnfs ? null : new GenericResourceApiServicedataServicedataVnfs(); + + // Overrides useNullSvc + if(!useNullVnfs) { + svcData = new GenericResourceApiServicedataServiceData(); + vnfs.setVnf(new ArrayList<>()); + svcData.setVnfs(vnfs); + } + + newService.setSvcInstanceId("test-siid"); + newService.setSvcData(objectMapper.writeValueAsString(svcData)); + configServicesRepository.save(newService); + } + }
\ No newline at end of file diff --git a/ms/generic-resource-api/src/test/resources/vnf-data.json b/ms/generic-resource-api/src/test/resources/vnf-data.json new file mode 100644 index 0000000..22fc4aa --- /dev/null +++ b/ms/generic-resource-api/src/test/resources/vnf-data.json @@ -0,0 +1,603 @@ +{ + "vnf-data": { + "request-information": { + "notification-url": "https://dev.null", + "order-number": "Order-123", + "order-version": "Order-v22", + "request-action": "CreateNetworkInstance", + "request-id": "a44e8401-2c62-47df-98be-9a09f6cbd996", + "source": "unit-test" + }, + "sdnc-request-header": { + "svc-action": "assign", + "svc-notification-url": "https://dev.null", + "svc-request-id": "9c06a7c6-be3a-4530-bdd8-c65b58f123a5" + }, + "service-information": { + "global-customer-id": "226fbb03-baf2-42bb-8311-03643a801238", + "onap-model-information": { + "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f", + "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e", + "model-name": "SMSF-NC2-578", + "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9", + "model-version": "3.0" + }, + "service-id": "98f189dd-2971-46f5-b4f1-1a9a323f39a4", + "service-instance-id": "98f189dd-2971-46f5-b4f1-1a9a323f39a4", + "subscriber-name": "unit-test", + "subscription-service-type": "unit-test" + }, + "vf-modules": { + "vf-module": [ + { + "vf-module-data": { + "request-information": { + "notification-url": "https://dev.null", + "order-number": "Order-123", + "order-version": "Order-v22", + "request-action": "CreateNetworkInstance", + "request-id": "a44e8401-2c62-47df-98be-9a09f6cbd996", + "source": "unit-test" + }, + "sdnc-request-header": { + "svc-action": "assign", + "svc-notification-url": "https://dev.null", + "svc-request-id": "9c06a7c6-be3a-4530-bdd8-c65b58f123a5" + }, + "service-information": { + "global-customer-id": "226fbb03-baf2-42bb-8311-03643a801238", + "onap-model-information": { + "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f", + "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e", + "model-name": "SMSF-NC2-578", + "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9", + "model-version": "3.0" + }, + "service-id": "98f189dd-2971-46f5-b4f1-1a9a323f39a4", + "service-instance-id": "98f189dd-2971-46f5-b4f1-1a9a323f39a4", + "subscriber-name": "unit-test", + "subscription-service-type": "unit-test" + }, + "vf-module-information": { + "from-preload": true, + "onap-model-information": { + "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f", + "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e", + "model-name": "SMSF-NC2-578", + "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9", + "model-version": "3.0" + }, + "vf-module-id": "9270c447-3caf-4e12-85aa-3578b0fa61d5", + "vf-module-type": "some-vf-module-type" + }, + "vf-module-level-oper-status": { + "create-timestamp": "string", + "last-action": "CreateNetworkInstance", + "last-order-status": "Active", + "last-rpc-action": "assign", + "last-svc-request-id": "9c06a7c6-be3a-4530-bdd8-c65b58f123a5", + "modify-timestamp": "string", + "order-status": "Active" + }, + "vf-module-request-input": { + "aic-clli": "string", + "aic-cloud-region": "test-region", + "cloud-owner": "unit-test", + "request-version": "string", + "tenant": "string", + "vf-module-input-parameters": { + "param": [ + { + "name": "string", + "resource-resolution-data": { + "capability-name": "string", + "payload": "string", + "resource-key": [ + { + "name": "string", + "value": "string" + } + ], + "status": "string" + }, + "value": "string" + } + ] + }, + "vf-module-name": "string" + }, + "vf-module-topology": { + "aic-clli": "string", + "aic-cloud-region": "test-region", + "cloud-owner": "unit-test", + "onap-model-information": { + "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f", + "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e", + "model-name": "SMSF-NC2-578", + "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9", + "model-version": "3.0" + }, + "sdnc-generated-cloud-resources": true, + "tenant": "string", + "vf-module-assignments": { + "dhcp-subnet-assignments": { + "dhcp-subnet-assignment": [ + { + "ip-version": "string", + "network-role": "test-network-role", + "neutron-subnet-id": "string" + } + ] + }, + "vf-module-status": "string", + "vlan-vnfc-instance-groups": { + "vlan-vnfc-instance-group": [ + { + "instance-group-function": "string", + "instance-group-id": "string", + "vnf-id": "2a3bfc93-cd4c-4845-8919-434b2d999ada", + "vnfcs": { + "vnfc": [ + { + "vnfc-name": "string", + "vnic-groups": { + "vnic-group": [ + { + "network-instance-group-function": "string", + "vlan-assignment-policy-name": "string", + "vlan-common-ip-addresses": { + "ip-addresses": { + "ipv4-address": "string", + "ipv6-address": "string", + "vipv4-address": "string", + "vipv6-address": "string" + } + }, + "vlan-tag-index-next": 0, + "vlan-vnics": { + "vlan-vnic": [ + { + "vnic-port-id": "string", + "vnic-sub-interfaces": { + "sub-interface-network-data": [ + { + "floating-ips": { + "floating-ip-v4": [ + "string" + ], + "floating-ip-v6": [ + "string" + ] + }, + "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf", + "network-information-items": { + "network-information-item": [ + { + "ip-count": 0, + "ip-version": "string", + "network-ips": { + "network-ip": [ + "string" + ] + }, + "use-dhcp": "Y" + } + ] + }, + "network-name": 0, + "network-role": "test-network-role", + "network-role-tag": "string", + "neutron-network-id": "string", + "vlan-tag-id": 0 + } + ] + } + } + ] + }, + "vnic-interface-role": "string" + } + ] + } + } + ] + } + } + ] + }, + "vms": { + "vm": [ + { + "nfc-naming-code": "string", + "onap-model-information": { + "model-customization-uuid": "string", + "model-invariant-uuid": "string", + "model-name": "string", + "model-uuid": "string", + "model-version": "string" + }, + "vm-count": 0, + "vm-names": { + "vm-name": [ + "string" + ], + "vnfc-names": [ + { + "vnfc-name": "string", + "vnfc-networks": { + "vnfc-network-data": [ + { + "connection-point": { + "connection-point-id": "string", + "port-id": "string", + "vlan-data": [ + { + "vlan-role": "string", + "vlan-tag-description": "string", + "vlan-tag-id": "string", + "vlan-uuid": "string" + } + ] + }, + "vnfc-network-role": "string", + "vnfc-ports": { + "vnfc-port": [ + { + "common-sub-interface-role": "string", + "vnfc-port-id": "string", + "vnic-sub-interfaces": { + "sub-interface-network-data": [ + { + "floating-ips": { + "floating-ip-v4": [ + "string" + ], + "floating-ip-v6": [ + "string" + ] + }, + "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf", + "network-information-items": { + "network-information-item": [ + { + "ip-count": 0, + "ip-version": "string", + "network-ips": { + "network-ip": [ + "string" + ] + }, + "use-dhcp": "Y" + } + ] + }, + "network-name": 0, + "network-role": "test-network-role", + "network-role-tag": "string", + "neutron-network-id": "string", + "vlan-tag-id": 0 + } + ] + } + } + ] + }, + "vnfc-subnet": [ + { + "vnfc-ip-assignments": [ + { + "vnfc-address-family": "ipv4", + "vnfc-subnet-dhcp": "Y", + "vnfc-subnet-ip": [ + { + "ip-type": "FIXED", + "vnfc-client-key": "string", + "vnfc-ip-address": "string" + } + ], + "vnfc-subnet-ip-count": 0 + } + ], + "vnfc-subnet-role": "string" + } + ], + "vnfc-type": "string" + } + ] + } + } + ] + }, + "vm-networks": { + "vm-network": [ + { + "floating-ips": { + "floating-ip-v4": [ + "string" + ], + "floating-ip-v6": [ + "string" + ] + }, + "interface-route-prefixes": { + "interface-route-prefix": [ + "string" + ] + }, + "is-trunked": true, + "mac-addresses": { + "mac-address": [ + "string" + ] + }, + "network-information-items": { + "network-information-item": [ + { + "ip-count": 0, + "ip-version": "string", + "network-ips": { + "network-ip": [ + "string" + ] + }, + "use-dhcp": "Y" + } + ] + }, + "network-role": "test-network-role", + "network-role-tag": "string", + "related-networks": { + "related-network": [ + { + "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf", + "network-role": "test-network-role", + "vlan-tags": { + "is-private": true, + "lower-tag-id": 0, + "upper-tag-id": 0, + "vlan-interface": "string" + } + } + ] + }, + "segmentation-id": "string", + "sriov-parameters": { + "application-tags": { + "c-tags": { + "c-tag": [ + "string" + ], + "ctag": [ + "string" + ] + }, + "ctags": { + "c-tag": [ + "string" + ], + "ctag": [ + "string" + ] + }, + "s-tags": { + "s-tag": [ + "string" + ], + "stag": [ + "string" + ] + }, + "stags": { + "s-tag": [ + "string" + ], + "stag": [ + "string" + ] + } + }, + "heat-vlan-filters": { + "heat-vlan-filter": [ + "string" + ] + } + } + } + ] + }, + "vm-type": "string", + "vm-type-tag": "string" + } + ] + } + }, + "vf-module-parameters": { + "param": [ + { + "name": "string", + "resource-resolution-data": { + "capability-name": "string", + "payload": "string", + "resource-key": [ + { + "name": "string", + "value": "string" + } + ], + "status": "string" + }, + "value": "string" + } + ] + }, + "vf-module-topology-identifier": { + "vf-module-id": "9270c447-3caf-4e12-85aa-3578b0fa61d5", + "vf-module-name": "some-vf-module-name", + "vf-module-type": "some-vf-module-type" + } + }, + "vnf-information": { + "onap-model-information": { + "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f", + "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e", + "model-name": "SMSF-NC2-578", + "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9", + "model-version": "3.0" + }, + "vnf-id": "2a3bfc93-cd4c-4845-8919-434b2d999ada", + "vnf-name": "mytestvnf", + "vnf-type" : "SMSF-NC2-578-SVC/SMSF-NC2-578" + } + }, + "vf-module-id": "9270c447-3caf-4e12-85aa-3578b0fa61d5" + } + ] + }, + "vnf-information": { + "onap-model-information": { + "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f", + "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e", + "model-name": "SMSF-NC2-578", + "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9", + "model-version": "3.0" + }, + "vnf-id": "2a3bfc93-cd4c-4845-8919-434b2d999ada", + "vnf-name": "mytestvnf", + "vnf-type" : "SMSF-NC2-578-SVC/SMSF-NC2-578" + }, + "vnf-level-oper-status": { + "create-timestamp": "string", + "last-action": "CreateNetworkInstance", + "last-order-status": "Active", + "last-rpc-action": "assign", + "last-svc-request-id": "9c06a7c6-be3a-4530-bdd8-c65b58f123a5", + "modify-timestamp": "string", + "order-status": "Active" + }, + "vnf-request-input": { + "aic-clli": "string", + "aic-cloud-region": "test-region", + "cloud-owner": "unit-test", + "request-version": "string", + "tenant": "string", + "vnf-name": "mytestvnf", + "vnf-networks": { + "vnf-network": [ + { + "contrail-network-fqdn": "string", + "is-trunked": true, + "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf", + "network-name": "test-network-name", + "network-role": "test-network-role", + "neutron-id": "812562dd-9d91-4ba6-9c3e-e52bf1cd4cc6", + "related-networks": { + "related-network": [ + { + "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf", + "network-role": "test-network-role", + "vlan-tags": { + "is-private": true, + "lower-tag-id": 0, + "upper-tag-id": 0, + "vlan-interface": "string" + } + } + ] + }, + "segmentation-id": "string", + "subnets-data": { + "subnet-data": [ + { + "cidr-mask": "string", + "dhcp-enabled": "Y", + "gateway-address": "string", + "ip-version": "string", + "network-start-address": "string", + "sdnc-subnet-id": "string", + "subnet-id": "string", + "subnet-name": "string", + "subnet-role": "string" + } + ] + } + } + ] + } + }, + "vnf-topology": { + "aic-clli": "string", + "aic-cloud-region": "test-region", + "cloud-owner": "unit-test", + "onap-model-information": { + "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f", + "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e", + "model-name": "SMSF-NC2-578", + "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9", + "model-version": "3.0" + }, + "sdnc-generated-cloud-resources": true, + "tenant": "string", + "vnf-resource-assignments": { + "availability-zones": { + "availability-zone": [ + "string" + ], + "max-count": 0 + }, + "vnf-networks": { + "vnf-network": [ + { + "contrail-network-fqdn": "string", + "is-trunked": true, + "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf", + "network-name": "test-network-name", + "network-role": "test-network-role", + "neutron-id": "812562dd-9d91-4ba6-9c3e-e52bf1cd4cc6", + "related-networks": { + "related-network": [ + { + "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf", + "network-role": "test-network-role", + "vlan-tags": { + "is-private": true, + "lower-tag-id": 0, + "upper-tag-id": 0, + "vlan-interface": "string" + } + } + ] + }, + "segmentation-id": "string", + "subnets-data": { + "subnet-data": [ + { + "cidr-mask": "string", + "dhcp-enabled": "Y", + "gateway-address": "string", + "ip-version": "string", + "network-start-address": "string", + "sdnc-subnet-id": "string", + "subnet-id": "string", + "subnet-name": "string", + "subnet-role": "string" + } + ] + } + } + ] + }, + "vnf-status": "string" + }, + "vnf-topology-identifier-structure": { + "nf-code": "string", + "nf-function": "string", + "nf-role": "string", + "nf-type": "string", + "vnf-id": "2a3bfc93-cd4c-4845-8919-434b2d999ada", + "vnf-name": "mytestvnf", + "vnf-type" : "SMSF-NC2-578-SVC/SMSF-NC2-578" + } + } + }, + "vnf-id": "2a3bfc93-cd4c-4845-8919-434b2d999ada" +}
\ No newline at end of file diff --git a/ms/generic-resource-api/src/test/resources/vnf-level-oper-status.json b/ms/generic-resource-api/src/test/resources/vnf-level-oper-status.json new file mode 100644 index 0000000..1778cab --- /dev/null +++ b/ms/generic-resource-api/src/test/resources/vnf-level-oper-status.json @@ -0,0 +1,11 @@ +{ + "vnf-level-oper-status": { + "create-timestamp": "string", + "last-action": "CreateNetworkInstance", + "last-order-status": "Active", + "last-rpc-action": "assign", + "last-svc-request-id": "9c06a7c6-be3a-4530-bdd8-c65b58f123a5", + "modify-timestamp": "string", + "order-status": "Active" + } +}
\ No newline at end of file diff --git a/ms/generic-resource-api/src/test/resources/vnf-onap-model-info.json b/ms/generic-resource-api/src/test/resources/vnf-onap-model-info.json new file mode 100644 index 0000000..d44dc49 --- /dev/null +++ b/ms/generic-resource-api/src/test/resources/vnf-onap-model-info.json @@ -0,0 +1,9 @@ +{ + "onap-model-information": { + "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f", + "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e", + "model-name": "SMSF-NC2-578", + "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9", + "model-version": "3.0" + } +}
\ No newline at end of file diff --git a/ms/generic-resource-api/src/test/resources/vnf-vnf-networks-network-role.json b/ms/generic-resource-api/src/test/resources/vnf-vnf-networks-network-role.json new file mode 100644 index 0000000..d435c4a --- /dev/null +++ b/ms/generic-resource-api/src/test/resources/vnf-vnf-networks-network-role.json @@ -0,0 +1,34 @@ +{ + "contrail-network-fqdn": "string", + "is-trunked": true, + "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf", + "network-name": "test-network-name", + "network-role": "test-network-role", + "neutron-id": "812562dd-9d91-4ba6-9c3e-e52bf1cd4cc6", + "related-networks": { + "related-network": [{ + "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf", + "network-role": "test-network-role", + "vlan-tags": { + "is-private": true, + "lower-tag-id": 0, + "upper-tag-id": 0, + "vlan-interface": "string" + } + }] + }, + "segmentation-id": "string", + "subnets-data": { + "subnet-data": [{ + "cidr-mask": "string", + "dhcp-enabled": "Y", + "gateway-address": "string", + "ip-version": "string", + "network-start-address": "string", + "sdnc-subnet-id": "string", + "subnet-id": "string", + "subnet-name": "string", + "subnet-role": "string" + }] + } +}
\ No newline at end of file diff --git a/ms/generic-resource-api/src/test/resources/vnf-vnf-networks.json b/ms/generic-resource-api/src/test/resources/vnf-vnf-networks.json new file mode 100644 index 0000000..3f73cba --- /dev/null +++ b/ms/generic-resource-api/src/test/resources/vnf-vnf-networks.json @@ -0,0 +1,38 @@ +{ + "vnf-networks": { + "vnf-network": [{ + "contrail-network-fqdn": "string", + "is-trunked": true, + "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf", + "network-name": "test-network-name", + "network-role": "test-network-role", + "neutron-id": "812562dd-9d91-4ba6-9c3e-e52bf1cd4cc6", + "related-networks": { + "related-network": [{ + "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf", + "network-role": "test-network-role", + "vlan-tags": { + "is-private": true, + "lower-tag-id": 0, + "upper-tag-id": 0, + "vlan-interface": "string" + } + }] + }, + "segmentation-id": "string", + "subnets-data": { + "subnet-data": [{ + "cidr-mask": "string", + "dhcp-enabled": "Y", + "gateway-address": "string", + "ip-version": "string", + "network-start-address": "string", + "sdnc-subnet-id": "string", + "subnet-id": "string", + "subnet-name": "string", + "subnet-role": "string" + }] + } + }] + } +}
\ No newline at end of file |