Fix container startup
[vfc/nfvo/driver/vnfm/svnfm.git] / nokiav2 / driver / src / main / java / org / onap / vfc / nfvo / driver / vnfm / svnfm / nokia / vnfm / JobManager.java
index d6b1cb2..e97f634 100644 (file)
@@ -19,14 +19,14 @@ import com.google.common.collect.Ordering;
 import com.google.common.collect.Sets;
 import com.google.gson.Gson;
 import com.google.gson.JsonElement;
-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.OperationExecution;
+import com.nokia.cbam.lcm.v32.model.OperationType;
 import com.nokia.cbam.lcm.v32.model.VnfInfo;
-import org.apache.http.HttpStatus;
+import java.util.*;
+import javax.servlet.http.HttpServletResponse;
 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrationManager;
-import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.LifecycleChangeNotificationManager;
 import org.onap.vnfmdriver.model.JobDetailInfo;
 import org.onap.vnfmdriver.model.JobDetailInfoResponseDescriptor;
 import org.onap.vnfmdriver.model.JobResponseInfo;
@@ -35,18 +35,21 @@ import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import javax.servlet.http.HttpServletResponse;
-import java.util.*;
+import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
+import static java.util.Optional.empty;
+import static java.util.Optional.of;
 
 import static com.google.common.base.Splitter.on;
+import static com.google.common.collect.Iterables.find;
 import static com.google.common.collect.Iterables.tryFind;
 import static com.google.common.collect.Lists.newArrayList;
-import static java.util.Optional.empty;
-import static java.util.Optional.of;
-import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.fatalFailure;
+import static com.nokia.cbam.lcm.v32.model.OperationStatus.FAILED;
+import static com.nokia.cbam.lcm.v32.model.OperationStatus.STARTED;
+import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.SEPARATOR;
+import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.buildFatalFailure;
 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions.systemFunctions;
 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCM_API_VERSION;
-import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.ILifecycleChangeNotificationManager.SEPARATOR;
+import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.LifecycleChangeNotificationManager.NEWEST_OPERATIONS_FIRST;
 import static org.slf4j.LoggerFactory.getLogger;
 import static org.springframework.util.StringUtils.isEmpty;
 
@@ -58,6 +61,7 @@ import static org.springframework.util.StringUtils.isEmpty;
  */
 @Component
 public class JobManager {
+    public static final String OPERATION_STARTED_DESCRIPTION = "Operation started";
     private static final Ordering<JobResponseInfo> OLDEST_FIRST = new Ordering<JobResponseInfo>() {
         @Override
         public int compare(JobResponseInfo left, JobResponseInfo right) {
@@ -93,6 +97,13 @@ public class JobManager {
         return jobId.getAsString();
     }
 
+    /**
+     * @return is the component preparing for shutdown
+     */
+    public boolean isPreparingForShutDown(){
+        return preparingForShutDown;
+    }
+
     /**
      * Throws an exception in case the service is not ready to serve requests due to
      * not being able to register to MSB or to subscribe to CBAM LCNs
@@ -105,12 +116,12 @@ public class JobManager {
         String jobId = vnfId + SEPARATOR + UUID.randomUUID().toString();
         synchronized (this) {
             if (preparingForShutDown) {
-                response.setStatus(HttpStatus.SC_SERVICE_UNAVAILABLE);
-                fatalFailure(logger, "The service is preparing to shut down");
+                response.setStatus(SC_SERVICE_UNAVAILABLE);
+                throw buildFatalFailure(logger, "The service is preparing to shut down");
             }
             if (!selfRegistrationManager.isReady()) {
-                response.setStatus(HttpStatus.SC_SERVICE_UNAVAILABLE);
-                fatalFailure(logger, "The service is not yet ready");
+                response.setStatus(SC_SERVICE_UNAVAILABLE);
+                throw buildFatalFailure(logger, "The service is not yet ready");
             }
         }
         ongoingJobs.add(jobId);
@@ -130,7 +141,7 @@ public class JobManager {
      * @return the system has any ongoing jobs
      */
     public boolean hasOngoingJobs() {
-        return ongoingJobs.size() != 0;
+        return !ongoingJobs.isEmpty();
     }
 
 
@@ -155,7 +166,7 @@ public class JobManager {
      * @return detailed information of the job
      */
     public JobDetailInfo getJob(String vnfmId, String jobId) {
-        logger.debug("Retrieving the details for job with " + jobId);
+        logger.debug("Retrieving the details for job with {} identifier", jobId);
         ArrayList<String> jobParts = newArrayList(on(SEPARATOR).split(jobId));
         if (jobParts.size() != 2) {
             throw new IllegalArgumentException("The jobId should be in the <vnfId>" + SEPARATOR + "<UUID> format, but was " + jobId);
@@ -172,7 +183,7 @@ public class JobManager {
         if (!vnf.isPresent()) {
             return getJobDetailInfoForMissingVnf(jobId);
         } else {
-            return getJobInfoForExistingVnf(vnfmId, jobId, vnfId, vnf);
+            return getJobInfoForExistingVnf(vnfmId, jobId, vnfId, vnf.get());
         }
     }
 
@@ -184,35 +195,12 @@ public class JobManager {
         }
     }
 
-    private JobDetailInfo getJobInfoForExistingVnf(String vnfmId, String jobId, String vnfId, Optional<VnfInfo> vnf) {
+    private JobDetailInfo getJobInfoForExistingVnf(String vnfmId, String jobId, String vnfId, VnfInfo vnf) {
         try {
             OperationExecution operation = findOperationByJobId(vnfmId, vnf, jobId);
-            switch (operation.getStatus()) {
-                case STARTED:
-                    return reportOngoing(jobId);
-                case FINISHED:
-                case OTHER:
-                    switch (operation.getOperationType()) {
-                        case TERMINATE:
-                            //termination includes VNF deletion in ONAP terminology
-                            if (ongoingJobs.contains(jobId)) {
-                                return reportOngoing(jobId);
-                            } else {
-                                //the VNF must be queried again since it could have been deleted since the VNF has been terminated
-                                if (getVnf(vnfmId, vnfId).isPresent()) {
-                                    return reportFailed(jobId, "unable to delete VNF");
-                                } else {
-                                    return reportFinished(jobId);
-                                }
-                            }
-                        default:
-                            return reportFinished(jobId);
-                    }
-                default: //all cases handled
-                case FAILED:
-                    return reportFailed(jobId, operation.getError().getTitle() + ": " + operation.getError().getDetail());
-            }
+            return getJobDetailInfo(vnfmId, jobId, vnfId, operation);
         } catch (NoSuchElementException e) {
+            logger.warn("No operation could be identified for job with {} identifier", jobId, e);
             if (ongoingJobs.contains(jobId)) {
                 return reportOngoing(jobId);
             } else {
@@ -221,6 +209,34 @@ public class JobManager {
         }
     }
 
+    private JobDetailInfo getJobDetailInfo(String vnfmId, String jobId, String vnfId, OperationExecution operation) {
+        if (operation.getStatus() == STARTED) {
+            return reportOngoing(jobId);
+        } else if (operation.getStatus() == FAILED) {
+            return reportFailed(jobId, operation.getError().getTitle() + ": " + operation.getError().getDetail());
+        } else {
+            return getJobForTerminalOperationState(vnfmId, jobId, vnfId, operation);
+        }
+    }
+
+    private JobDetailInfo getJobForTerminalOperationState(String vnfmId, String jobId, String vnfId, OperationExecution operation) {
+        //termination includes VNF deletion in ONAP terminology
+        if (operation.getOperationType() == com.nokia.cbam.lcm.v32.model.OperationType.TERMINATE) {
+            if (ongoingJobs.contains(jobId)) {
+                return reportOngoing(jobId);
+            } else {
+                //the VNF must be queried again since it could have been deleted since the VNF has been terminated
+                if (getVnf(vnfmId, vnfId).isPresent()) {
+                    return reportFailed(jobId, "unable to delete VNF");
+                } else {
+                    return reportFinished(jobId);
+                }
+            }
+        } else {
+            return reportFinished(jobId);
+        }
+    }
+
     private JobDetailInfo buildJob(String jobId, JobResponseInfo... history) {
         JobDetailInfo job = new JobDetailInfo();
         job.setJobId(jobId);
@@ -247,62 +263,67 @@ public class JobManager {
     }
 
     private JobDetailInfo reportOngoing(String jobId) {
-        return buildJob(jobId, buildJobPart("Operation started", JobStatus.STARTED, 50, 1));
+        return buildJob(jobId, buildJobPart(OPERATION_STARTED_DESCRIPTION, JobStatus.STARTED, 50, 1));
     }
 
     private JobDetailInfo reportFailed(String jobId, String reason) {
         return buildJob(jobId,
-                buildJobPart("Operation started", JobStatus.STARTED, 50, 1),
+                buildJobPart(OPERATION_STARTED_DESCRIPTION, JobStatus.STARTED, 50, 1),
                 buildJobPart("Operation failed due to " + reason, JobStatus.ERROR, 100, 2)
         );
     }
 
     private JobDetailInfo reportFinished(String jobId) {
         return buildJob(jobId,
-                buildJobPart("Operation started", JobStatus.STARTED, 50, 1),
+                buildJobPart(OPERATION_STARTED_DESCRIPTION, JobStatus.STARTED, 50, 1),
                 buildJobPart("Operation finished", JobStatus.FINISHED, 100, 2)
         );
     }
 
-    private OperationExecution findOperationByJobId(String vnfmId, Optional<VnfInfo> vnf, String jobId) {
+    private OperationExecution findOperationByJobId(String vnfmId, VnfInfo vnf, String jobId) {
         OperationExecutionsApi cbamOperationExecutionApi = cbamRestApiProvider.getCbamOperationExecutionApi(vnfmId);
         //the operations are sorted so that the newest operations are queried first
         //performance optimization that usually the core system is interested in the operations executed last
-        if (vnf.get().getOperationExecutions() != null) {
-            for (OperationExecution operationExecution : LifecycleChangeNotificationManager.NEWEST_OPERATIONS_FIRST.sortedCopy(vnf.get().getOperationExecutions())) {
-                try {
-                    Object operationParams = cbamOperationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(operationExecution.getId(), NOKIA_LCM_API_VERSION);
-                    if (extractOnapJobId(operationParams).equals(jobId)) {
-                        return operationExecution;
-                    }
-                } catch (ApiException e) {
-                    logger.error("Unable to retrieve operation parameters", e);
-                    throw new RuntimeException(e);
-                }
-            }
+        if (vnf.getOperationExecutions() != null) {
+            List<OperationExecution> sortedOperation = NEWEST_OPERATIONS_FIRST.sortedCopy(vnf.getOperationExecutions());
+            return find(sortedOperation, operation -> isCurrentOperationTriggeredByJob(jobId, cbamOperationExecutionApi, operation));
         }
         throw new NoSuchElementException();
     }
 
+    private boolean isCurrentOperationTriggeredByJob(String jobId, OperationExecutionsApi cbamOperationExecutionApi, OperationExecution operationExecution) {
+        if (OperationType.MODIFY_INFO.equals(operationExecution.getOperationType())) {
+            //the modify info is never triggered by an external job
+            return false;
+        }
+        try {
+            Object operationParams = cbamOperationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(operationExecution.getId(), NOKIA_LCM_API_VERSION).blockingFirst();
+            if (extractOnapJobId(operationParams).equals(jobId)) {
+                return true;
+            }
+        } catch (Exception e) {
+            throw buildFatalFailure(logger, "Unable to retrieve operation parameters of operation with " + operationExecution.getId() + " identifier", e);
+        }
+        return false;
+    }
+
     private Optional<VnfInfo> getVnf(String vnfmId, String vnfId) {
         try {
             //test if the VNF exists (required to be able to distingush between failed request )
             VnfsApi cbamLcmApi = cbamRestApiProvider.getCbamLcmApi(vnfmId);
             logger.debug("Listing VNFs");
-            List<VnfInfo> vnfs = cbamLcmApi.vnfsGet(NOKIA_LCM_API_VERSION);
+            List<VnfInfo> vnfs = cbamLcmApi.vnfsGet(NOKIA_LCM_API_VERSION).blockingSingle();
             com.google.common.base.Optional<VnfInfo> vnf = tryFind(vnfs, vnfInfo -> vnfId.equals(vnfInfo.getId()));
             if (!vnf.isPresent()) {
-                logger.debug("VNF with " + vnfId + " is missing");
+                logger.debug("VNF with {} identifier is missing", vnfId);
                 return empty();
             } else {
-                logger.debug("VNF with " + vnfId + " still exists");
+                logger.debug("VNF with {} identifier still exists", vnfId);
                 //query the VNF again to get operation execution result
-                return of(cbamLcmApi.vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION));
+                return of(cbamLcmApi.vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION).blockingFirst());
             }
-        } catch (ApiException e) {
-            logger.error("Unable to retrieve VNF", e);
-            throw new RuntimeException(e);
+        } catch (Exception e) {
+            throw buildFatalFailure(logger, "Unable to retrieve VNF with " + vnfId + " identifier", e);
         }
     }
-
 }