Fix sonar issues
[vfc/nfvo/driver/vnfm/svnfm.git] / nokiav2 / driver / src / main / java / org / onap / vfc / nfvo / driver / vnfm / svnfm / nokia / vnfm / notification / LifecycleChangeNotificationManager.java
index 9ee8cbd..3ff0499 100644 (file)
 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Ordering;
-import com.google.common.collect.Sets;
 import com.google.gson.Gson;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
-import com.nokia.cbam.lcm.v32.ApiException;
 import com.nokia.cbam.lcm.v32.api.OperationExecutionsApi;
 import com.nokia.cbam.lcm.v32.api.VnfsApi;
 import com.nokia.cbam.lcm.v32.model.*;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.INotificationSender;
 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions;
 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider;
@@ -36,13 +36,13 @@ import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Set;
+import static java.util.Optional.empty;
+import static java.util.Optional.of;
 
-import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.find;
 import static com.google.common.collect.Iterables.tryFind;
 import static com.google.common.collect.Sets.newConcurrentHashSet;
+import static com.google.common.collect.Sets.newHashSet;
 import static com.nokia.cbam.lcm.v32.model.OperationType.INSTANTIATE;
 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.buildFatalFailure;
 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.childElement;
@@ -80,7 +80,7 @@ public class LifecycleChangeNotificationManager implements ILifecycleChangeNotif
     /**
      * < Separates the VNF id and the resource id within a VNF
      */
-    private static final Set<OperationStatus> terminalStatus = Sets.newHashSet(OperationStatus.FINISHED, OperationStatus.FAILED);
+    private static final Set<OperationStatus> terminalStatus = newHashSet(OperationStatus.FINISHED, OperationStatus.FAILED);
     private static Logger logger = getLogger(LifecycleChangeNotificationManager.class);
 
     private final CbamRestApiProvider restApiProvider;
@@ -95,35 +95,37 @@ public class LifecycleChangeNotificationManager implements ILifecycleChangeNotif
         this.restApiProvider = restApiProvider;
     }
 
+    /**
+     * @param status the status of the operation
+     * @return has the operation finished
+     */
+    public static boolean isTerminal(OperationStatus status) {
+        return terminalStatus.contains(status);
+    }
+
     @VisibleForTesting
     static OperationExecution findLastInstantiationBefore(List<OperationExecution> operationExecutions, OperationExecution currentOperation) {
-        for (OperationExecution opExs : filter(NEWEST_OPERATIONS_FIRST.sortedCopy(operationExecutions), (OperationExecution opex2) -> !opex2.getStartTime().isAfter(currentOperation.getStartTime()))) {
-            if (INSTANTIATE.equals(opExs.getOperationType()) &&
-                    (opExs.getStartTime().toLocalDate().isBefore(currentOperation.getStartTime().toLocalDate()) ||
-                            opExs.getStartTime().toLocalDate().isEqual(currentOperation.getStartTime().toLocalDate())
-                    )) {
-                return opExs;
-            }
-        }
-        throw new NoSuchElementException();
+        return find(NEWEST_OPERATIONS_FIRST.sortedCopy(operationExecutions), (OperationExecution opex2) ->
+                !opex2.getStartTime().isAfter(currentOperation.getStartTime())
+                        && INSTANTIATE.equals(opex2.getOperationType()));
     }
 
     @Override
-    public void handleLcn(VnfLifecycleChangeNotification recievedNotification) {
+    public void handleLcn(VnfLifecycleChangeNotification receivedNotification) {
         if (logger.isInfoEnabled()) {
-            logger.info("Received LCN: " + new Gson().toJson(recievedNotification));
+            logger.info("Received LCN: {}", new Gson().toJson(receivedNotification));
         }
         VnfsApi cbamLcmApi = restApiProvider.getCbamLcmApi(driverProperties.getVnfmId());
         try {
-            List<VnfInfo> vnfs = cbamLcmApi.vnfsGet(NOKIA_LCM_API_VERSION);
-            com.google.common.base.Optional<VnfInfo> currentVnf = tryFind(vnfs, vnf -> vnf.getId().equals(recievedNotification.getVnfInstanceId()));
-            String vnfHeader = "The VNF with " + recievedNotification.getVnfInstanceId() + " identifier";
+            List<VnfInfo> vnfs = cbamLcmApi.vnfsGet(NOKIA_LCM_API_VERSION).blockingFirst();
+            com.google.common.base.Optional<VnfInfo> currentVnf = tryFind(vnfs, vnf -> vnf.getId().equals(receivedNotification.getVnfInstanceId()));
+            String vnfHeader = "The VNF with " + receivedNotification.getVnfInstanceId() + " identifier";
             if (!currentVnf.isPresent()) {
                 logger.warn(vnfHeader + " disappeared before being able to process the LCN");
                 //swallow LCN
                 return;
             } else {
-                VnfInfo vnf = cbamLcmApi.vnfsVnfInstanceIdGet(recievedNotification.getVnfInstanceId(), NOKIA_LCN_API_VERSION);
+                VnfInfo vnf = cbamLcmApi.vnfsVnfInstanceIdGet(receivedNotification.getVnfInstanceId(), NOKIA_LCN_API_VERSION).blockingFirst();
                 com.google.common.base.Optional<VnfProperty> externalVnfmId = tryFind(vnf.getExtensions(), prop -> prop.getName().equals(LifecycleManager.EXTERNAL_VNFM_ID));
                 if (!externalVnfmId.isPresent()) {
                     logger.warn(vnfHeader + " is not a managed VNF");
@@ -138,23 +140,34 @@ public class LifecycleChangeNotificationManager implements ILifecycleChangeNotif
             throw buildFatalFailure(logger, "Unable to list VNFs / query VNF", e);
         }
         OperationExecutionsApi cbamOperationExecutionApi = restApiProvider.getCbamOperationExecutionApi(driverProperties.getVnfmId());
+        List<OperationExecution> operationExecutions;
         try {
-            List<OperationExecution> operationExecutions = cbamLcmApi.vnfsVnfInstanceIdOperationExecutionsGet(recievedNotification.getVnfInstanceId(), NOKIA_LCM_API_VERSION);
-            OperationExecution operationExecution = cbamOperationExecutionApi.operationExecutionsOperationExecutionIdGet(recievedNotification.getLifecycleOperationOccurrenceId(), NOKIA_LCM_API_VERSION);
-            OperationExecution closestInstantiationToOperation = findLastInstantiationBefore(operationExecutions, operationExecution);
-            String vimId = getVimId(cbamOperationExecutionApi, closestInstantiationToOperation);
-            notificationSender.processNotification(recievedNotification, operationExecution, buildAffectedCps(operationExecution), vimId);
-            if (OperationType.TERMINATE.equals(recievedNotification.getOperation()) && terminalStatus.contains(recievedNotification.getStatus())) {
-                processedNotifications.add(new ProcessedNotification(recievedNotification.getLifecycleOperationOccurrenceId(), recievedNotification.getStatus()));
-            }
-        } catch (ApiException e) {
-            throw buildFatalFailure(logger, "Unable to retrieve the current VNF " + recievedNotification.getVnfInstanceId(), e);
+            operationExecutions = cbamLcmApi.vnfsVnfInstanceIdOperationExecutionsGet(receivedNotification.getVnfInstanceId(), NOKIA_LCM_API_VERSION).blockingFirst();
+        } catch (Exception e) {
+            throw buildFatalFailure(logger, "Unable to retrieve the operation executions for the VNF " + receivedNotification.getVnfInstanceId(), e);
         }
+        OperationExecution operationExecution;
+        try {
+            operationExecution = cbamOperationExecutionApi.operationExecutionsOperationExecutionIdGet(receivedNotification.getLifecycleOperationOccurrenceId(), NOKIA_LCM_API_VERSION).blockingFirst();
+        } catch (Exception e) {
+            throw buildFatalFailure(logger, "Unable to retrieve the operation execution with " + receivedNotification.getLifecycleOperationOccurrenceId() + " identifier", e);
+        }
+        OperationExecution closestInstantiationToOperation = findLastInstantiationBefore(operationExecutions, operationExecution);
+        String vimId = getVimId(cbamOperationExecutionApi, closestInstantiationToOperation);
+        notificationSender.processNotification(receivedNotification, operationExecution, buildAffectedCps(operationExecution), vimId);
+        if (isTerminationFinished(receivedNotification)) {
+            //signal LifecycleManager to continue the deletion of the VNF
+            processedNotifications.add(new ProcessedNotification(receivedNotification.getLifecycleOperationOccurrenceId(), receivedNotification.getStatus()));
+        }
+    }
+
+    private boolean isTerminationFinished(VnfLifecycleChangeNotification receivedNotification) {
+        return OperationType.TERMINATE.equals(receivedNotification.getOperation()) && terminalStatus.contains(receivedNotification.getStatus());
     }
 
     private String getVimId(OperationExecutionsApi cbamOperationExecutionApi, OperationExecution closestInstantiationToOperation) {
         try {
-            Object operationParams = cbamOperationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(closestInstantiationToOperation.getId(), NOKIA_LCM_API_VERSION);
+            Object operationParams = cbamOperationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(closestInstantiationToOperation.getId(), NOKIA_LCM_API_VERSION).blockingFirst();
             return getVimId(operationParams);
         } catch (Exception e) {
             throw buildFatalFailure(logger, "Unable to detect last instantiation operation", e);
@@ -164,7 +177,7 @@ public class LifecycleChangeNotificationManager implements ILifecycleChangeNotif
     @Override
     public void waitForTerminationToBeProcessed(String operationExecutionId) {
         while (true) {
-            com.google.common.base.Optional<ProcessedNotification> notification = Iterables.tryFind(processedNotifications, processedNotification -> processedNotification.getOperationExecutionId().equals(operationExecutionId));
+            com.google.common.base.Optional<ProcessedNotification> notification = tryFind(processedNotifications, processedNotification -> processedNotification.getOperationExecutionId().equals(operationExecutionId));
             if (notification.isPresent()) {
                 processedNotifications.remove(notification.get());
                 return;
@@ -178,47 +191,53 @@ public class LifecycleChangeNotificationManager implements ILifecycleChangeNotif
         return request.getVims().get(0).getId();
     }
 
-    private ReportedAffectedConnectionPoints buildAffectedCps(OperationExecution operationExecution) {
+    private Optional<ReportedAffectedConnectionPoints> buildAffectedCps(OperationExecution operationExecution) {
+        if (!isTerminal(operationExecution.getStatus())) {
+            //connection points can only be calculated after the operation has finished
+            return Optional.empty();
+        }
         if (operationExecution.getOperationType() == OperationType.TERMINATE) {
             String terminationType = childElement(new Gson().toJsonTree(operationExecution.getOperationParams()).getAsJsonObject(), "terminationType").getAsString();
             if (TerminationType.FORCEFUL.name().equals(terminationType)) {
                 //in case of force full termination the Ansible is not executed, so the connection points can not be
                 //calculated from operation execution result
                 logger.warn("Unable to send information related to affected connection points during forceful termination");
-                return null;
+                return empty();
+            } else {
+                //graceful termination should be handled as any other operation
             }
         }
         try {
             JsonElement root = new Gson().toJsonTree(operationExecution.getAdditionalData());
             if (root.getAsJsonObject().has("operationResult")) {
                 JsonObject operationResult = root.getAsJsonObject().get("operationResult").getAsJsonObject();
-                if (!isPresent(operationResult, "cbam_pre") || !isPresent(operationResult, "cbam_post")) {
-                    handleFailure(operationExecution, null);
+                if (isAbsent(operationResult, "cbam_pre") ||
+                        isAbsent(operationResult, "cbam_post")) {
+                    return handleFailure(operationExecution, null);
+                } else {
+                    return of(new Gson().fromJson(operationResult, ReportedAffectedConnectionPoints.class));
                 }
-                return new Gson().fromJson(operationResult, ReportedAffectedConnectionPoints.class);
+            } else {
+                return handleFailure(operationExecution, null);
             }
         } catch (Exception e) {
-            handleFailure(operationExecution, e);
+            return handleFailure(operationExecution, e);
         }
-        return new ReportedAffectedConnectionPoints();
     }
 
-    private boolean isPresent(JsonObject operationResult, String key) {
-        return operationResult.has(key) && operationResult.get(key).isJsonArray();
+    private boolean isAbsent(JsonObject operationResult, String key) {
+        return !operationResult.has(key) || !operationResult.get(key).isJsonArray();
     }
 
-    private void handleFailure(OperationExecution operationExecution, Exception e) {
-        switch (operationExecution.getStatus()) {
-            case FAILED:
-            case OTHER:
-                logger.warn("The operation failed and the affected connection points were not reported");
-                break;
-            case STARTED: //can not happen (the changed resources are only executed for terminal state
-            case FINISHED:
-                if (e != null) {
-                    throw buildFatalFailure(logger, PROBLEM, e);
-                }
-                throw buildFatalFailure(logger, PROBLEM);
+    private Optional<ReportedAffectedConnectionPoints> handleFailure(OperationExecution operationExecution, Exception e) {
+        if (operationExecution.getStatus() == OperationStatus.FAILED) {
+            logger.warn("The operation failed and the affected connection points were not reported");
+            return empty();
+        } else {
+            if (e != null) {
+                throw buildFatalFailure(logger, PROBLEM, e);
+            }
+            throw buildFatalFailure(logger, PROBLEM);
         }
     }
 }