From b4b7e11715b8dbeda752229012d8cdc00ed5c32f Mon Sep 17 00:00:00 2001 From: AndrewLamb Date: Thu, 10 Sep 2020 13:37:31 +0100 Subject: Terminate NS Backend Service Issue-ID: SO-2869 Change-Id: I9c2b268d4f9aba7179633b71c8994065acacb742 Signed-off-by: AndrewLamb --- .../bpmn/flows/CamundaVariableNameConstants.java | 6 +- .../so/etsi/nfvo/ns/lcm/bpmn/flows/Constants.java | 1 + .../flows/extclients/aai/AaiServiceProvider.java | 2 + .../extclients/aai/AaiServiceProviderImpl.java | 7 + .../vnfm/Sol003AdapterServiceProvider.java | 3 + .../vnfm/Sol003AdapterServiceProviderImpl.java | 32 +++ .../extclients/vnfm/Sol003AdapterUrlProvider.java | 10 + .../lcm/bpmn/flows/service/JobExecutorService.java | 104 ++++++- .../flows/tasks/AbstractNetworkServiceTask.java | 69 ++++- .../bpmn/flows/tasks/CreateInstantiateVnfTask.java | 12 - .../ns/lcm/bpmn/flows/tasks/InstantiateNsTask.java | 63 +---- .../flows/tasks/MonitorSol003AdapterNodeTask.java | 6 +- .../MonitorSol003AdapterTerminateJobTask.java | 106 +++++++ .../MonitorSol003AdapterTerminateNodeTask.java | 55 ++++ .../ns/lcm/bpmn/flows/tasks/TerminateNsTask.java | 145 ++++++++++ .../ns/lcm/bpmn/flows/tasks/TerminateVnfTask.java | 187 +++++++++++++ .../MonitorSol003AdapterTerminateJob.bpmn | 160 +++++++++++ .../MonitorSol003AdapterTerminateNodeStatus.bpmn | 138 +++++++++ .../src/main/resources/TerminateNs.bpmn | 307 +++++++++++++++++++++ .../src/main/resources/TerminateVnf.bpmn | 171 ++++++++++++ .../MonitorSol003AdapterTerminateJobTaskTest.java | 148 ++++++++++ .../workflow/engine/tasks/TerminateNsTaskTest.java | 232 ++++++++++++++++ .../nfvo/ns/lcm/database/beans/NsLcmOpOcc.java | 2 +- .../so/etsi/nfvo/ns/lcm/database/beans/State.java | 2 +- .../database/service/DatabaseServiceProvider.java | 10 + .../nfvo/ns/lcm/EtsiSoNsLcmManagerUrlProvider.java | 2 +- .../nfvo/ns/lcm/lifecycle/NsLifeCycleManager.java | 10 +- .../lcm/rest/NsLifecycleManagementController.java | 10 +- .../rest/NsLifecycleManagementControllerTest.java | 40 ++- 29 files changed, 1946 insertions(+), 94 deletions(-) create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterTerminateJobTask.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterTerminateNodeTask.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/TerminateNsTask.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/TerminateVnfTask.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/MonitorSol003AdapterTerminateJob.bpmn create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/MonitorSol003AdapterTerminateNodeStatus.bpmn create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/TerminateNs.bpmn create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/TerminateVnf.bpmn create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/workflow/engine/tasks/MonitorSol003AdapterTerminateJobTaskTest.java create mode 100644 so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/workflow/engine/tasks/TerminateNsTaskTest.java (limited to 'so-etsi-nfvo') diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaVariableNameConstants.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaVariableNameConstants.java index e90391d51a..fd51b1a873 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaVariableNameConstants.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/CamundaVariableNameConstants.java @@ -31,7 +31,6 @@ public class CamundaVariableNameConstants { public static final String GLOBAL_CUSTOMER_ID_PARAM_NAME = "globalCustomerId"; public static final String SERVICE_TYPE_PARAM_NAME = "serviceType"; - public static final String NS_PACKAGE_MODEL_PARAM_NAME = "NSPackageModel"; public static final String CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME = "CreateNsWorkflowProcessingException"; @@ -47,6 +46,11 @@ public class CamundaVariableNameConstants { public static final String CREATE_VNF_RESPONSE_PARAM_NAME = "createVnfResponse"; public static final String OPERATION_STATUS_PARAM_NAME = "operationStatus"; + public static final String TERMINATE_NS_REQUEST_PARAM_NAME = "terminateNsRequest"; + public static final String NFVO_NF_INST_IDS_PARAM_NAME = "nfvoNfInstIds"; + public static final String DELETE_VNF_RESPONSE_PARAM_NAME = "deleteVnfResponse"; + public static final String TERMINATE_VNF_VNFID_PARAM_NAME = "vnfId"; + private CamundaVariableNameConstants() {} } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/Constants.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/Constants.java index a2128fc2af..14a4f4340b 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/Constants.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/Constants.java @@ -29,6 +29,7 @@ public class Constants { public static final String NS_WORKFLOW_ENGINE = "NS-WORKFLOW-ENGINE"; public static final String CREATE_NS_WORKFLOW_NAME = "CreateNs"; public static final String INSTANTIATE_NS_WORKFLOW_NAME = "InstantiateNs"; + public static final String TERMINATE_NS_WORKFLOW_NAME = "TerminateNs"; public static final String GET_NS_OCCURRENCE_OPERATION_STATUS_NAME = "GetNsOccurrenceOperationStatus"; diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java index 53062395cf..29ed85cbd8 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProvider.java @@ -41,4 +41,6 @@ public interface AaiServiceProvider { Optional getGenericVnf(final String vnfId); + void deleteGenericVnf(final String vnfId); + } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java index 049746c6ab..c6687096a2 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/aai/AaiServiceProviderImpl.java @@ -80,4 +80,11 @@ public class AaiServiceProviderImpl implements AaiServiceProvider { return aaiClientProvider.getAaiClient().get(GenericVnf.class, AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId)); } + + @Override + public void deleteGenericVnf(final String vnfId) { + logger.info("Deleting GenericVnf with id: {} from AAI.", vnfId); + final AAIResourceUri aaiResourceUri = AAIUriFactory.createResourceUri(AAIObjectType.GENERIC_VNF, vnfId); + aaiClientProvider.getAaiClient().delete(aaiResourceUri); + } } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterServiceProvider.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterServiceProvider.java index c053ba94f1..4f98e2c267 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterServiceProvider.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterServiceProvider.java @@ -23,6 +23,7 @@ package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.vnfm; import java.util.Optional; import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.CreateVnfRequest; import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.CreateVnfResponse; +import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.DeleteVnfResponse; import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.QueryJobResponse; public interface Sol003AdapterServiceProvider { @@ -31,4 +32,6 @@ public interface Sol003AdapterServiceProvider { Optional getInstantiateOperationJobStatus(final String jobId); + Optional invokeTerminationRequest(final String vnfId); + } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterServiceProviderImpl.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterServiceProviderImpl.java index 09fecc64ae..a0798f6e55 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterServiceProviderImpl.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterServiceProviderImpl.java @@ -24,6 +24,7 @@ import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.vnfm.Sol003Adap import java.util.Optional; import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.CreateVnfRequest; import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.CreateVnfResponse; +import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.DeleteVnfResponse; import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.QueryJobResponse; import org.onap.so.rest.exceptions.HttpResouceNotFoundException; import org.onap.so.rest.exceptions.InvalidRestRequestException; @@ -114,4 +115,35 @@ public class Sol003AdapterServiceProviderImpl implements Sol003AdapterServicePro throw exception; } } + + @Override + public Optional invokeTerminationRequest(final String vnfId) { + try { + final String url = urlProvider.getTerminateVnfUrl(vnfId); + + final ResponseEntity response = + httpServiceProvider.deleteHttpRequest(url, DeleteVnfResponse.class); + final HttpStatus httpStatus = response.getStatusCode(); + if (!(httpStatus.equals(HttpStatus.ACCEPTED)) && !(httpStatus.equals(HttpStatus.OK))) { + LOGGER.error("Unable to invoke HTTP DELETE using URL: {}, Response Code: {}", url, httpStatus.value()); + return Optional.empty(); + } + if (!response.hasBody()) { + LOGGER.error(RECEIVED_RESPONSE_WITHOUT_BODY, response); + return Optional.empty(); + } + + final DeleteVnfResponse deleteVnfResponse = response.getBody(); + if (deleteVnfResponse.getJobId() == null || deleteVnfResponse.getJobId().isEmpty()) { + LOGGER.error("Received invalid terminate response: {}", response); + return Optional.empty(); + } + + return Optional.of(deleteVnfResponse); + } catch (final RestProcessingException | InvalidRestRequestException + | HttpResouceNotFoundException httpInvocationException) { + LOGGER.error("Unexpected error while processing terminate request", httpInvocationException); + return Optional.empty(); + } + } } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterUrlProvider.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterUrlProvider.java index 351d4bf88c..e3abc059f5 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterUrlProvider.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/extclients/vnfm/Sol003AdapterUrlProvider.java @@ -61,4 +61,14 @@ public class Sol003AdapterUrlProvider { return UriComponentsBuilder.fromUri(baseUri).pathSegment("jobs").pathSegment(jobId).build().toString(); } + /** + * Get VNFM terminate vnf URL + * + * @param vnfId + * @return + */ + public String getTerminateVnfUrl(final String vnfId) { + return UriComponentsBuilder.fromUri(baseUri).pathSegment("vnfs").pathSegment(vnfId).build().toString(); + } + } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/JobExecutorService.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/JobExecutorService.java index 13cdc60b1b..f240fa33ef 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/JobExecutorService.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/service/JobExecutorService.java @@ -26,9 +26,12 @@ import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstan import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NS_INSTANCE_ID_PARAM_NAME; import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.OCC_ID_PARAM_NAME; import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.SERVICE_TYPE_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.TERMINATE_NS_REQUEST_PARAM_NAME; import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.CREATE_NS_WORKFLOW_NAME; import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.INSTANTIATE_NS_WORKFLOW_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.Constants.TERMINATE_NS_WORKFLOW_NAME; import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobAction.INSTANTIATE; +import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobAction.TERMINATE; import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.ERROR; import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.FINISHED; import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.FINISHED_WITH_ERROR; @@ -47,14 +50,17 @@ import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions.NsRequestProcessingExc import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobAction; import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum; import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJob; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst; import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NsLcmOpOcc; import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NsLcmOpType; import org.onap.so.etsi.nfvo.ns.lcm.database.beans.OperationStateEnum; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.State; import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider; import org.onap.so.etsi.nfvo.ns.lcm.model.CreateNsRequest; import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400; import org.onap.so.etsi.nfvo.ns.lcm.model.InstantiateNsRequest; import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesNsInstance; +import org.onap.so.etsi.nfvo.ns.lcm.model.TerminateNsRequest; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -156,8 +162,8 @@ public class JobExecutorService { final LocalDateTime currentDateTime = LocalDateTime.now(); final NsLcmOpOcc newNsLcmOpOcc = new NsLcmOpOcc().id(nsInstanceId).operation(NsLcmOpType.INSTANTIATE) .operationState(OperationStateEnum.PROCESSING).stateEnteredTime(currentDateTime) - .startTime(currentDateTime).isAutoInnovation(false).isCancelPending(false) - .operationParams(gson.toJson(instantiateNsRequest)); + .startTime(currentDateTime).nfvoNsInst(getNfvoNsInst(nsInstanceId)).isAutoInnovation(false) + .isCancelPending(false).operationParams(gson.toJson(instantiateNsRequest)); databaseServiceProvider.addNSLcmOpOcc(newNsLcmOpOcc); logger.info("New NSLcmOpOcc created in database :\n{}", newNsLcmOpOcc); @@ -190,6 +196,89 @@ public class JobExecutorService { throw new NsRequestProcessingException(message); } + public String runTerminateNsJob(final String nsInstanceId, final TerminateNsRequest terminateNsRequest) { + doInitialTerminateChecks(nsInstanceId, terminateNsRequest); + + final NfvoJob nfvoJob = new NfvoJob().startTime(LocalDateTime.now()).jobType("NS").jobAction(TERMINATE) + .resourceId(nsInstanceId).status(STARTING).progress(0); + databaseServiceProvider.addJob(nfvoJob); + logger.info("New job created in database :\n{}", nfvoJob); + + final LocalDateTime currentDateTime = LocalDateTime.now(); + final NsLcmOpOcc nsLcmOpOcc = new NsLcmOpOcc().id(nsInstanceId).operation(NsLcmOpType.TERMINATE) + .operationState(OperationStateEnum.PROCESSING).stateEnteredTime(currentDateTime) + .startTime(currentDateTime).nfvoNsInst(getNfvoNsInst(nsInstanceId)).isAutoInnovation(false) + .isCancelPending(false).operationParams(gson.toJson(terminateNsRequest)); + databaseServiceProvider.addNSLcmOpOcc(nsLcmOpOcc); + logger.info("New NSLcmOpOcc created in database :\n{}", nsLcmOpOcc); + + workflowExecutorService.executeWorkflow(nfvoJob.getJobId(), TERMINATE_NS_WORKFLOW_NAME, + getVariables(nsInstanceId, nfvoJob.getJobId(), nsLcmOpOcc.getId(), terminateNsRequest)); + + final ImmutableSet jobFinishedStates = + ImmutableSet.of(FINISHED, ERROR, FINISHED_WITH_ERROR, IN_PROGRESS); + final ImmutablePair immutablePair = + waitForJobToFinish(nfvoJob.getJobId(), jobFinishedStates); + + if (immutablePair.getRight() == null) { + final String message = + "Failed to Terminate NS with id: " + nsInstanceId + " for request: \n" + terminateNsRequest; + logger.error(message); + throw new NsRequestProcessingException(message); + } + + final JobStatusEnum finalJobStatus = immutablePair.getRight(); + + if (IN_PROGRESS.equals(finalJobStatus) || FINISHED.equals(finalJobStatus)) { + logger.info("Termination Job status: {}", finalJobStatus); + return nsLcmOpOcc.getId(); + } + + final String message = "Received unexpected Job Status: " + finalJobStatus + " Failed to Terminate NS with id: " + + nsInstanceId + " for request: \n" + terminateNsRequest; + logger.error(message); + throw new NsRequestProcessingException(message); + } + + private void doInitialTerminateChecks(final String nsInstanceId, final TerminateNsRequest terminateNsRequest) { + if (isNotImmediateTerminateRequest(terminateNsRequest)) { + final String message = "TerminateNsRequest received with terminateTime: " + + terminateNsRequest.getTerminationTime() + + "\nOnly immediate Terminate requests are currently supported \n(i.e., terminateTime field must not be set)."; + logger.error(message); + throw new NsRequestProcessingException(message); + } + + final NfvoNsInst nfvoNsInst = getNfvoNsInst(nsInstanceId); + if (isNotInstantiated(nfvoNsInst)) { + final String message = "TerminateNsRequest received: " + terminateNsRequest + " for nsInstanceId: " + + nsInstanceId + "\nUnable to terminate. NS Instance is already in NOT_INSTANTIATED state." + + "\nThis method can only be used with an NS instance in the INSTANTIATED state."; + logger.error(message); + throw new NsRequestProcessingException(message); + } + } + + private boolean isNotImmediateTerminateRequest(final TerminateNsRequest terminateNsRequest) { + return terminateNsRequest.getTerminationTime() != null; + } + + private boolean isNotInstantiated(final NfvoNsInst nfvoNsInst) { + return State.NOT_INSTANTIATED.equals(nfvoNsInst.getStatus()); + } + + private NfvoNsInst getNfvoNsInst(final String nsInstId) { + logger.info("Getting NfvoNsInst with nsInstId: {}", nsInstId); + final Optional optionalNfvoNsInst = databaseServiceProvider.getNfvoNsInst(nsInstId); + + if (optionalNfvoNsInst.isEmpty()) { + final String message = "No matching NS Instance for id: " + nsInstId + " found in database."; + throw new NsRequestProcessingException(message); + } + + return optionalNfvoNsInst.get(); + } + private ImmutablePair waitForJobToFinish(final String jobId, final ImmutableSet jobFinishedStates) { try { @@ -209,7 +298,7 @@ public class JobExecutorService { final NfvoJob nfvoJob = optional.get(); currentJobStatus = nfvoJob.getStatus(); - logger.info("Received job status response: \n ", nfvoJob); + logger.debug("Received job status response: \n {}", nfvoJob); if (jobFinishedStates.contains(nfvoJob.getStatus())) { logger.info("Job finished \n {}", currentJobStatus); return ImmutablePair.of(nfvoJob.getProcessInstanceId(), currentJobStatus); @@ -249,4 +338,13 @@ public class JobExecutorService { return variables; } + private Map getVariables(final String nsInstanceId, final String jobId, final String occId, + final TerminateNsRequest terminateNsRequest) { + final Map variables = new HashMap<>(); + variables.put(NS_INSTANCE_ID_PARAM_NAME, nsInstanceId); + variables.put(JOB_ID_PARAM_NAME, jobId); + variables.put(OCC_ID_PARAM_NAME, occId); + variables.put(TERMINATE_NS_REQUEST_PARAM_NAME, terminateNsRequest); + return variables; + } } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/AbstractNetworkServiceTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/AbstractNetworkServiceTask.java index 99116dacad..e6905b86fc 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/AbstractNetworkServiceTask.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/AbstractNetworkServiceTask.java @@ -21,6 +21,8 @@ package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.tasks; import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME; import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.JOB_ID_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NS_INSTANCE_ID_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.OCC_ID_PARAM_NAME; import java.time.LocalDateTime; import java.util.Optional; import org.camunda.bpm.engine.delegate.BpmnError; @@ -28,6 +30,9 @@ import org.camunda.bpm.engine.delegate.DelegateExecution; import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum; import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJob; import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJobStatus; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NsLcmOpOcc; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.OperationStateEnum; import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider; import org.onap.so.etsi.nfvo.ns.lcm.model.InlineResponse400; import org.slf4j.Logger; @@ -35,6 +40,7 @@ import org.slf4j.LoggerFactory; /** * @author Waqas Ikram (waqas.ikram@est.tech) + * @author Andrew Lamb (andrew.a.lamb@est.tech) * */ public abstract class AbstractNetworkServiceTask { @@ -90,6 +96,49 @@ public abstract class AbstractNetworkServiceTask { } + public void updateNsLcmOpOccStatusToCompleted(final DelegateExecution execution) { + logger.info("Executing updateNsLcmOpOccStatusToCompleted ..."); + final String occId = (String) execution.getVariable(OCC_ID_PARAM_NAME); + + final Optional optional = databaseServiceProvider.getNsLcmOpOcc(occId); + + if (optional.isEmpty()) { + final String message = "Unable to find record for NSLcmOpOcc in database using id: " + occId; + logger.error(message); + abortOperation(execution, message); + } + + final NsLcmOpOcc nsLcmOpOcc = optional.get(); + final OperationStateEnum operationStateCompleted = OperationStateEnum.COMPLETED; + logger.info("Setting operation state to {} for id: {}", operationStateCompleted, occId); + nsLcmOpOcc.setOperationState(operationStateCompleted); + databaseServiceProvider.addNSLcmOpOcc(nsLcmOpOcc); + + logger.info("Finished executing updateNsLcmOpOccStatusToCompleted ..."); + + } + + public void updateNsLcmOpOccStatusToFailed(final DelegateExecution execution) { + logger.info("Executing updateNsLcmOpOccStatusToFailed ..."); + final String occId = (String) execution.getVariable(OCC_ID_PARAM_NAME); + + final Optional optional = databaseServiceProvider.getNsLcmOpOcc(occId); + + if (optional.isPresent()) { + final NsLcmOpOcc nsLcmOpOcc = optional.get(); + final OperationStateEnum operationStateFailed = OperationStateEnum.FAILED; + logger.info("Setting operation state to {} for id: {}", operationStateFailed, occId); + nsLcmOpOcc.setOperationState(operationStateFailed); + + databaseServiceProvider.addNSLcmOpOcc(nsLcmOpOcc); + } else { + logger.error("Unable to find record for NSLcmOpOcc in database using id: {}", occId); + } + + logger.info("Finished executing updateNsLcmOpOccStatusToFailed ..."); + + } + protected void abortOperation(final DelegateExecution execution, final String message) { abortOperation(execution, message, new InlineResponse400().detail(message)); } @@ -104,7 +153,7 @@ public abstract class AbstractNetworkServiceTask { private NfvoJob getNfvoJob(final DelegateExecution execution) { final String jobId = (String) execution.getVariable(JOB_ID_PARAM_NAME); final Optional optional = databaseServiceProvider.getJob(jobId); - if (!optional.isPresent()) { + if (optional.isEmpty()) { final String message = "Unable to find job using job id: " + jobId; logger.error(message); execution.setVariable(CREATE_NS_WORKFLOW_PROCESSING_EXCEPTION_PARAM_NAME, @@ -114,4 +163,22 @@ public abstract class AbstractNetworkServiceTask { } return optional.get(); } + + protected NfvoNsInst getNfvoNsInst(final DelegateExecution execution) { + final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME); + return getNfvoNsInst(execution, nsInstId); + } + + protected NfvoNsInst getNfvoNsInst(final DelegateExecution execution, final String nsInstId) { + logger.info("Getting NfvoNsInst to update with nsInstId: {}", nsInstId); + final Optional optionalNfvoNsInst = databaseServiceProvider.getNfvoNsInst(nsInstId); + + if (optionalNfvoNsInst.isEmpty()) { + final String message = "Unable to find NS Instance in database using id: " + nsInstId; + abortOperation(execution, message); + } + + return optionalNfvoNsInst.get(); + } + } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateInstantiateVnfTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateInstantiateVnfTask.java index c33c67e540..251e694219 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateInstantiateVnfTask.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/CreateInstantiateVnfTask.java @@ -219,16 +219,4 @@ public class CreateInstantiateVnfTask extends AbstractNetworkServiceTask { databaseServiceProvider.saveNfvoNfInst(nfvoNfInst); } - private NfvoNsInst getNfvoNsInst(final DelegateExecution execution, final String nsInstId) { - logger.info("Getting NfvoNsInst to update with nsInstId: {}", nsInstId); - final Optional optionalNfvoNsInst = databaseServiceProvider.getNfvoNsInst(nsInstId); - - if (!optionalNfvoNsInst.isPresent()) { - final String message = "Unable to find NS Instance in datababse using id: " + nsInstId; - abortOperation(execution, message); - } - - return optionalNfvoNsInst.get(); - } - } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/InstantiateNsTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/InstantiateNsTask.java index 8d212045ad..6774fad543 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/InstantiateNsTask.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/InstantiateNsTask.java @@ -55,6 +55,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** + * @author Waqas Ikram (waqas.ikram@est.tech) * @author Andrew Lamb (andrew.a.lamb@est.tech) * */ @@ -272,50 +273,6 @@ public class InstantiateNsTask extends AbstractNetworkServiceTask { setJobStatusToError(execution, "Instantiate NS workflow process failed"); } - - public void updateNsLcmOpOccStatusToCompleted(final DelegateExecution execution) { - logger.info("Executing updateNsLcmOpOccStatusToCompleted ..."); - final String occId = (String) execution.getVariable(OCC_ID_PARAM_NAME); - - final Optional optional = databaseServiceProvider.getNsLcmOpOcc(occId); - - if (!optional.isPresent()) { - final String message = "Unable to find record for NSLcmOpOcc in database using id: " + occId; - logger.error(message); - abortOperation(execution, message); - } - - final NsLcmOpOcc nsLcmOpOcc = optional.get(); - final OperationStateEnum operationStateCompleted = OperationStateEnum.COMPLETED; - logger.info("Setting operation state to {} for id: {}", operationStateCompleted, occId); - nsLcmOpOcc.setOperationState(operationStateCompleted); - databaseServiceProvider.addNSLcmOpOcc(nsLcmOpOcc); - - logger.info("Finished executing updateNsLcmOpOccStatusToCompleted ..."); - - } - - public void updateNsLcmOpOccStatusToFailed(final DelegateExecution execution) { - logger.info("Executing updateNsLcmOpOccStatusToFailed ..."); - final String occId = (String) execution.getVariable(OCC_ID_PARAM_NAME); - - final Optional optional = databaseServiceProvider.getNsLcmOpOcc(occId); - - if (optional.isPresent()) { - final NsLcmOpOcc nsLcmOpOcc = optional.get(); - final OperationStateEnum operationStateFailed = OperationStateEnum.FAILED; - logger.info("Setting operation state to {} for id: {}", operationStateFailed, occId); - nsLcmOpOcc.setOperationState(operationStateFailed); - - databaseServiceProvider.addNSLcmOpOcc(nsLcmOpOcc); - } else { - logger.error("Unable to find record for NSLcmOpOcc in database using id: {}", occId); - } - - logger.info("Finished executing updateNsLcmOpOccStatusToFailed ..."); - - } - private NsdInfo getNsdInfo(final DelegateExecution execution, final String nsPackageId) { try { final Optional optional = @@ -395,22 +352,4 @@ public class InstantiateNsTask extends AbstractNetworkServiceTask { } - private NfvoNsInst getNfvoNsInst(final DelegateExecution execution) { - final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME); - return getNfvoNsInst(execution, nsInstId); - } - - private NfvoNsInst getNfvoNsInst(final DelegateExecution execution, final String nsInstId) { - logger.info("Getting NfvoNsInst to update with nsInstId: {}", nsInstId); - final Optional optionalNfvoNsInst = databaseServiceProvider.getNfvoNsInst(nsInstId); - - if (!optionalNfvoNsInst.isPresent()) { - final String message = "Unable to find NS Instance in database using id: " + nsInstId; - abortOperation(execution, message); - } - - return optionalNfvoNsInst.get(); - } - - } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterNodeTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterNodeTask.java index e27e0c1579..e4dc3d5e07 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterNodeTask.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterNodeTask.java @@ -57,7 +57,7 @@ public abstract class MonitorSol003AdapterNodeTask extends AbstractNetworkServic final Optional aaiGenericVnfOptional = aaiServiceProvider.getGenericVnf(vnfId); if (!aaiGenericVnfOptional.isPresent()) { - abortOperation(execution, "Unable to invoke Sol003 adapter for create and instantiate vnfId" + vnfId); + abortOperation(execution, "Unable to find generic vnf in A&AI using vnfId" + vnfId); } final GenericVnf genericVnf = aaiGenericVnfOptional.get(); final String orchestrationStatus = genericVnf.getOrchestrationStatus(); @@ -89,4 +89,8 @@ public abstract class MonitorSol003AdapterNodeTask extends AbstractNetworkServic LOGGER.error(message); abortOperation(execution, message); } + + AaiServiceProvider getAaiServiceProvider() { + return aaiServiceProvider; + } } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterTerminateJobTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterTerminateJobTask.java new file mode 100644 index 0000000000..d85444497d --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterTerminateJobTask.java @@ -0,0 +1,106 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.tasks; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.DeleteVnfResponse; +import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStateEnum; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.vnfm.Sol003AdapterServiceProvider; +import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.OPERATION_STATUS_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.DELETE_VNF_RESPONSE_PARAM_NAME; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * @author Andrew Lamb (andrew.a.lamb@est.tech) + * + */ +@Component +public class MonitorSol003AdapterTerminateJobTask extends MonitorSol003AdapterJobTask { + + private static final Logger LOGGER = LoggerFactory.getLogger(MonitorSol003AdapterTerminateJobTask.class); + + @Autowired + public MonitorSol003AdapterTerminateJobTask(final Sol003AdapterServiceProvider sol003AdapterServiceProvider, + final DatabaseServiceProvider databaseServiceProvider) { + super(sol003AdapterServiceProvider, databaseServiceProvider); + } + + public void getCurrentOperationStatus(final DelegateExecution execution) { + try { + LOGGER.debug("Executing getCurrentOperationStatus ..."); + final DeleteVnfResponse deleteVnfResponse = + (DeleteVnfResponse) execution.getVariable(DELETE_VNF_RESPONSE_PARAM_NAME); + execution.setVariable(OPERATION_STATUS_PARAM_NAME, + getOperationStatus(execution, deleteVnfResponse.getJobId())); + LOGGER.debug("Finished executing getCurrentOperationStatus ..."); + } catch (final Exception exception) { + final String message = "Unable to invoke get current Operation status"; + LOGGER.error(message, exception); + abortOperation(execution, message); + + } + } + + /** + * Log and throw exception on timeout for job status + * + * @param execution {@link org.onap.so.bpmn.common.DelegateExecutionImpl} + */ + public void timeOutLogFailure(final DelegateExecution execution) { + final String message = "Termination operation time out"; + LOGGER.error(message); + abortOperation(execution, message); + } + + /** + * Check the final status of termination throw exception if not completed successfully + * + * @param execution {@link org.onap.so.bpmn.common.DelegateExecutionImpl} + */ + public void checkIfOperationWasSuccessful(final DelegateExecution execution) { + LOGGER.debug("Executing checkIfOperationWasSuccessful ..."); + final OperationStateEnum operationStatus = + (OperationStateEnum) execution.getVariable(OPERATION_STATUS_PARAM_NAME); + final DeleteVnfResponse deleteVnfResponse = + (DeleteVnfResponse) execution.getVariable(DELETE_VNF_RESPONSE_PARAM_NAME); + + if (operationStatus == null) { + final String message = + "Unable to terminate, jobId: " + (deleteVnfResponse != null ? deleteVnfResponse.getJobId() : "null") + + "Unable to retrieve OperationStatus"; + LOGGER.error(message); + abortOperation(execution, message); + } + if (operationStatus != OperationStateEnum.COMPLETED) { + final String message = + "Unable to terminate, jobId: " + (deleteVnfResponse != null ? deleteVnfResponse.getJobId() : "null") + + " OperationStatus: " + operationStatus; + LOGGER.error(message); + abortOperation(execution, message); + } + + LOGGER.debug("Successfully completed termination of job {}", deleteVnfResponse); + } +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterTerminateNodeTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterTerminateNodeTask.java new file mode 100644 index 0000000000..f38bdba71b --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/MonitorSol003AdapterTerminateNodeTask.java @@ -0,0 +1,55 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.tasks; + +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.aai.AaiServiceProvider; +import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * @author Andrew Lamb (andrew.a.lamb@est.tech) + * + */ +@Component +public class MonitorSol003AdapterTerminateNodeTask extends MonitorSol003AdapterNodeTask { + + public static final String DELETE_VNF_NODE_STATUS = "deleteVnfNodeStatus"; + public static final String VNF_ASSIGNED = "Assigned"; + + @Autowired + public MonitorSol003AdapterTerminateNodeTask(final DatabaseServiceProvider databaseServiceProvider, + final AaiServiceProvider aaiServiceProvider) { + super(databaseServiceProvider, aaiServiceProvider); + } + + @Override + public String getNodeStatusVariableName() { + return DELETE_VNF_NODE_STATUS; + } + + @Override + public boolean isOrchestrationStatusValid(final String orchestrationStatus) { + return VNF_ASSIGNED.equalsIgnoreCase(orchestrationStatus); + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/TerminateNsTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/TerminateNsTask.java new file mode 100644 index 0000000000..972e4d6de8 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/TerminateNsTask.java @@ -0,0 +1,145 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.tasks; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNfInst; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.State; +import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.List; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NS_INSTANCE_ID_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.FINISHED; +import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.IN_PROGRESS; +import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.STARTED; + +/** + * @author Andrew Lamb (andrew.a.lamb@est.tech) + * + */ +@Component +public class TerminateNsTask extends AbstractNetworkServiceTask { + + private static final String IS_NS_TERMINATION_SUCCESSFUL_PARAM_NAME = "isNsTerminationSuccessful"; + private static final Logger logger = LoggerFactory.getLogger(TerminateNsTask.class); + + @Autowired + public TerminateNsTask(final DatabaseServiceProvider databaseServiceProvider) { + super(databaseServiceProvider); + } + + public void setJobStatusToStarted(final DelegateExecution execution) { + setJobStatus(execution, STARTED, "Terminate NS workflow process started"); + } + + public void setJobStatusToFinished(final DelegateExecution execution) { + setJobStatus(execution, FINISHED, "Terminate NS workflow process finished"); + } + + public void setJobStatusToError(final DelegateExecution execution) { + updateNsInstanceStatus(execution, State.FAILED); + setJobStatusToError(execution, "Terminate NS workflow process failed"); + } + + public void updateNsInstanceStatusToTerminating(final DelegateExecution execution) { + logger.info("Executing updateNsInstanceStatusToTerminating"); + setJobStatus(execution, IN_PROGRESS, "Updating NfvoNsInst Status to " + State.TERMINATING); + updateNsInstanceStatus(execution, State.TERMINATING); + logger.info("Finished executing updateNsInstanceStatusToTerminating ..."); + } + + public void updateNsInstanceStatusToNotInstantiated(final DelegateExecution execution) { + logger.info("Executing updateNsInstanceStatusToNotInstantiated"); + setJobStatus(execution, IN_PROGRESS, "Updating NfvoNsInst Status to " + State.NOT_INSTANTIATED); + updateNsInstanceStatus(execution, State.NOT_INSTANTIATED); + logger.info("Finished executing updateNsInstanceStatusToNotInstantiated ..."); + } + + public void getVnfIdsInNs(final DelegateExecution execution) { + logger.info("Executing getVnfIdsInNs ..."); + setJobStatus(execution, IN_PROGRESS, "Getting Each VnfId In Ns"); + final List nfvoNfInstIds = getNfvoNfInstIds(execution); + execution.setVariable(CamundaVariableNameConstants.NFVO_NF_INST_IDS_PARAM_NAME, nfvoNfInstIds); + logger.info("Finished executing getVnfIdsInNs ..."); + } + + public void checkIfVnfTerminationWasSuccessful(final DelegateExecution execution) { + logger.info("Executing checkIfVnfTerminationWasSuccessful"); + + final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME); + final List nfInstances = databaseServiceProvider.getNfvoNfInstByNsInstId(nsInstId); + + if ((nfInstances != null) && !(nfInstances.isEmpty())) { + final String message = "Found NF Instances"; + nfInstances.stream().forEach(instance -> { + logger.error("VNF : {} {} termination failed", instance.getNfInstId(), instance.getName()); + execution.setVariable(IS_NS_TERMINATION_SUCCESSFUL_PARAM_NAME, false); + }); + abortOperation(execution, message); + } + + execution.setVariable(IS_NS_TERMINATION_SUCCESSFUL_PARAM_NAME, true); + logger.info("Finished executing checkIfVnfTerminationWasSuccessful"); + } + + public void logTimeOut(final DelegateExecution execution) { + logger.error("Vnf termination timedOut ..."); + final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME); + final List nfInstances = databaseServiceProvider.getNfvoNfInstByNsInstId(nsInstId); + if (nfInstances != null) { + nfInstances.stream().forEach(instance -> { + logger.info("Current status {} of vnf: {}", instance.getStatus(), instance.getName()); + }); + } + } + + private void updateNsInstanceStatus(final DelegateExecution execution, final State nsStatus) { + final NfvoNsInst nfvoNsInst = getNfvoNsInst(execution); + logger.info("Updating NfvoNsInst Status to {} and saving to DB", nsStatus); + nfvoNsInst.setStatus(nsStatus); + databaseServiceProvider.saveNfvoNsInst(nfvoNsInst); + } + + private List getNfvoNfInstIds(final DelegateExecution execution) { + final String nsInstId = (String) execution.getVariable(NS_INSTANCE_ID_PARAM_NAME); + logger.info("Getting NfvoNfInstList using nsInstId: {}", nsInstId); + final List nfvoNfInstList = databaseServiceProvider.getNfvoNfInstByNsInstId(nsInstId); + + if (nfvoNfInstList.size() == 0) { + final String message = "Unable to find NF Instances in database using id: " + nsInstId; + abortOperation(execution, message); + } + + final List vnfIdsList = new ArrayList<>(); + + nfvoNfInstList.stream().forEach(nfvoNfInst -> { + vnfIdsList.add(nfvoNfInst.getNfInstId()); + }); + + return vnfIdsList; + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/TerminateVnfTask.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/TerminateVnfTask.java new file mode 100644 index 0000000000..15eee22dd2 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/tasks/TerminateVnfTask.java @@ -0,0 +1,187 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.tasks; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.DeleteVnfResponse; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.aai.AaiServiceProvider; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.vnfm.Sol003AdapterServiceProvider; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNfInst; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.State; +import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import java.util.Optional; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NF_INST_ID_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.DELETE_VNF_RESPONSE_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.TERMINATE_VNF_VNFID_PARAM_NAME; +import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.ERROR; +import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.FINISHED; +import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.JobStatusEnum.IN_PROGRESS; + +/** + * @author Andrew Lamb (andrew.a.lamb@est.tech) + */ +@Component +public class TerminateVnfTask extends AbstractNetworkServiceTask { + private static final Logger logger = LoggerFactory.getLogger(TerminateVnfTask.class); + private final AaiServiceProvider aaiServiceProvider; + private final Sol003AdapterServiceProvider sol003AdapterServiceProvider; + + @Autowired + public TerminateVnfTask(final DatabaseServiceProvider databaseServiceProvider, + final AaiServiceProvider aaiServiceProvider, + final Sol003AdapterServiceProvider sol003AdapterServiceProvider) { + super(databaseServiceProvider); + this.aaiServiceProvider = aaiServiceProvider; + this.sol003AdapterServiceProvider = sol003AdapterServiceProvider; + } + + public void checkIfNfInstanceExistsInDb(final DelegateExecution execution) { + logger.info("Executing checkIfNfInstanceInDb"); + final String vnfId = (String) execution.getVariable(TERMINATE_VNF_VNFID_PARAM_NAME); + logger.info("vnfId: {}", vnfId); + execution.setVariable(NF_INST_ID_PARAM_NAME, vnfId); + + setJobStatus(execution, JobStatusEnum.IN_PROGRESS, + "Checking if VNF Instance with id: " + vnfId + " exists in database."); + if (!databaseServiceProvider.isNfInstExists(vnfId)) { + abortOperation(execution, + "VNF instance with id: " + vnfId + " does not exist in database, so will not be terminated."); + } + logger.info("Finished executing checkIfNfInstanceInDb ..."); + + } + + public void invokeTerminateRequest(final DelegateExecution execution) { + logger.info("Executing invokeTerminateRequest"); + final String vnfId = (String) execution.getVariable(TERMINATE_VNF_VNFID_PARAM_NAME); + + try { + setJobStatus(execution, IN_PROGRESS, "Invoking SOL003 adapter for terminating VNF with vnfId: " + vnfId); + + final Optional optional = sol003AdapterServiceProvider.invokeTerminationRequest(vnfId); + + if (optional.isEmpty()) { + final String errorMessage = "Unexpected error while processing terminate request for vnfId: " + vnfId; + logger.error(errorMessage); + abortOperation(execution, errorMessage); + } + + final DeleteVnfResponse vnfResponse = optional.get(); + + logger.info("Vnf delete response: {}", vnfResponse); + execution.setVariable(DELETE_VNF_RESPONSE_PARAM_NAME, vnfResponse); + setJobStatus(execution, IN_PROGRESS, "Successfully invoked SOL003 adapter terminate VNF with vnfId: " + + vnfId + " DeleteVnfResponse Job Id: " + vnfResponse.getJobId()); + logger.debug("Finished executing invokeTerminateRequest ..."); + } catch (final Exception exception) { + final String message = "Unable to invoke terminate request for vnfId: " + vnfId; + logger.error(message, exception); + abortOperation(execution, message); + } + + } + + public void deleteGenericVnfFromAai(final DelegateExecution execution) { + logger.info("Executing deleteGenericVnfFromAai"); + final String vnfId = (String) execution.getVariable(TERMINATE_VNF_VNFID_PARAM_NAME); + + try { + setJobStatus(execution, IN_PROGRESS, "Deleting GenericVnf record from AAI for vnfId: " + vnfId); + aaiServiceProvider.deleteGenericVnf(vnfId); + + } catch (final Exception exception) { + final String message = "Unable to Delete GenericVnf from AAI for vnfId: " + vnfId; + logger.error(message, exception); + abortOperation(execution, message); + } + + logger.info("Finished executing deleteGenericVnfFromAai ..."); + } + + public void deleteNfInstanceFromDb(final DelegateExecution execution) { + logger.info("Executing deleteNfInstanceFromDb"); + final String vnfId = (String) execution.getVariable(TERMINATE_VNF_VNFID_PARAM_NAME); + + setJobStatus(execution, IN_PROGRESS, "Deleting NF Instance record from Database for vnfId: " + vnfId); + databaseServiceProvider.deleteNfvoNfInst(vnfId); + + setJobStatus(execution, FINISHED, "Successfully finished terminating VNF with vnfId: " + vnfId); + logger.info("Finished executing deleteNfInstanceFromDb ..."); + } + + public void updateNfInstanceStatusToTerminating(final DelegateExecution execution) { + logger.info("Executing updateNfInstanceStatusToTerminating"); + + updateNfInstanceStatus(execution, State.TERMINATING); + final String vnfId = (String) execution.getVariable(TERMINATE_VNF_VNFID_PARAM_NAME); + setJobStatus(execution, IN_PROGRESS, + "Terminating VNF with vnfId: " + vnfId + " will set status to " + State.TERMINATING); + + logger.info("Finished executing updateNfInstanceStatusToTerminating ..."); + + } + + public void updateNfInstanceStatusToNotInstantiated(final DelegateExecution execution) { + logger.info("Executing updateNfInstanceStatusToNotInstantiated"); + + updateNfInstanceStatus(execution, State.NOT_INSTANTIATED); + final String vnfId = (String) execution.getVariable(TERMINATE_VNF_VNFID_PARAM_NAME); + setJobStatus(execution, IN_PROGRESS, + "Successfully terminated VNF with vnfId: " + vnfId + " will set status to " + State.NOT_INSTANTIATED); + + logger.info("Finished executing updateNfInstanceStatusToInstantiated ..."); + + } + + public void updateNfInstanceStatusToFailed(final DelegateExecution execution) { + logger.info("Executing updateNfInstanceStatusToFailed"); + + updateNfInstanceStatus(execution, State.FAILED); + final String vnfId = (String) execution.getVariable(TERMINATE_VNF_VNFID_PARAM_NAME); + setJobStatus(execution, ERROR, + "Failed to terminate VNF with vnfId: " + vnfId + " will set status to " + State.FAILED); + + logger.info("Finished executing updateNfInstanceStatusToFailed ..."); + + } + + private void updateNfInstanceStatus(final DelegateExecution execution, final State vnfStatus) { + final String vnfId = (String) execution.getVariable(TERMINATE_VNF_VNFID_PARAM_NAME); + + final Optional optional = databaseServiceProvider.getNfvoNfInst(vnfId); + if (optional.isEmpty()) { + final String message = "Unable to find NfvoNfInst record in database using vnfId: " + vnfId; + logger.error(message); + + abortOperation(execution, message); + + } + + final NfvoNfInst nfvoNfInst = optional.get(); + nfvoNfInst.setStatus(vnfStatus); + databaseServiceProvider.saveNfvoNfInst(nfvoNfInst); + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/MonitorSol003AdapterTerminateJob.bpmn b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/MonitorSol003AdapterTerminateJob.bpmn new file mode 100644 index 0000000000..1181a497b2 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/MonitorSol003AdapterTerminateJob.bpmn @@ -0,0 +1,160 @@ + + + + + SequenceFlow_1x3tbl0 + + + SequenceFlow_1543qy7 + + + SequenceFlow_1x3tbl0 + SequenceFlow_1v4yr3f + + SequenceFlow_0s1plu9 + + + SequenceFlow_153a3kp + SequenceFlow_1vmxw9g + SequenceFlow_0is7myf + + + SequenceFlow_1vmxw9g + SequenceFlow_0etw572 + + PT15S + + + + SequenceFlow_0is7myf + + + + + SequenceFlow_0etw572 + SequenceFlow_0s1plu9 + SequenceFlow_153a3kp + + + + ${MonitorSol003AdapterCreateJobTask.hasOperationFinished(execution)} + + + + + SequenceFlow_0bcgtzj + + + + SequenceFlow_1i1o9sh + + PT3H + + + + + + + SequenceFlow_1i1o9sh + SequenceFlow_0bcgtzj + + + + SequenceFlow_1v4yr3f + SequenceFlow_1543qy7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/MonitorSol003AdapterTerminateNodeStatus.bpmn b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/MonitorSol003AdapterTerminateNodeStatus.bpmn new file mode 100644 index 0000000000..5629ce81fa --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/MonitorSol003AdapterTerminateNodeStatus.bpmn @@ -0,0 +1,138 @@ + + + + + SequenceFlow_1miob62 + + + SequenceFlow_1miob62 + + SequenceFlow_1moaz0q + + + SequenceFlow_0qvy3sn + SequenceFlow_1rxbeqi + SequenceFlow_1luu31f + + + SequenceFlow_1luu31f + SequenceFlow_09t51ao + + PT15S + + + + SequenceFlow_1rxbeqi + + + SequenceFlow_1moaz0q + SequenceFlow_09t51ao + SequenceFlow_0qvy3sn + + + ${execution.getVariable("deleteVnfNodeStatus")} + + + + + + + + SequenceFlow_0uiqnl8 + + + + SequenceFlow_0qcc5x4 + SequenceFlow_0uiqnl8 + + + SequenceFlow_0qcc5x4 + + PT3H + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/TerminateNs.bpmn b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/TerminateNs.bpmn new file mode 100644 index 0000000000..36c52c8ad6 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/TerminateNs.bpmn @@ -0,0 +1,307 @@ + + + + + SequenceFlow_16k0f61 + + + + Flow_04pxtdd + SequenceFlow_0bdznyp + + + Flow_1pcu8aa + + + + SequenceFlow_16k0f61 + Flow_04pxtdd + + + + + Flow_07bh7l7 + + + + Flow_1wa1jpl + + + Flow_0n3dai5 + Flow_1wa1jpl + + + + + Flow_07bh7l7 + Flow_0n3dai5 + + + + + + Flow_05lo00r + + + + Flow_16aryg5 + + + Flow_09zcw2a + Flow_16aryg5 + + + + + Flow_05lo00r + Flow_09zcw2a + + + + + Flow_1i36dw4 + Flow_1pcu8aa + + + + + + + + + Flow_01ju1mj + Flow_0mi4nqa + + + + Flow_17zn7we + + PT3H + + + + + SequenceFlow_0bdznyp + Flow_01ju1mj + + + + Flow_1nieng0 + Flow_0xptc0r + + + + Flow_10oprxr + Flow_1p21p1m + + + + Flow_15m4nm1 + Flow_1nieng0 + Flow_10oprxr + + + #{isNsTerminationSuccessful} + + + Flow_0mi4nqa + Flow_15m4nm1 + + + + + Flow_17zn7we + Flow_1p21p1m + + + #{not isNsTerminationSuccessful} + + + + Flow_0xptc0r + Flow_1i36dw4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/TerminateVnf.bpmn b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/TerminateVnf.bpmn new file mode 100644 index 0000000000..994933f2ac --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/resources/TerminateVnf.bpmn @@ -0,0 +1,171 @@ + + + + + Flow_02bjz2v + + + + Flow_1egtf3w + + + Flow_02bjz2v + Flow_123uagz + + + + Flow_0in3hgl + SequenceFlow_0xzptc2 + + + + + + + SequenceFlow_0xzptc2 + SequenceFlow_053tvct + + + + + Flow_1rw8pwu + Flow_0srinh7 + + + + + Flow_06q1m6i + + + + Flow_0anjylz + + + Flow_06q1m6i + Flow_0anjylz + + + + + + + + + + SequenceFlow_053tvct + Flow_1wfvdmt + + + + + Flow_0srinh7 + Flow_1egtf3w + + + + Flow_123uagz + Flow_0in3hgl + + + Flow_1wfvdmt + Flow_1rw8pwu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/workflow/engine/tasks/MonitorSol003AdapterTerminateJobTaskTest.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/workflow/engine/tasks/MonitorSol003AdapterTerminateJobTaskTest.java new file mode 100644 index 0000000000..13fff6d32b --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/workflow/engine/tasks/MonitorSol003AdapterTerminateJobTaskTest.java @@ -0,0 +1,148 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.workflow.engine.tasks; + +import com.google.gson.Gson; +import org.camunda.bpm.engine.history.HistoricProcessInstance; +import org.camunda.bpm.engine.history.HistoricVariableInstance; +import org.camunda.bpm.engine.runtime.ProcessInstance; +import org.junit.Before; +import org.junit.Test; +import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.DeleteVnfResponse; +import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStateEnum; +import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.QueryJobResponse; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.BaseTest; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.GsonProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.GsonHttpMessageConverter; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.web.client.RestTemplate; +import java.util.HashMap; +import java.util.Map; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStateEnum.COMPLETED; +import static org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStateEnum.PROCESSING; +import static org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStatusRetrievalStatusEnum.STATUS_FOUND; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.vnfm.Sol003AdapterConfiguration.SOL003_ADAPTER_REST_TEMPLATE_BEAN; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +/** + * @author Waqas Ikram (waqas.ikram@est.tech) + * @author Andrew Lamb (andrew.a.lamb@est.tech) + * + */ +public class MonitorSol003AdapterTerminateJobTaskTest extends BaseTest { + + private static final String MONITOR_SOL003_ADAPTER_TERMINATE_JOB_WORKFLOW = "MonitorSol003AdapterTerminateJob"; + + @Autowired + @Qualifier(SOL003_ADAPTER_REST_TEMPLATE_BEAN) + private RestTemplate restTemplate; + + @Autowired + private GsonProvider gsonProvider; + + private MockRestServiceServer mockRestServiceServer; + private Gson gson; + + @Before + public void before() { + wireMockServer.resetAll(); + + final MockRestServiceServer.MockRestServiceServerBuilder builder = MockRestServiceServer.bindTo(restTemplate); + builder.ignoreExpectOrder(true); + mockRestServiceServer = builder.build(); + + gson = gsonProvider.getGson(); + restTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson)); + } + + + @Test + public void testMonitorSol003AdapterTerminateJobTaskWorkflow_SuccessfulCase() throws InterruptedException { + mockRestServiceServer.expect(requestTo(SOL003_ADAPTER_ENDPOINT_URL + "/jobs/" + RANDOM_JOB_ID)) + .andExpect(method(HttpMethod.GET)) + .andRespond(withSuccess(gson.toJson(getQueryJobResponse(COMPLETED)), MediaType.APPLICATION_JSON)); + + final ProcessInstance processInstance = executeWorkflow(MONITOR_SOL003_ADAPTER_TERMINATE_JOB_WORKFLOW, + RANDOM_JOB_ID, getVariables(RANDOM_JOB_ID, new DeleteVnfResponse().jobId(RANDOM_JOB_ID))); + assertTrue(waitForProcessInstanceToFinish(processInstance.getProcessInstanceId())); + + final HistoricProcessInstance historicProcessInstance = + getHistoricProcessInstance(processInstance.getProcessInstanceId()); + assertNotNull(historicProcessInstance); + assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState()); + + final HistoricVariableInstance nsResponseVariable = getVariable(processInstance.getProcessInstanceId(), + CamundaVariableNameConstants.OPERATION_STATUS_PARAM_NAME); + assertNotNull(nsResponseVariable); + assertEquals(COMPLETED, nsResponseVariable.getValue()); + } + + @Test + public void testMonitorSol003AdapterTerminateJobTaskWorkflow_SuccessfulCaseFollowingProcessingDelay() + throws InterruptedException { + mockRestServiceServer.expect(requestTo(SOL003_ADAPTER_ENDPOINT_URL + "/jobs/" + RANDOM_JOB_ID)) + .andExpect(method(HttpMethod.GET)) + .andRespond(withSuccess(gson.toJson(getQueryJobResponse(PROCESSING)), MediaType.APPLICATION_JSON)); + mockRestServiceServer.expect(requestTo(SOL003_ADAPTER_ENDPOINT_URL + "/jobs/" + RANDOM_JOB_ID)) + .andExpect(method(HttpMethod.GET)) + .andRespond(withSuccess(gson.toJson(getQueryJobResponse(PROCESSING)), MediaType.APPLICATION_JSON)); + mockRestServiceServer.expect(requestTo(SOL003_ADAPTER_ENDPOINT_URL + "/jobs/" + RANDOM_JOB_ID)) + .andExpect(method(HttpMethod.GET)) + .andRespond(withSuccess(gson.toJson(getQueryJobResponse(COMPLETED)), MediaType.APPLICATION_JSON)); + + final ProcessInstance processInstance = executeWorkflow(MONITOR_SOL003_ADAPTER_TERMINATE_JOB_WORKFLOW, + RANDOM_JOB_ID, getVariables(RANDOM_JOB_ID, new DeleteVnfResponse().jobId(RANDOM_JOB_ID))); + assertTrue(waitForProcessInstanceToFinish(processInstance.getProcessInstanceId())); + + final HistoricProcessInstance historicProcessInstance = + getHistoricProcessInstance(processInstance.getProcessInstanceId()); + assertNotNull(historicProcessInstance); + assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState()); + + final HistoricVariableInstance nsResponseVariable = getVariable(processInstance.getProcessInstanceId(), + CamundaVariableNameConstants.OPERATION_STATUS_PARAM_NAME); + assertNotNull(nsResponseVariable); + assertEquals(COMPLETED, nsResponseVariable.getValue()); + } + + private QueryJobResponse getQueryJobResponse(final OperationStateEnum operationState) { + return new QueryJobResponse().id(RANDOM_JOB_ID).operationState(operationState) + .operationStatusRetrievalStatus(STATUS_FOUND); + } + + private Map getVariables(final String jobId, final DeleteVnfResponse deleteVnfResponse) { + final Map variables = new HashMap<>(); + variables.put(CamundaVariableNameConstants.JOB_ID_PARAM_NAME, jobId); + variables.put(CamundaVariableNameConstants.DELETE_VNF_RESPONSE_PARAM_NAME, deleteVnfResponse); + + return variables; + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/workflow/engine/tasks/TerminateNsTaskTest.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/workflow/engine/tasks/TerminateNsTaskTest.java new file mode 100644 index 0000000000..14e5b1cafc --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/workflow/engine/tasks/TerminateNsTaskTest.java @@ -0,0 +1,232 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.etsi.nfvo.ns.workflow.engine.tasks; + +import com.google.gson.Gson; +import org.camunda.bpm.engine.history.HistoricProcessInstance; +import org.hamcrest.text.MatchesPattern; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.DeleteVnfResponse; +import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStatusRetrievalStatusEnum; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.BaseTest; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.GsonProvider; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.exceptions.NsRequestProcessingException; +import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.service.JobExecutorService; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJob; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNfInst; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NsLcmOpOcc; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.OperationStateEnum; +import org.onap.so.etsi.nfvo.ns.lcm.database.beans.State; +import org.onap.so.etsi.nfvo.ns.lcm.model.TerminateNsRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.GsonHttpMessageConverter; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.web.client.RestTemplate; +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import static com.github.tomakehurst.wiremock.client.WireMock.delete; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.ok; +import static com.github.tomakehurst.wiremock.client.WireMock.okJson; +import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog.EtsiCatalogServiceProviderConfiguration.ETSI_CATALOG_REST_TEMPLATE_BEAN; +import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.vnfm.Sol003AdapterConfiguration.SOL003_ADAPTER_REST_TEMPLATE_BEAN; +import static org.springframework.test.web.client.ExpectedCount.times; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +/** + * @author Andrew Lamb (andrew.a.lamb@est.tech) + * + */ +public class TerminateNsTaskTest extends BaseTest { + + @Autowired + @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN) + private RestTemplate etsiCatalogRestTemplate; + + @Autowired + @Qualifier(SOL003_ADAPTER_REST_TEMPLATE_BEAN) + private RestTemplate sol003AdapterRestTemplate; + + private MockRestServiceServer mockEtsiCatalogRestServiceServer; + + private MockRestServiceServer mockSol003AdapterRestServiceServer; + + @Autowired + private JobExecutorService objUnderTest; + + @Autowired + private GsonProvider gsonProvider; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private Gson gson; + + @Before + public void before() { + wireMockServer.resetAll(); + gson = gsonProvider.getGson(); + + mockEtsiCatalogRestServiceServer = + MockRestServiceServer.bindTo(etsiCatalogRestTemplate).ignoreExpectOrder(true).build(); + mockSol003AdapterRestServiceServer = + MockRestServiceServer.bindTo(sol003AdapterRestTemplate).ignoreExpectOrder(true).build(); + + etsiCatalogRestTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson)); + sol003AdapterRestTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson)); + + } + + @After + public void after() { + wireMockServer.resetAll(); + mockEtsiCatalogRestServiceServer.reset(); + } + + @Test + public void testRunTerminateNsJob_timeSetInTerminateRequest_throwsNsRequestProcessingException() { + final String nsInstanceId = UUID.randomUUID().toString(); + final TerminateNsRequest terminateNsRequest = new TerminateNsRequest().terminationTime(LocalDateTime.now()); + final String message = "TerminateNsRequest received with terminateTime: " + + terminateNsRequest.getTerminationTime() + + "\nOnly immediate Terminate requests are currently supported \n(i.e., terminateTime field must not be set)."; + expectedException.expect(NsRequestProcessingException.class); + expectedException.expectMessage(message); + objUnderTest.runTerminateNsJob(nsInstanceId, terminateNsRequest); + } + + @Test + public void testRunTerminateNsJob_NsInstNotInDb_throwsNsRequestProcessingException() { + final String nsInstanceId = UUID.randomUUID().toString(); + final TerminateNsRequest terminateNsRequest = new TerminateNsRequest(); + final String message = "No matching NS Instance for id: " + nsInstanceId + " found in database."; + assertThat(databaseServiceProvider.getNfvoNsInst(nsInstanceId)).isEmpty(); + expectedException.expect(NsRequestProcessingException.class); + expectedException.expectMessage(message); + objUnderTest.runTerminateNsJob(nsInstanceId, terminateNsRequest); + } + + @Test + public void testTerminateNsTask_SuccessfulCase() throws InterruptedException, IOException { + final String nsInstanceId = UUID.randomUUID().toString(); + addDummyNsToDatabase(nsInstanceId); + mockSol003AdapterEndpoints(); + mockAAIEndpoints(); + + final String nsLcmOpOccId = objUnderTest.runTerminateNsJob(nsInstanceId, new TerminateNsRequest()); + + final Optional optional = getJobByResourceId(nsInstanceId); + assertTrue(optional.isPresent()); + final NfvoJob nfvoJob = optional.get(); + + // Confirm Process finishes in STATE_COMPLETED + assertTrue(waitForProcessInstanceToFinish(nfvoJob.getProcessInstanceId())); + final HistoricProcessInstance historicProcessInstance = + getHistoricProcessInstance(nfvoJob.getProcessInstanceId()); + assertNotNull(historicProcessInstance); + assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState()); + + // Confirm NS Instance set to NOT_INSTANTIATED and related NF Instances Deleted + final Optional optionalNfvoNsInst = databaseServiceProvider.getNfvoNsInst(nsInstanceId); + assertTrue(optionalNfvoNsInst.isPresent()); + final NfvoNsInst nfvoNsInst = optionalNfvoNsInst.get(); + assertEquals(State.NOT_INSTANTIATED, nfvoNsInst.getStatus()); + final List nfvoNfInsts = databaseServiceProvider.getNfvoNfInstByNsInstId(nsInstanceId); + assertTrue(nfvoNfInsts.isEmpty()); + + // Confirm NS LCM OP OCC Job set to Completed + final Optional optionalNsLcmOpOcc = databaseServiceProvider.getNsLcmOpOcc(nsLcmOpOccId); + assertTrue(optionalNsLcmOpOcc.isPresent()); + final NsLcmOpOcc nsLcmOpOcc = optionalNsLcmOpOcc.get(); + assertEquals(OperationStateEnum.COMPLETED, nsLcmOpOcc.getOperationState()); + } + + private void addDummyNsToDatabase(final String nsInstanceId) { + final String nsPackageId = UUID.randomUUID().toString(); + final NfvoNsInst nfvoNsInst = + new NfvoNsInst().nsInstId(nsInstanceId).name("nsName").nsPackageId(nsPackageId).nsdId("nsdId") + .nsdInvariantId("nsdId").status(State.INSTANTIATED).statusUpdatedTime(LocalDateTime.now()); + databaseServiceProvider.saveNfvoNsInst(nfvoNsInst); + addDummyNfToDatabase(nfvoNsInst); + addDummyNfToDatabase(nfvoNsInst); + addDummyNfToDatabase(nfvoNsInst); + } + + private void addDummyNfToDatabase(final NfvoNsInst nfvoNsInst) { + final LocalDateTime localDateTime = LocalDateTime.now(); + final String nfPackageId = UUID.randomUUID().toString(); + final NfvoNfInst nfvoNfInst = + new NfvoNfInst().status(State.INSTANTIATED).createTime(localDateTime).lastUpdateTime(localDateTime) + .name("nfName").vnfdId("vnfdId").packageId(nfPackageId).nfvoNsInst(nfvoNsInst); + databaseServiceProvider.saveNfvoNfInst(nfvoNfInst); + } + + private void mockSol003AdapterEndpoints() { + final int numTimes = 3; + + mockSol003AdapterRestServiceServer + .expect(times(numTimes), + requestTo(MatchesPattern.matchesPattern(SOL003_ADAPTER_ENDPOINT_URL + "/vnfs/.*"))) + .andExpect(method(HttpMethod.DELETE)) + .andRespond(withSuccess(gson.toJson(new DeleteVnfResponse().jobId(UUID.randomUUID().toString())), + MediaType.APPLICATION_JSON)); + + mockSol003AdapterRestServiceServer + .expect(times(numTimes), + requestTo(MatchesPattern.matchesPattern(SOL003_ADAPTER_ENDPOINT_URL + "/jobs/.*"))) + .andExpect(method(HttpMethod.GET)) + .andRespond(withSuccess(gson.toJson( + new org.onap.so.adapters.etsisol003adapter.lcm.v1.model.QueryJobResponse().operationState( + org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStateEnum.COMPLETED) + .operationStatusRetrievalStatus(OperationStatusRetrievalStatusEnum.STATUS_FOUND)), + MediaType.APPLICATION_JSON)); + } + + private void mockAAIEndpoints() { + final String modelEndpoint = "/aai/v[0-9]+/network/generic-vnfs/generic-vnf/" + UUID_REGEX; + final String resourceVersion = "12345"; + + final String body = + "{\"resource-version\": \"" + resourceVersion + "\",\n\"orchestration-status\": \"Assigned\"}"; + wireMockServer.stubFor(get(urlMatching(modelEndpoint)).willReturn(ok()).willReturn(okJson(body))); + + wireMockServer.stubFor( + delete(urlMatching(modelEndpoint + "\\?resource-version=" + resourceVersion)).willReturn(ok())); + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/NsLcmOpOcc.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/NsLcmOpOcc.java index cb8f92070a..c47bbdbefb 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/NsLcmOpOcc.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/NsLcmOpOcc.java @@ -216,7 +216,7 @@ public class NsLcmOpOcc { @Override public String toString() { final StringBuilder sb = new StringBuilder(); - sb.append("class NfvoNsInst {\n"); + sb.append("class NsLcmOpOcc {\n"); sb.append(" id: ").append(toIndentedString(id)).append("\n"); sb.append(" operationState: ").append(toIndentedString(operationState)).append("\n"); sb.append(" stateEnteredTime: ").append(toIndentedString(stateEnteredTime)).append("\n"); diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/State.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/State.java index 390c7fd776..ce917dd771 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/State.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/beans/State.java @@ -24,6 +24,6 @@ package org.onap.so.etsi.nfvo.ns.lcm.database.beans; * */ public enum State { - NOT_INSTANTIATED, INSTANTIATING, INSTANTIATED, FAILED; + NOT_INSTANTIATED, INSTANTIATING, INSTANTIATED, FAILED, TERMINATING; } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/service/DatabaseServiceProvider.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/service/DatabaseServiceProvider.java index 368242515b..762408a089 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/service/DatabaseServiceProvider.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-database-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/database/service/DatabaseServiceProvider.java @@ -127,6 +127,16 @@ public class DatabaseServiceProvider { return nfvoNfInstRepository.findByNfInstId(nfInstId); } + public boolean isNfInstExists(final String nfInstId) { + logger.info("Checking if NfvoNfInst entry exists in database using nfInstId: {}", nfInstId); + return nfvoNfInstRepository.findByNfInstId(nfInstId).isPresent(); + } + + public void deleteNfvoNfInst(final String nfInstId) { + logger.info("Deleting NfvoNfInst with nfInstId: {} from database", nfInstId); + nfvoNfInstRepository.deleteById(nfInstId); + } + public boolean addNSLcmOpOcc(final NsLcmOpOcc nsLcmOpOcc) { logger.info("Adding NSLcmOpOcc: {} to database", nsLcmOpOcc); return nsLcmOpOccRepository.save(nsLcmOpOcc) != null; diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/EtsiSoNsLcmManagerUrlProvider.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/EtsiSoNsLcmManagerUrlProvider.java index da1649de57..80ec60468f 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/EtsiSoNsLcmManagerUrlProvider.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/EtsiSoNsLcmManagerUrlProvider.java @@ -45,7 +45,7 @@ public class EtsiSoNsLcmManagerUrlProvider { + nsInstanceId); } - public URI getInstantiatedOccUri(final String nsLcmOpOccId) { + public URI getNsLcmOpOccUri(final String nsLcmOpOccId) { return URI.create(etsiNsLcmManagerEndpoint + Constants.NS_LIFE_CYCLE_MANAGEMENT_BASE_URL + "/ns_lcm_op_occs/" + nsLcmOpOccId); } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/lifecycle/NsLifeCycleManager.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/lifecycle/NsLifeCycleManager.java index 792ffdd00a..2ebf55ff7f 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/lifecycle/NsLifeCycleManager.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/lifecycle/NsLifeCycleManager.java @@ -27,6 +27,7 @@ import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.service.JobExecutorService; import org.onap.so.etsi.nfvo.ns.lcm.model.CreateNsRequest; import org.onap.so.etsi.nfvo.ns.lcm.model.InstantiateNsRequest; import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesNsInstance; +import org.onap.so.etsi.nfvo.ns.lcm.model.TerminateNsRequest; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -70,8 +71,15 @@ public class NsLifeCycleManager { instantiateNsRequest, nsInstanceId); final String nsLcmOpOccId = jobExecutorService.runInstantiateNsJob(nsInstanceId, instantiateNsRequest); - return etsiSoNsLcmManagerUrlProvider.getInstantiatedOccUri(nsLcmOpOccId); + return etsiSoNsLcmManagerUrlProvider.getNsLcmOpOccUri(nsLcmOpOccId); } + public URI terminateNs(final String nsInstanceId, final TerminateNsRequest terminateNsRequest) { + logger.info("Will execute Terminate Ns for TerminateNsRequest: {} and nsInstanceId: {}", terminateNsRequest, + nsInstanceId); + final String nsLcmOpOccId = jobExecutorService.runTerminateNsJob(nsInstanceId, terminateNsRequest); + + return etsiSoNsLcmManagerUrlProvider.getNsLcmOpOccUri(nsLcmOpOccId); + } } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/rest/NsLifecycleManagementController.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/rest/NsLifecycleManagementController.java index 87ec8420c6..cfda89f3f0 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/rest/NsLifecycleManagementController.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/rest/NsLifecycleManagementController.java @@ -72,8 +72,9 @@ public class NsLifecycleManagementController { * @param globalCustomerId The global customer ID * @param serviceType The service type * @param createNsRequest create network service request (see clause 6.5.2.9) - * @return "201 Created" response containing a representation of the NS instance resource {@link NsInstance} just - * created by the NFVO, and provides the URI of the newly-created resource in the "Location:" HTTP header + * @return "201 Created" response containing a representation of the NS instance resource + * {@link NsInstancesNsInstance} just created by the NFVO, and provides the URI of the newly-created + * resource in the "Location:" HTTP header */ @PostMapping(value = "/ns_instances", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}, consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) @@ -145,7 +146,10 @@ public class NsLifecycleManagementController { public ResponseEntity terminateNs(@PathVariable("nsInstanceId") final String nsInstanceId, @RequestBody final TerminateNsRequest terminateNsRequest) { logger.debug("Received terminate NS request: {}\n with nsInstanceId: {}", terminateNsRequest, nsInstanceId); - return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).body("Operation is not supported yet"); + final URI resourceUri = nsLifeCycleManager.terminateNs(nsInstanceId, terminateNsRequest); + logger.info("{} Ns Terminate started successfully. Resource Operation Occurrence uri: {}", nsInstanceId, + resourceUri); + return ResponseEntity.accepted().location(resourceUri).build(); } } diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/rest/NsLifecycleManagementControllerTest.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/rest/NsLifecycleManagementControllerTest.java index 81c4e8fd68..4b1195244c 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/rest/NsLifecycleManagementControllerTest.java +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-service/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/rest/NsLifecycleManagementControllerTest.java @@ -77,7 +77,7 @@ public class NsLifecycleManagementControllerTest { private static final String GLOBAL_CUSTOMER_ID = UUID.randomUUID().toString(); private static final String EXPECTED_CREATE_REQ_LOCATION_URL = EXPECTED_BASE_URL + "/ns_instances/" + RANDOM_NS_INST_ID; - private static final String EXPECTED_INSTANTIATE_REQ_LOCATION_URL = + private static final String EXPECTED_NS_LCM_OP_OCC_REQ_LOCATION_URL = EXPECTED_BASE_URL + "/ns_lcm_op_occs/" + RANDOM_NS_LCM_OP_OCC_ID; @LocalServerPort @@ -197,7 +197,7 @@ public class NsLifecycleManagementControllerTest { assertTrue(httpHeaders.containsKey(HttpHeaders.LOCATION)); final List actual = httpHeaders.get(HttpHeaders.LOCATION); assertEquals(1, actual.size()); - assertEquals(EXPECTED_INSTANTIATE_REQ_LOCATION_URL, actual.get(0)); + assertEquals(EXPECTED_NS_LCM_OP_OCC_REQ_LOCATION_URL, actual.get(0)); } @Test @@ -218,17 +218,43 @@ public class NsLifecycleManagementControllerTest { } @Test - public void testTerminateNs_ValidInstantiateNsRequest() { - final String baseUrl = getNsLcmBaseUrl() + "/ns_instances/" + UUID.randomUUID().toString() + "/terminate"; - final HttpEntity request = new HttpEntity<>(getTerminateNsRequest()); + public void testTerminateNs_ValidTerminateNsRequest_Success() { + final TerminateNsRequest terminateNsRequest = getTerminateNsRequest(); + when(mockedJobExecutorService.runTerminateNsJob(eq(RANDOM_NS_INST_ID), eq(terminateNsRequest))) + .thenReturn(RANDOM_NS_LCM_OP_OCC_ID); + + final String baseUrl = getNsLcmBaseUrl() + "/ns_instances/" + RANDOM_NS_INST_ID + "/terminate"; + final HttpEntity request = new HttpEntity<>(terminateNsRequest); final ResponseEntity responseEntity = testRestTemplate.exchange(baseUrl, HttpMethod.POST, request, Void.class); - assertEquals(HttpStatus.NOT_IMPLEMENTED, responseEntity.getStatusCode()); + assertEquals(HttpStatus.ACCEPTED, responseEntity.getStatusCode()); + + final HttpHeaders httpHeaders = responseEntity.getHeaders(); + assertTrue(httpHeaders.containsKey(HttpHeaders.LOCATION)); + final List actual = httpHeaders.get(HttpHeaders.LOCATION); + assertEquals(1, actual.size()); + assertEquals(EXPECTED_NS_LCM_OP_OCC_REQ_LOCATION_URL, actual.get(0)); } + @Test + public void testTerminateNs_ValidTerminateNsRequest_nsRequestProcessingExceptionThrown_returnInlineResponse400() { + final String errorMessage = "ERROR MESSAGE"; + final TerminateNsRequest terminateNsRequest = getTerminateNsRequest(); + when(mockedJobExecutorService.runTerminateNsJob(eq(RANDOM_NS_INST_ID), eq(terminateNsRequest))) + .thenThrow(new NsRequestProcessingException(errorMessage)); + + final String baseUrl = getNsLcmBaseUrl() + "/ns_instances/" + RANDOM_NS_INST_ID + "/terminate"; + final HttpEntity request = new HttpEntity<>(terminateNsRequest); + final ResponseEntity responseEntity = + testRestTemplate.exchange(baseUrl, HttpMethod.POST, request, InlineResponse400.class); + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode()); + assertTrue(responseEntity.hasBody()); + assertNotNull(responseEntity.getBody()); + } private TerminateNsRequest getTerminateNsRequest() { - return new TerminateNsRequest().terminationTime(LocalDateTime.now()); + // Only support for the immediate Terminate request; i.e., terminateTime field is empty (not set) + return new TerminateNsRequest(); } private InstantiateNsRequest getInstantiateNsRequest() { -- cgit 1.2.3-korg