Notification handling for terminate 85/84385/1
authorMichaelMorris <michael.morris@est.tech>
Fri, 5 Apr 2019 18:46:44 +0000 (18:46 +0000)
committerMichaelMorris <michael.morris@est.tech>
Fri, 5 Apr 2019 18:46:44 +0000 (18:46 +0000)
Issue-ID: SO-1634
Change-Id: Idd5e06554cb7714d9107042cd4f7426cdf764cef
Signed-off-by: MichaelMorris <michael.morris@est.tech>
adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/aai/AaiServiceProvider.java
adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/aai/AaiServiceProviderImpl.java
adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmServiceProvider.java
adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/vnfm/VnfmServiceProviderImpl.java
adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/jobmanagement/JobManager.java
adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/jobmanagement/VnfmOperation.java
adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/notificationhandling/NotificationHandler.java
adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003LcnContoller.java
adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003LcnControllerTest.java

index a043bb8..b3767a3 100644 (file)
@@ -91,6 +91,18 @@ public interface AaiServiceProvider {
     void invokePutVserver(final String cloudOwner, final String cloudRegion, final String tenantId,
             final Vserver vserver);
 
+    /**
+     * Invoke a DELETE request for a vserver.
+     *
+     * @param cloudOwner the cloud owner
+     * @param cloudRegion the cloud region
+     * @param tenantId the ID of the tenant
+     * @param vserver the ID of the vserver
+     * @return
+     */
+    void invokeDeleteVserver(final String cloudOwner, final String cloudRegion, final String tenantId,
+            final String vserverId);
+
     /**
      * Invoke a GET request for the a tenant.
      *
index 364a641..6c3d7c2 100644 (file)
@@ -108,6 +108,13 @@ public class AaiServiceProviderImpl implements AaiServiceProvider {
                 cloudRegion, tenant, vserver.getVserverId()), vserver);
     }
 
+    @Override
+    public void invokeDeleteVserver(final String cloudOwner, final String cloudRegion, final String tenant,
+            final String vserverId) {
+        aaiClientProvider.getAaiClient().delete(
+                AAIUriFactory.createResourceUri(AAIObjectType.VSERVER, cloudOwner, cloudRegion, tenant, vserverId));
+    }
+
     @Override
     public Tenant invokeGetTenant(final String cloudOwner, final String cloudRegion, final String tenantId) {
         return aaiClientProvider.getAaiClient()
index 8af6889..320715d 100644 (file)
@@ -57,6 +57,14 @@ public interface VnfmServiceProvider {
      */
     String terminateVnf(final String vnfSelfLink, final TerminateVnfRequest terminateVnfRequest);
 
+    /**
+     * Invoke a delete request for a VNF.
+     *
+     * @param vnfSelfLink the link to he VNF on the VNFM
+     * @return the operation ID of the instantiation operation
+     */
+    void deleteVnf(final String vnfSelfLink);
+
     /**
      * Invoke a get request for a VNFM operation.
      *
index d447bef..246444f 100644 (file)
@@ -103,6 +103,17 @@ public class VnfmServiceProviderImpl implements VnfmServiceProvider {
 
     }
 
+    @Override
+    public void deleteVnf(final String vnfSelfLink) {
+        logger.debug("Sending delete request to : " + vnfSelfLink);
+        final ResponseEntity<Void> response = httpServiceProvider.deleteHttpRequest(vnfSelfLink, Void.class);
+        if (response.getStatusCode() != HttpStatus.OK) {
+            throw new VnfmRequestFailureException(
+                    "Delete request to " + vnfSelfLink + " return status code: " + response.getStatusCode());
+        }
+    }
+
+
     @Override
     public Optional<InlineResponse200> getOperation(final String vnfmId, final String operationId) {
         final String url = urlProvider.getOperationUrl(vnfmId, operationId);
index 97a945c..89356c1 100644 (file)
@@ -110,11 +110,27 @@ public class JobManager {
             final InlineResponse200 operationResponse) {
         final OperationStateEnum operationState =
                 OperationStateEnum.fromValue(operationResponse.getOperationState().getValue());
-        if (operationState == OperationStateEnum.COMPLETED && vnfmOperation.isWaitForNotificationForSuccess()
-                && !vnfmOperation.isNotificationProcessed()) {
-            return org.onap.vnfmadapter.v1.model.OperationStateEnum.PROCESSING;
+        switch (vnfmOperation.getNotificationStatus()) {
+            case NOTIFICATION_PROCESSING_NOT_REQUIRED:
+            default:
+                return operationState;
+            case NOTIFICATION_PROCESSING_PENDING:
+                return org.onap.vnfmadapter.v1.model.OperationStateEnum.PROCESSING;
+            case NOTIFICATION_PROCEESING_SUCCESSFUL:
+                return operationState;
+            case NOTIFICATION_PROCESSING_FAILED:
+                return org.onap.vnfmadapter.v1.model.OperationStateEnum.FAILED;
         }
-        return operationState;
+    }
+
+    public void notificationProcessedForOperation(final String operationId,
+            final boolean notificationProcessingWasSuccessful) {
+        final java.util.Optional<VnfmOperation> relatedOperation = mapOfJobIdToVnfmOperation.values().stream()
+                .filter(operation -> operation.getOperationId().equals(operationId)).findFirst();
+        if (relatedOperation.isPresent()) {
+            relatedOperation.get().setNotificationProcessed(notificationProcessingWasSuccessful);
+        }
+        logger.debug("No operation found for operation ID " + operationId);
     }
 
 }
index 916c9e4..e0ad327 100644 (file)
@@ -27,13 +27,13 @@ public class VnfmOperation {
 
     private final String vnfmId;
     private final String operationId;
-    private boolean waitForNotificationForSuccess = false;
-    private boolean isNotificationProcessed = false;
+    private NotificationStatus notificationStatus;
 
     public VnfmOperation(final String vnfmId, final String operationId, final boolean waitForNotificationForSuccess) {
         this.vnfmId = vnfmId;
         this.operationId = operationId;
-        this.waitForNotificationForSuccess = waitForNotificationForSuccess;
+        this.notificationStatus = waitForNotificationForSuccess ? NotificationStatus.NOTIFICATION_PROCESSING_PENDING
+                : NotificationStatus.NOTIFICATION_PROCESSING_NOT_REQUIRED;
     }
 
     /**
@@ -55,31 +55,43 @@ public class VnfmOperation {
     }
 
     /**
-     * Check if a notification should be processed before the operation is considered successfully
-     * completed.
+     * Set the required notification has been processed for the operation.
      *
-     * @return <code>true></code> if a notification must be processed before the operation is considered
-     *         successfully completed, <code>false</code> otherwise
+     * @param notificationProcessingWasSuccessful <code>true</code> if the notification processing was
+     *        successful, <code>false<code> otherwise
      */
-    public boolean isWaitForNotificationForSuccess() {
-        return waitForNotificationForSuccess;
+    public void setNotificationProcessed(final boolean notificationProcessingWasSuccessful) {
+        this.notificationStatus =
+                notificationProcessingWasSuccessful ? NotificationStatus.NOTIFICATION_PROCEESING_SUCCESSFUL
+                        : NotificationStatus.NOTIFICATION_PROCESSING_FAILED;
     }
 
     /**
-     * Set the required notification has been processed for the operation.
+     * Get the notification status for the operation.
+     *
+     * @return the notification status
      */
-    public void setNotificationProcessed() {
-        this.isNotificationProcessed = true;
+    public NotificationStatus getNotificationStatus() {
+        return notificationStatus;
     }
 
-    /**
-     * Check if the required notification has been processed.
-     *
-     * @return <code>true</code> of the required notification has been processed, <code>false</code>
-     *         otherwise
-     */
-    public boolean isNotificationProcessed() {
-        return isNotificationProcessed;
+    public enum NotificationStatus {
+        /**
+         * No notification handling is required to determine the status of the operation
+         */
+        NOTIFICATION_PROCESSING_NOT_REQUIRED,
+        /**
+         * A notification must be processed before the notification can be considered to be completed
+         */
+        NOTIFICATION_PROCESSING_PENDING,
+        /**
+         * A notification has been successfully handled for the operation
+         */
+        NOTIFICATION_PROCEESING_SUCCESSFUL,
+        /**
+         * An error occurred processing a notification for the operation
+         */
+        NOTIFICATION_PROCESSING_FAILED;
     }
 
 }
index 36b197d..b82ed86 100644 (file)
@@ -30,11 +30,13 @@ import org.onap.aai.domain.yang.GenericVnf;
 import org.onap.aai.domain.yang.Vserver;
 import org.onap.so.adapters.vnfmadapter.extclients.aai.AaiHelper;
 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.lcn.model.LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.VnfLcmOperationOccurrenceNotification;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.VnfLcmOperationOccurrenceNotification.OperationStateEnum;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse201;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse201VimConnectionInfo;
+import org.onap.so.adapters.vnfmadapter.jobmanagement.JobManager;
 import org.slf4j.Logger;
 
 /**
@@ -46,16 +48,19 @@ public class NotificationHandler implements Runnable {
     private final VnfLcmOperationOccurrenceNotification vnfLcmOperationOccurrenceNotification;
     private final AaiHelper aaiHelper;
     private final AaiServiceProvider aaiServiceProvider;
-
-
+    private final VnfmServiceProvider vnfmServiceProvider;
+    private final JobManager jobManager;
     private final InlineResponse201 vnfInstance;
 
     public NotificationHandler(final VnfLcmOperationOccurrenceNotification vnfLcmOperationOccurrenceNotification,
             final AaiHelper aaiHelper, final AaiServiceProvider aaiServiceProvider,
+            final VnfmServiceProvider vnfmServiceProvider, final JobManager jobManager,
             final InlineResponse201 vnfInstance) {
         this.vnfLcmOperationOccurrenceNotification = vnfLcmOperationOccurrenceNotification;
         this.aaiHelper = aaiHelper;
         this.aaiServiceProvider = aaiServiceProvider;
+        this.vnfmServiceProvider = vnfmServiceProvider;
+        this.jobManager = jobManager;
         this.vnfInstance = vnfInstance;
     }
 
@@ -63,12 +68,12 @@ public class NotificationHandler implements Runnable {
     public void run() {
         try {
             if (vnfLcmOperationOccurrenceNotification.getOperationState().equals(OperationStateEnum.COMPLETED)) {
-                final GenericVnf genericVnf =
-                        aaiServiceProvider.invokeQueryGenericVnf(vnfInstance.getLinks().getSelf().getHref()).get(0);
-
                 switch (vnfLcmOperationOccurrenceNotification.getOperation()) {
                     case INSTANTIATE:
-                        handleVnfInstantiated(genericVnf);
+                        handleVnfInstantiate();
+                        break;
+                    case TERMINATE:
+                        handleVnfTerminate();
                         break;
                     default:
                 }
@@ -79,7 +84,15 @@ public class NotificationHandler implements Runnable {
         }
     }
 
-    private void handleVnfInstantiated(final GenericVnf genericVnf) {
+    private void handleVnfInstantiate() {
+        if (vnfLcmOperationOccurrenceNotification.getOperationState().equals(OperationStateEnum.COMPLETED)) {
+            handleVnfInstantiateCompleted();
+        }
+    }
+
+    private void handleVnfInstantiateCompleted() {
+        final GenericVnf genericVnf =
+                aaiServiceProvider.invokeQueryGenericVnf(vnfInstance.getLinks().getSelf().getHref()).get(0);
         final String ipAddress = getOamIpAddress(vnfInstance);
         logger.debug("Updating " + genericVnf.getVnfId() + " with VNF OAM IP ADDRESS: " + ipAddress);
         genericVnf.setIpv4OamAddress(ipAddress);
@@ -108,6 +121,45 @@ public class NotificationHandler implements Runnable {
         }
     }
 
+    private void handleVnfTerminate() {
+        switch (vnfLcmOperationOccurrenceNotification.getOperationState()) {
+            case COMPLETED:
+                handleVnfTerminateCompleted();
+                break;
+            case FAILED:
+            case ROLLING_BACK:
+                handleVnfTerminateFailed();
+                break;
+            default:
+        }
+    }
+
+    private void handleVnfTerminateFailed() {
+        final GenericVnf genericVnf =
+                aaiServiceProvider.invokeQueryGenericVnf(vnfInstance.getLinks().getSelf().getHref()).get(0);
+        updateVservers(vnfLcmOperationOccurrenceNotification, genericVnf.getVnfId(),
+                vnfInstance.getVimConnectionInfo());
+        jobManager.notificationProcessedForOperation(vnfLcmOperationOccurrenceNotification.getId(), false);
+    }
+
+    private void handleVnfTerminateCompleted() {
+        final GenericVnf genericVnf =
+                aaiServiceProvider.invokeQueryGenericVnf(vnfInstance.getLinks().getSelf().getHref()).get(0);
+        updateVservers(vnfLcmOperationOccurrenceNotification, genericVnf.getVnfId(),
+                vnfInstance.getVimConnectionInfo());
+
+        boolean deleteSuccessful = false;
+        try {
+            vnfmServiceProvider.deleteVnf(genericVnf.getSelflink());
+            deleteSuccessful = true;
+        } finally {
+            jobManager.notificationProcessedForOperation(vnfLcmOperationOccurrenceNotification.getId(),
+                    deleteSuccessful);
+            genericVnf.setOrchestrationStatus("Assigned");
+            aaiServiceProvider.invokePutGenericVnf(genericVnf);
+        }
+    }
+
     private void updateVservers(final VnfLcmOperationOccurrenceNotification notification, final String vnfId,
             final List<InlineResponse201VimConnectionInfo> vnfInstancesVimConnectionInfo) {
         final Map<String, InlineResponse201VimConnectionInfo> vimConnectionIdToVimConnectionInfo = new HashMap<>();
@@ -116,17 +168,21 @@ public class NotificationHandler implements Runnable {
         }
 
         for (final LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs vnfc : notification.getAffectedVnfcs()) {
-
+            final InlineResponse201VimConnectionInfo vimConnectionInfo =
+                    getVimConnectionInfo(vimConnectionIdToVimConnectionInfo, vnfc);
             switch (vnfc.getChangeType()) {
                 case ADDED:
                     final Vserver vserver = aaiHelper.createVserver(vnfc);
                     aaiHelper.addRelationshipFromVserverVnfToGenericVnf(vserver, vnfId);
-                    final InlineResponse201VimConnectionInfo vimConnectionInfo =
-                            getVimConnectionInfo(vimConnectionIdToVimConnectionInfo, vnfc);
+
                     aaiServiceProvider.invokePutVserver(getCloudOwner(vimConnectionInfo),
                             getCloudRegion(vimConnectionInfo), getTenant(vimConnectionInfo), vserver);
                     break;
                 case REMOVED:
+                    aaiServiceProvider.invokeDeleteVserver(getCloudOwner(vimConnectionInfo),
+                            getCloudRegion(vimConnectionInfo), getTenant(vimConnectionInfo),
+                            vnfc.getComputeResource().getResourceId());
+                    break;
                 case MODIFIED:
                 case TEMPORARY:
                 default:
index 60f3f51..f0958cb 100644 (file)
@@ -34,6 +34,7 @@ import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.VnfLcmOperatio
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.VnfLcmOperationOccurrenceNotification.OperationEnum;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.VnfLcmOperationOccurrenceNotification.OperationStateEnum;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse201;
+import org.onap.so.adapters.vnfmadapter.jobmanagement.JobManager;
 import org.onap.so.adapters.vnfmadapter.notificationhandling.NotificationHandler;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -56,14 +57,16 @@ public class Sol003LcnContoller {
     private final AaiServiceProvider aaiServiceProvider;
     private final AaiHelper aaiHelper;
     private final VnfmServiceProvider vnfmServiceProvider;
+    private final JobManager jobManager;
     private final ExecutorService executor = Executors.newCachedThreadPool();
 
     @Autowired
     Sol003LcnContoller(final AaiServiceProvider aaiServiceProvider, final AaiHelper aaiHelper,
-            final VnfmServiceProvider vnfmServiceProvider) {
+            final VnfmServiceProvider vnfmServiceProvider, final JobManager jobManager) {
         this.aaiServiceProvider = aaiServiceProvider;
         this.aaiHelper = aaiHelper;
         this.vnfmServiceProvider = vnfmServiceProvider;
+        this.jobManager = jobManager;
     }
 
     @PostMapping(value = "/lcn/VnfIdentifierCreationNotification")
@@ -85,12 +88,10 @@ public class Sol003LcnContoller {
             @RequestBody final VnfLcmOperationOccurrenceNotification vnfLcmOperationOccurrenceNotification) {
         logger.info(LOG_LCN_RECEIVED + vnfLcmOperationOccurrenceNotification);
 
-        final OperationEnum operation = vnfLcmOperationOccurrenceNotification.getOperation();
-        if ((operation.equals(OperationEnum.INSTANTIATE))
-                && vnfLcmOperationOccurrenceNotification.getOperationState().equals(OperationStateEnum.COMPLETED)) {
+        if (isANotificationOfInterest(vnfLcmOperationOccurrenceNotification)) {
             final InlineResponse201 vnfInstance = getVnfInstance(vnfLcmOperationOccurrenceNotification);
             final NotificationHandler handler = new NotificationHandler(vnfLcmOperationOccurrenceNotification,
-                    aaiHelper, aaiServiceProvider, vnfInstance);
+                    aaiHelper, aaiServiceProvider, vnfmServiceProvider, jobManager, vnfInstance);
             executor.execute(handler);
         }
 
@@ -98,6 +99,22 @@ public class Sol003LcnContoller {
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
+    private boolean isANotificationOfInterest(final VnfLcmOperationOccurrenceNotification notification) {
+        return isInstanitiateCompleted(notification) || isTerminateTerminalState(notification);
+    }
+
+    private boolean isInstanitiateCompleted(final VnfLcmOperationOccurrenceNotification notification) {
+        return notification.getOperation().equals(OperationEnum.INSTANTIATE)
+                && notification.getOperationState().equals(OperationStateEnum.COMPLETED);
+    }
+
+    private boolean isTerminateTerminalState(final VnfLcmOperationOccurrenceNotification notification) {
+        return notification.getOperation().equals(OperationEnum.TERMINATE)
+                && (notification.getOperationState().equals(OperationStateEnum.COMPLETED)
+                        || notification.getOperationState().equals(OperationStateEnum.FAILED)
+                        || notification.getOperationState().equals(OperationStateEnum.ROLLED_BACK));
+    }
+
     private InlineResponse201 getVnfInstance(
             final VnfLcmOperationOccurrenceNotification vnfLcmOperationOccurrenceNotification) {
         return vnfmServiceProvider.getVnf(vnfLcmOperationOccurrenceNotification.getLinks().getVnfInstance().getHref())
index b3fbcaa..a8455f8 100644 (file)
@@ -25,8 +25,10 @@ import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.onap.so.client.RestTemplateConfig.CONFIGURABLE_REST_TEMPLATE;
 import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
 import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
 import com.google.gson.Gson;
 import java.net.URI;
@@ -124,9 +126,34 @@ public class Sol003LcnControllerTest {
         assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
     }
 
+    @Test
+    public void lcnNotification_InstantiateStartingOrProcessing_NoAction()
+            throws URISyntaxException, InterruptedException {
+        final VnfLcmOperationOccurrenceNotification startingNotification = new VnfLcmOperationOccurrenceNotification();
+        startingNotification.setOperation(OperationEnum.INSTANTIATE);
+        startingNotification.setOperationState(OperationStateEnum.STARTING);
+
+        ResponseEntity<Void> response = controller.lcnVnfLcmOperationOccurrenceNotificationPost(startingNotification);
+        assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
+
+        verifyZeroInteractions(aaiResourcesClient);
+
+        final VnfLcmOperationOccurrenceNotification processingNotification =
+                new VnfLcmOperationOccurrenceNotification();
+        processingNotification.setOperation(OperationEnum.INSTANTIATE);
+        processingNotification.setOperationState(OperationStateEnum.STARTING);
+
+        response = controller.lcnVnfLcmOperationOccurrenceNotificationPost(processingNotification);
+        assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
+
+        verifyZeroInteractions(aaiResourcesClient);
+    }
+
     @Test
     public void lcnNotification_InstantiateCompleted_AaiUpdated() throws URISyntaxException, InterruptedException {
-        final VnfLcmOperationOccurrenceNotification vnfLcmOperationOccurrenceNotification = createNotification();
+        final VnfLcmOperationOccurrenceNotification vnfLcmOperationOccurrenceNotification =
+                createNotification(OperationEnum.INSTANTIATE);
+        addVnfcsToNotification(vnfLcmOperationOccurrenceNotification, ChangeTypeEnum.ADDED);
         final InlineResponse201 vnfInstance = createVnfInstance();
 
         mockRestServer.expect(requestTo(new URI("http://vnfm:8080/vnfs/myTestVnfIdOnVnfm")))
@@ -169,9 +196,51 @@ public class Sol003LcnControllerTest {
         assertEquals("myTestVnfId", relationship.getRelationshipData().get(0).getRelationshipValue());
     }
 
-    private VnfLcmOperationOccurrenceNotification createNotification() {
+    @Test
+    public void lcnNotification_TerminateCompleted_AaiUpdated() throws URISyntaxException, InterruptedException {
+        final VnfLcmOperationOccurrenceNotification vnfLcmOperationOccurrenceNotification =
+                createNotification(OperationEnum.TERMINATE);
+        addVnfcsToNotification(vnfLcmOperationOccurrenceNotification, ChangeTypeEnum.REMOVED);
+
+        final InlineResponse201 vnfInstance = createVnfInstance();
+
+        mockRestServer.expect(requestTo(new URI("http://vnfm:8080/vnfs/myTestVnfIdOnVnfm")))
+                .andRespond(withSuccess(gson.toJson(vnfInstance), MediaType.APPLICATION_JSON));
+
+        mockRestServer.expect(requestTo(new URI("http://vnfm:8080/vnfs/myTestVnfIdOnVnfm")))
+                .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON));
+
+        final GenericVnf genericVnf = createGenericVnf("vnfmType1");
+        genericVnf.setSelflink("http://vnfm:8080/vnfs/myTestVnfIdOnVnfm");
+        final List<GenericVnf> genericVnfs = new ArrayList<>();
+        genericVnfs.add(genericVnf);
+        doReturn(Optional.of(genericVnfs)).when(aaiResourcesClient).get(eq(List.class),
+                MockitoHamcrest.argThat(new AaiResourceUriMatcher(
+                        "/network/generic-vnfs?selflink=http%3A%2F%2Fvnfm%3A8080%2Fvnfs%2FmyTestVnfIdOnVnfm")));
+
+        final ResponseEntity<Void> response =
+                controller.lcnVnfLcmOperationOccurrenceNotificationPost(vnfLcmOperationOccurrenceNotification);
+        assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
+
+        final ArgumentCaptor<GenericVnf> genericVnfArgument = ArgumentCaptor.forClass(GenericVnf.class);
+        final ArgumentCaptor<AAIResourceUri> updateUriArgument = ArgumentCaptor.forClass(AAIResourceUri.class);
+        verify(aaiResourcesClient, timeout(10000000)).update(updateUriArgument.capture(), genericVnfArgument.capture());
+        assertEquals("/network/generic-vnfs/generic-vnf/myTestVnfId", updateUriArgument.getValue().build().toString());
+        assertEquals("Assigned", genericVnfArgument.getValue().getOrchestrationStatus());
+
+        final ArgumentCaptor<AAIResourceUri> deleteUriArgument = ArgumentCaptor.forClass(AAIResourceUri.class);
+
+        verify(aaiResourcesClient, timeout(10000000)).delete(deleteUriArgument.capture());
+
+        assertEquals(
+                "/cloud-infrastructure/cloud-regions/cloud-region/" + CLOUD_OWNER + "/" + REGION + "/tenants/tenant/"
+                        + TENANT_ID + "/vservers/vserver/myVnfc1",
+                deleteUriArgument.getAllValues().get(0).build().toString());
+    }
+
+    private VnfLcmOperationOccurrenceNotification createNotification(final OperationEnum operation) {
         final VnfLcmOperationOccurrenceNotification notification = new VnfLcmOperationOccurrenceNotification();
-        notification.setOperation(OperationEnum.INSTANTIATE);
+        notification.setOperation(operation);
         notification.setOperationState(OperationStateEnum.COMPLETED);
 
         final LcnVnfLcmOperationOccurrenceNotificationLinksVnfInstance linkToVnfInstance =
@@ -181,10 +250,15 @@ public class Sol003LcnControllerTest {
                 new LcnVnfLcmOperationOccurrenceNotificationLinks().vnfInstance(linkToVnfInstance);
         notification.setLinks(operationLinks);
 
+        return notification;
+    }
+
+    private void addVnfcsToNotification(final VnfLcmOperationOccurrenceNotification notification,
+            final ChangeTypeEnum changeType) {
         final List<LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs> affectedVnfcs = new ArrayList<>();;
         final LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs vnfc =
                 new LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs();
-        vnfc.changeType(ChangeTypeEnum.ADDED);
+        vnfc.changeType(changeType);
         final LcnVnfLcmOperationOccurrenceNotificationComputeResource computeResource =
                 new LcnVnfLcmOperationOccurrenceNotificationComputeResource();
         computeResource.setResourceId("myVnfc1");
@@ -192,7 +266,6 @@ public class Sol003LcnControllerTest {
         vnfc.setComputeResource(computeResource);
         affectedVnfcs.add(vnfc);
         notification.setAffectedVnfcs(affectedVnfcs);
-        return notification;
     }
 
     private InlineResponse201 createVnfInstance() {