From fbf6300274558ffe323bf66bb5b23c72c350d3ee Mon Sep 17 00:00:00 2001 From: MichaelMorris Date: Thu, 3 Oct 2019 17:45:05 +0100 Subject: Improved error handling Change-Id: Iac436f6a950bf61ac6321ef1d427a7bb14774e30 Issue-ID: SO-2395 Signed-off-by: MichaelMorris --- .../extclients/vnfm/VnfmServiceProviderImpl.java | 15 ++++ .../vnfmadapter/jobmanagement/JobManager.java | 9 +- .../vnfmadapter/lifecycle/LifecycleManager.java | 28 +++++++ .../notificationhandling/NotificationHandler.java | 97 +++++++++++++++------- .../rest/VnfmAdapterControllerTest.java | 35 ++++++++ 5 files changed, 155 insertions(+), 29 deletions(-) (limited to 'adapters') diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmServiceProviderImpl.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmServiceProviderImpl.java index 948f5fc269..3bdba368b2 100644 --- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmServiceProviderImpl.java +++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmServiceProviderImpl.java @@ -26,10 +26,13 @@ import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.CreateVnfRequest; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse200; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse2001; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse201; +import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse201.InstantiationStateEnum; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InstantiateVnfRequest; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.LccnSubscriptionRequest; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.TerminateVnfRequest; +import org.onap.so.adapters.vnfmadapter.jobmanagement.JobManager; import org.onap.so.adapters.vnfmadapter.rest.exceptions.VnfmRequestFailureException; +import org.onap.so.rest.exceptions.RestProcessingException; import org.onap.so.rest.service.HttpRestServiceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -115,6 +118,18 @@ public class VnfmServiceProviderImpl implements VnfmServiceProvider { try { response = getHttpServiceProvider(vnfm).postHttpRequest(terminateVnfRequest, vnfSelfLink + "/terminate", Void.class); + } catch (final RestProcessingException restProcessingException) { + if (restProcessingException.getStatusCode() == HttpStatus.CONFLICT.value()) { + InlineResponse201 vnf = getVnf(vnfm, vnfSelfLink).get(); + if (vnf.getInstantiationState().equals(InstantiationStateEnum.NOT_INSTANTIATED)) { + return JobManager.ALREADY_COMPLETED_OPERATION_ID; + } else { + final String errorMessage = + "Terminate request to " + vnfSelfLink + " resulted in exception" + terminateVnfRequest; + logger.error(errorMessage, restProcessingException); + throw new VnfmRequestFailureException(errorMessage, restProcessingException); + } + } } catch (final Exception exception) { final String errorMessage = "Terminate request to " + vnfSelfLink + " resulted in exception" + terminateVnfRequest; diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/jobmanagement/JobManager.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/jobmanagement/JobManager.java index 68fdb79444..3de94ebe05 100644 --- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/jobmanagement/JobManager.java +++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/jobmanagement/JobManager.java @@ -29,6 +29,7 @@ import org.onap.so.adapters.vnfmadapter.extclients.aai.AaiServiceProvider; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.VnfmServiceProvider; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse200; import org.onap.so.adapters.vnfmadapter.rest.exceptions.JobNotFoundException; +import org.onap.so.rest.exceptions.HttpResouceNotFoundException; import org.onap.vnfmadapter.v1.model.OperationEnum; import org.onap.vnfmadapter.v1.model.OperationStateEnum; import org.onap.vnfmadapter.v1.model.OperationStatusRetrievalStatusEnum; @@ -42,6 +43,7 @@ import org.springframework.stereotype.Component; */ @Component public class JobManager { + public static final String ALREADY_COMPLETED_OPERATION_ID = "alreadyCompleted"; private static final String SEPARATOR = "_"; private static Logger logger = getLogger(JobManager.class); private final Map mapOfJobIdToVnfmOperation = Maps.newConcurrentMap(); @@ -87,6 +89,11 @@ public class JobManager { throw new JobNotFoundException("No job found with ID: " + jobId); } + if (vnfmOperation.getOperationId().equals(ALREADY_COMPLETED_OPERATION_ID)) { + response.setOperationStatusRetrievalStatus(OperationStatusRetrievalStatusEnum.STATUS_FOUND); + return response.operationState(OperationStateEnum.COMPLETED); + } + if (vnfmOperation.isVnfDeleted()) { response.setOperationStatusRetrievalStatus(OperationStatusRetrievalStatusEnum.STATUS_FOUND); return response.operationState(getOperationState(vnfmOperation, null)); @@ -116,7 +123,7 @@ public class JobManager { response.setVnfInstanceId(operation.getVnfInstanceId()); return response; - } catch (final Exception exception) { + } catch (final HttpResouceNotFoundException exception) { logger.error("Exception encountered trying to get operation status for operation id " + vnfmOperation.getOperationId(), exception); return response.operationStatusRetrievalStatus(OperationStatusRetrievalStatusEnum.WAITING_FOR_STATUS); diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/lifecycle/LifecycleManager.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/lifecycle/LifecycleManager.java index 461c15a512..a885721b76 100644 --- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/lifecycle/LifecycleManager.java +++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/lifecycle/LifecycleManager.java @@ -24,6 +24,7 @@ import com.google.common.base.Optional; import java.util.Map; import org.onap.aai.domain.yang.EsrVnfm; import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.Relationship; import org.onap.so.adapters.vnfmadapter.extclients.SdcPackageProvider; import org.onap.so.adapters.vnfmadapter.extclients.aai.AaiHelper; import org.onap.so.adapters.vnfmadapter.extclients.aai.AaiServiceProvider; @@ -207,6 +208,10 @@ public class LifecycleManager { final EsrVnfm vnfm = getAssignedVnfm(genericVnf); final String operationId = sendTerminateRequestToVnfm(vnfm, genericVnf); + + if (operationId.equals(JobManager.ALREADY_COMPLETED_OPERATION_ID)) { + sendDeleteRequestToVnfm(genericVnf); + } final String jobId = jobManager.createJob(vnfm.getVnfmId(), operationId, true); return new DeleteVnfResponse().jobId(jobId); @@ -234,4 +239,27 @@ public class LifecycleManager { } return vnfm; } + + private void sendDeleteRequestToVnfm(final GenericVnf genericVnf) { + + vnfmServiceProvider.deleteVnf(aaiHelper.getAssignedVnfm(genericVnf), genericVnf.getSelflink()); + + final GenericVnf genericVnfPatch = new GenericVnf(); + genericVnfPatch.setVnfId(genericVnf.getVnfId()); + genericVnfPatch.setOrchestrationStatus("Assigned"); + genericVnfPatch.setSelflink(""); + aaiServiceProvider.invokePatchGenericVnf(genericVnfPatch); + + for (final Relationship relationship : genericVnf.getRelationshipList().getRelationship()) { + if (relationship.getRelatedTo().equals("vserver")) { + aaiServiceProvider.invokeDeleteVserver( + aaiHelper.getRelationshipData(relationship, "cloud-region.cloud-owner"), + aaiHelper.getRelationshipData(relationship, "cloud-region.cloud-region-id"), + aaiHelper.getRelationshipData(relationship, "tenant.tenant-id"), + aaiHelper.getRelationshipData(relationship, "vserver.vserver-id")); + } + } + + + } } diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/notificationhandling/NotificationHandler.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/notificationhandling/NotificationHandler.java index 7a6bbfe0d9..63ec4ccc57 100644 --- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/notificationhandling/NotificationHandler.java +++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/notificationhandling/NotificationHandler.java @@ -145,31 +145,31 @@ public class NotificationHandler implements Runnable { } private void handleVnfTerminateFailed() { - final GenericVnf genericVnf = aaiServiceProvider - .invokeQueryGenericVnf(vnfInstance.getLinks().getSelf().getHref()).getGenericVnf().get(0); - deleteVservers(vnfLcmOperationOccurrenceNotification, genericVnf); - jobManager.notificationProcessedForOperation(vnfLcmOperationOccurrenceNotification.getVnfLcmOpOccId(), false); + try { + final GenericVnf genericVnf = aaiServiceProvider + .invokeQueryGenericVnf(vnfInstance.getLinks().getSelf().getHref()).getGenericVnf().get(0); + deleteVserversFromAai(vnfLcmOperationOccurrenceNotification, genericVnf); + } finally { + jobManager.notificationProcessedForOperation(vnfLcmOperationOccurrenceNotification.getVnfLcmOpOccId(), + false); + } } private void handleVnfTerminateCompleted() { - final GenericVnf genericVnf = aaiServiceProvider - .invokeQueryGenericVnf(vnfInstance.getLinks().getSelf().getHref()).getGenericVnf().get(0); - deleteVservers(vnfLcmOperationOccurrenceNotification, genericVnf); - - boolean deleteSuccessful = false; + GenericVnf genericVnf = null; + boolean vServersDeletedFromAai = false; + boolean identifierDeletedFromVnfm = false; + boolean genericVnfUpdated = false; try { - vnfmServiceProvider.deleteVnf(aaiHelper.getAssignedVnfm(genericVnf), genericVnf.getSelflink()); - deleteSuccessful = true; + genericVnf = aaiServiceProvider.invokeQueryGenericVnf(vnfInstance.getLinks().getSelf().getHref()) + .getGenericVnf().get(0); + vServersDeletedFromAai = deleteVserversFromAai(vnfLcmOperationOccurrenceNotification, genericVnf); + identifierDeletedFromVnfm = deleteVnfIdentifierOnVnfm(genericVnf); + genericVnfUpdated = patchVnfInAai(genericVnf.getVnfId(), "Assigned", identifierDeletedFromVnfm ? "" : null); } finally { jobManager.notificationProcessedForOperation(vnfLcmOperationOccurrenceNotification.getVnfLcmOpOccId(), - deleteSuccessful); + vServersDeletedFromAai && identifierDeletedFromVnfm && genericVnfUpdated); jobManager.vnfDeleted(vnfLcmOperationOccurrenceNotification.getVnfLcmOpOccId()); - - final GenericVnf genericVnfPatch = new GenericVnf(); - genericVnfPatch.setVnfId(genericVnf.getVnfId()); - genericVnfPatch.setOrchestrationStatus("Assigned"); - genericVnfPatch.setSelflink(""); - aaiServiceProvider.invokePatchGenericVnf(genericVnfPatch); } } @@ -194,19 +194,60 @@ public class NotificationHandler implements Runnable { } } - private void deleteVservers(final VnfLcmOperationOccurrenceNotification notification, final GenericVnf vnf) { - for (final LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs vnfc : notification.getAffectedVnfcs()) { - if (ChangeTypeEnum.REMOVED.equals(vnfc.getChangeType())) { + private boolean deleteVserversFromAai(final VnfLcmOperationOccurrenceNotification notification, + final GenericVnf vnf) { + try { + for (final LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs vnfc : notification.getAffectedVnfcs()) { + if (ChangeTypeEnum.REMOVED.equals(vnfc.getChangeType())) { - final Relationship relationshipToVserver = aaiHelper.deleteRelationshipWithDataValue(vnf, "vserver", - "vserver.vserver-id", vnfc.getComputeResource().getResourceId()); + final Relationship relationshipToVserver = aaiHelper.deleteRelationshipWithDataValue(vnf, "vserver", + "vserver.vserver-id", vnfc.getComputeResource().getResourceId()); - aaiServiceProvider.invokeDeleteVserver( - aaiHelper.getRelationshipData(relationshipToVserver, "cloud-region.cloud-owner"), - aaiHelper.getRelationshipData(relationshipToVserver, "cloud-region.cloud-region-id"), - aaiHelper.getRelationshipData(relationshipToVserver, "tenant.tenant-id"), - vnfc.getComputeResource().getResourceId()); + aaiServiceProvider.invokeDeleteVserver( + aaiHelper.getRelationshipData(relationshipToVserver, "cloud-region.cloud-owner"), + aaiHelper.getRelationshipData(relationshipToVserver, "cloud-region.cloud-region-id"), + aaiHelper.getRelationshipData(relationshipToVserver, "tenant.tenant-id"), + vnfc.getComputeResource().getResourceId()); + } } + return true; + } catch (final Exception exception) { + logger.error( + "Error encountered deleting vservers based on received notification, AAI may not be updated correctly " + + vnfLcmOperationOccurrenceNotification, + exception); + return false; + } + } + + private boolean deleteVnfIdentifierOnVnfm(GenericVnf genericVnf) { + try { + vnfmServiceProvider.deleteVnf(aaiHelper.getAssignedVnfm(genericVnf), genericVnf.getSelflink()); + return true; + } catch (Exception exception) { + logger.error("Exception deleting the identifier " + genericVnf.getSelflink() + + " from the VNFM. The VNF has been terminated successfully but the identifier will remain on the VNFM.", + exception); + return false; + } + } + + private boolean patchVnfInAai(final String vnfId, final String orchestrationStatus, final String selfLink) { + try { + final GenericVnf genericVnfPatch = new GenericVnf(); + genericVnfPatch.setVnfId(vnfId); + genericVnfPatch.setOrchestrationStatus(orchestrationStatus); + if (selfLink != null) { + genericVnfPatch.setSelflink(selfLink); + } + aaiServiceProvider.invokePatchGenericVnf(genericVnfPatch); + return true; + } catch (final Exception exception) { + logger.error( + "Error encountered setting orchestration status and/or self link based on received notification, AAI may not be updated correctly " + + vnfLcmOperationOccurrenceNotification, + exception); + return false; } } diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/VnfmAdapterControllerTest.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/VnfmAdapterControllerTest.java index 297f74433e..6cdb93a25d 100644 --- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/VnfmAdapterControllerTest.java +++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/VnfmAdapterControllerTest.java @@ -57,6 +57,7 @@ import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.JSON; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse200; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse2001; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse201; +import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse201.InstantiationStateEnum; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse201Links; import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse201LinksSelf; import org.onap.so.adapters.vnfmadapter.rest.exceptions.VnfmNotFoundException; @@ -321,6 +322,40 @@ public class VnfmAdapterControllerTest { assertEquals(JAN_1_2019_1_00, secondJobQueryResponse.getBody().getStateEnteredTime()); } + @Test + public void deleteVnf_VnfAlreadyTerminated_Returns202AndJobId() throws Exception { + final TestRestTemplate restTemplate = new TestRestTemplate("test", "test"); + + final GenericVnf genericVnf = setUpGenericVnfInMockAai("vnfmType1"); + addSelfLinkToGenericVnf(genericVnf); + addRelationshipFromGenericVnfToVnfm(genericVnf, "vnfm1"); + setUpVnfmsInMockAai(); + + mockRestServer.expect(requestTo("http://vnfm:8080/vnfs/myTestVnfIdOnVnfm/terminate")) + .andRespond(withStatus(HttpStatus.CONFLICT).contentType(MediaType.APPLICATION_JSON)); + + final InlineResponse201 reponse = new InlineResponse201(); + reponse.setInstantiationState(InstantiationStateEnum.NOT_INSTANTIATED); + mockRestServer.expect(requestTo(new URI("http://vnfm:8080/vnfs/myTestVnfIdOnVnfm"))) + .andRespond(withSuccess(gson.toJson(reponse), MediaType.APPLICATION_JSON)); + + mockRestServer.expect(requestTo("http://vnfm:8080/vnfs/myTestVnfIdOnVnfm")) + .andRespond(withStatus(HttpStatus.NO_CONTENT).contentType(MediaType.APPLICATION_JSON)); + + final RequestEntity request = RequestEntity + .delete(new URI("http://localhost:" + port + "/so/vnfm-adapter/v1/vnfs/myTestVnfId")) + .accept(MediaType.APPLICATION_JSON).header("X-ONAP-RequestId", "myRequestId") + .header("X-ONAP-InvocationID", "myInvocationId").header("Content-Type", "application/json").build(); + final ResponseEntity deleteVnfResponse = + restTemplate.exchange(request, DeleteVnfResponse.class); + assertEquals(202, deleteVnfResponse.getStatusCode().value()); + assertNotNull(deleteVnfResponse.getBody().getJobId()); + + final ResponseEntity jobQueryResponse = + controller.jobQuery(deleteVnfResponse.getBody().getJobId(), "", "so", "1213"); + assertEquals(OperationStateEnum.COMPLETED, jobQueryResponse.getBody().getOperationState()); + } + @Test public void deleteVnf_GenericVnfNotFound_Returns404() throws Exception { final TestRestTemplate restTemplate = new TestRestTemplate("test", "test"); -- cgit 1.2.3-korg