Merge branch 'recursive-orch'
[so.git] / bpmn / so-bpmn-tasks / src / main / java / org / onap / so / bpmn / infrastructure / workflow / tasks / WorkflowAction.java
old mode 100644 (file)
new mode 100755 (executable)
index 29206a6..35e1196
@@ -10,6 +10,8 @@
  * ================================================================================
  * Modifications Copyright (c) 2020 Tech Mahindra
  * ================================================================================
+ * Modifications Copyright (c) 2021 Orange
+ * ================================================================================
  * 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
 
 package org.onap.so.bpmn.infrastructure.workflow.tasks;
 
-import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.ASSIGNINSTANCE;
+import static org.onap.so.bpmn.infrastructure.service.composition.ServiceCompositionConstants.IS_CHILD_PROCESS;
+import static org.onap.so.bpmn.infrastructure.service.composition.ServiceCompositionConstants.PARENT_CORRELATION_ID;
+import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.ASSIGN_INSTANCE;
 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.CONTROLLER;
 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.CREATE_INSTANCE;
+import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.DELETE_INSTANCE;
 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.FABRIC_CONFIGURATION;
+import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.RECREATE_INSTANCE;
 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.REPLACEINSTANCE;
 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.REPLACEINSTANCERETAINASSIGNMENTS;
 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.SERVICE;
+import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.UPDATE_INSTANCE;
+import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.HEALTH_CHECK;
 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.WORKFLOW_ACTION_ERROR_MESSAGE;
+import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.UPGRADE_CNF;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.UUID;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.SerializationUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.camunda.bpm.engine.delegate.DelegateExecution;
 import org.javatuples.Pair;
 import org.onap.aai.domain.yang.Vnfc;
@@ -86,6 +99,7 @@ import org.springframework.core.env.Environment;
 import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.onap.so.serviceinstancebeans.InstanceDirection;
 
 @Component
 public class WorkflowAction {
@@ -279,14 +293,21 @@ public class WorkflowAction {
         List<Resource> resourceList = new ArrayList<>();
         List<Pair<WorkflowType, String>> aaiResourceIds = new ArrayList<>();
 
-        if (resourceType == WorkflowType.SERVICE) {
+        if (resourceType == WorkflowType.SERVICE || isVNFCreate(resourceType, requestAction)) {
             resourceList = serviceEBBLoader.getResourceListForService(sIRequest, requestAction, execution,
                     serviceInstanceId, resourceId, aaiResourceIds);
-        } else if (resourceType == WorkflowType.VNF && (REPLACEINSTANCE.equalsIgnoreCase(requestAction)
-                || ("recreateInstance".equalsIgnoreCase(requestAction)))) {
+        } else if (resourceType == WorkflowType.VNF
+                && (DELETE_INSTANCE.equalsIgnoreCase(requestAction) || REPLACEINSTANCE.equalsIgnoreCase(requestAction)
+                        || (RECREATE_INSTANCE.equalsIgnoreCase(requestAction)))) {
             vnfEBBLoader.traverseAAIVnf(execution, resourceList, workflowResourceIds.getServiceInstanceId(),
                     workflowResourceIds.getVnfId(), aaiResourceIds);
-        } else if (resourceType == WorkflowType.VNF && "updateInstance".equalsIgnoreCase(requestAction)) {
+        } else if (resourceType == WorkflowType.VNF && UPDATE_INSTANCE.equalsIgnoreCase(requestAction)) {
+            vnfEBBLoader.customTraverseAAIVnf(execution, resourceList, workflowResourceIds.getServiceInstanceId(),
+                    workflowResourceIds.getVnfId(), aaiResourceIds);
+        } else if (resourceType == WorkflowType.VNF && HEALTH_CHECK.equalsIgnoreCase(requestAction)) {
+            vnfEBBLoader.customTraverseAAIVnf(execution, resourceList, workflowResourceIds.getServiceInstanceId(),
+                    workflowResourceIds.getVnfId(), aaiResourceIds);
+        } else if (resourceType == WorkflowType.VNF && UPGRADE_CNF.equalsIgnoreCase(requestAction)) {
             vnfEBBLoader.customTraverseAAIVnf(execution, resourceList, workflowResourceIds.getServiceInstanceId(),
                     workflowResourceIds.getVnfId(), aaiResourceIds);
         } else {
@@ -315,22 +336,58 @@ public class WorkflowAction {
             logger.info("Sorting for Vlan Tagging");
             flowsToExecute = sortExecutionPathByObjectForVlanTagging(flowsToExecute, requestAction);
         }
+        logger.info("Building Block Execution Order");
+        for (ExecuteBuildingBlock block : flowsToExecute) {
+            Resource res = resourceList.stream()
+                    .filter(resource -> resource.getResourceId() == block.getBuildingBlock().getKey()).findAny()
+                    .orElse(null);
+            String log = "Block: " + block.getBuildingBlock().getBpmnFlowName();
+            if (res != null) {
+                log += ", Resource: " + res.getResourceType() + "[" + res.getResourceId() + "]";
+                log += ", Priority: " + res.getProcessingPriority();
+                if (res.getResourceType() == WorkflowType.VFMODULE)
+                    log += ", Base: " + res.isBaseVfModule();
+            }
+            if (block.getBuildingBlock().getBpmnScope() != null)
+                log += ", Scope: " + block.getBuildingBlock().getBpmnScope();
+            if (block.getBuildingBlock().getBpmnAction() != null)
+                log += ", Action: " + block.getBuildingBlock().getBpmnAction();
+            logger.info(log);
+        }
+
+        RelatedInstanceList[] instanceList = sIRequest.getRequestDetails().getRelatedInstanceList();
+        execution.setVariable(IS_CHILD_PROCESS, Boolean.FALSE);
+        if (instanceList != null) {
+            for (RelatedInstanceList relatedInstanceList : instanceList) {
+                RelatedInstance relatedInstance = relatedInstanceList.getRelatedInstance();
+                if (InstanceDirection.source.equals(relatedInstance.getInstanceDirection())) {
+                    execution.setVariable(IS_CHILD_PROCESS, Boolean.TRUE);
+                    execution.setVariable(PARENT_CORRELATION_ID, requestDetails.getRequestInfo().getCorrelator());
+                }
+            }
+        }
+
         // By default, enable homing at VNF level for CREATE_INSTANCE and ASSIGNINSTANCE
         if (resourceType == WorkflowType.SERVICE
-                && (requestAction.equals(CREATE_INSTANCE) || requestAction.equals(ASSIGNINSTANCE))
+                && (requestAction.equals(CREATE_INSTANCE) || requestAction.equals(ASSIGN_INSTANCE))
                 && resourceList.stream().anyMatch(x -> WorkflowType.VNF.equals(x.getResourceType()))) {
             execution.setVariable(HOMING, true);
             execution.setVariable("calledHoming", false);
         }
-        if (resourceType == WorkflowType.SERVICE && (requestAction.equalsIgnoreCase(ASSIGNINSTANCE)
+        if (resourceType == WorkflowType.SERVICE && (requestAction.equalsIgnoreCase(ASSIGN_INSTANCE)
                 || requestAction.equalsIgnoreCase(CREATE_INSTANCE))) {
             generateResourceIds(flowsToExecute, resourceList, serviceInstanceId);
         } else {
             updateResourceIdsFromAAITraversal(flowsToExecute, resourceList, aaiResourceIds, serviceInstanceId);
         }
+        execution.setVariable("resources", resourceList);
         return flowsToExecute;
     }
 
+    private boolean isVNFCreate(WorkflowType resourceType, String requestAction) {
+        return resourceType == WorkflowType.VNF && CREATE_INSTANCE.equalsIgnoreCase(requestAction);
+    }
+
     private void setExecutionVariables(DelegateExecution execution, List<ExecuteBuildingBlock> flowsToExecute,
             List<String> flowNames) {
         execution.setVariable("flowNames", flowNames);
@@ -409,7 +466,7 @@ public class WorkflowAction {
                 resourceId = modelInfo.getModelCustomizationId();
             }
         }
-        return new Resource(resourceType, resourceId, true);
+        return new Resource(resourceType, resourceId, true, null);
     }
 
     private String getCloudOwner(CloudConfiguration cloudConfiguration) {
@@ -638,11 +695,12 @@ public class WorkflowAction {
         for (Pair<WorkflowType, String> pair : aaiResourceIds) {
             logger.debug("{}, {}", pair.getValue0(), pair.getValue1());
         }
-
-        Arrays.stream(WorkflowType.values()).filter(type -> !type.equals(WorkflowType.SERVICE))
-                .forEach(type -> resourceList.stream().filter(resource -> type.equals(resource.getResourceType()))
-                        .forEach(resource -> updateWorkflowResourceIds(flowsToExecute, type, resource.getResourceId(),
-                                retrieveAAIResourceId(aaiResourceIds, type), null, serviceInstanceId)));
+        Map<Resource, String> resourceInstanceIds = new HashMap<>();
+        Arrays.stream(WorkflowType.values()).forEach(type -> resourceList.stream()
+                .filter(resource -> type.equals(resource.getResourceType())
+                        && !(WorkflowType.SERVICE.equals(type) && !resource.hasParent()))
+                .forEach(resource -> updateWorkflowResourceIds(flowsToExecute, type, resource,
+                        retrieveAAIResourceId(aaiResourceIds, type), null, serviceInstanceId, resourceInstanceIds)));
     }
 
     private String retrieveAAIResourceId(List<Pair<WorkflowType, String>> aaiResourceIds, WorkflowType resource) {
@@ -659,27 +717,53 @@ public class WorkflowAction {
 
     private void generateResourceIds(List<ExecuteBuildingBlock> flowsToExecute, List<Resource> resourceList,
             String serviceInstanceId) {
-        Arrays.stream(WorkflowType.values()).filter(type -> !type.equals(WorkflowType.SERVICE))
-                .forEach(type -> resourceList.stream().filter(resource -> type.equals(resource.getResourceType()))
-                        .forEach(resource -> updateWorkflowResourceIds(flowsToExecute, type, resource.getResourceId(),
-                                null, resource.getVirtualLinkKey(), serviceInstanceId)));
+        Map<Resource, String> resourceInstanceIds = new HashMap<>();
+        Arrays.stream(WorkflowType.values())
+                .forEach(type -> resourceList.stream()
+                        .filter(resource -> resource.hasParent() && type.equals(resource.getResourceType()))
+                        .forEach(resource -> updateWorkflowResourceIds(flowsToExecute, type, resource, null,
+                                resource.getVirtualLinkKey(), serviceInstanceId, resourceInstanceIds)));
     }
 
     protected void updateWorkflowResourceIds(List<ExecuteBuildingBlock> flowsToExecute, WorkflowType resourceType,
-            String key, String id, String virtualLinkKey, String serviceInstanceId) {
+            Resource resource, String id, String virtualLinkKey, String serviceInstanceId,
+            Map<Resource, String> resourceInstanceIds) {
+        String key = resource.getResourceId();
         String resourceId = id;
         if (resourceId == null) {
             resourceId = UUID.randomUUID().toString();
         }
+        resourceInstanceIds.put(resource, resourceId);
+        Set<String> assignedFlows = new LinkedHashSet<>();
         for (ExecuteBuildingBlock ebb : flowsToExecute) {
-            if (key != null && key.equalsIgnoreCase(ebb.getBuildingBlock().getKey()) && (ebb.getBuildingBlock()
-                    .getBpmnFlowName().contains(resourceType.toString())
-                    || (ebb.getBuildingBlock().getBpmnFlowName().contains(CONTROLLER)
-                            && ebb.getBuildingBlock().getBpmnScope().equalsIgnoreCase(resourceType.toString())))) {
+            String resourceTypeStr = resourceType.toString();
+            String flowName = ebb.getBuildingBlock().getBpmnFlowName();
+            String scope = StringUtils.defaultString(ebb.getBuildingBlock().getBpmnScope());
+            String action = StringUtils.defaultString(ebb.getBuildingBlock().getBpmnAction());
+
+            if (key != null && key.equalsIgnoreCase(ebb.getBuildingBlock().getKey())
+                    && isFlowAssignable(assignedFlows, ebb, resourceType, flowName + action)
+                    && (flowName.contains(resourceTypeStr)
+                            || (flowName.contains(CONTROLLER) && resourceTypeStr.equalsIgnoreCase(scope)))) {
                 WorkflowResourceIds workflowResourceIds = new WorkflowResourceIds();
                 workflowResourceIds.setServiceInstanceId(serviceInstanceId);
-                WorkflowResourceIdsUtils.setResourceIdByWorkflowType(workflowResourceIds, resourceType, resourceId);
+                Resource parent = resource.getParent();
+                if (resource.hasParent() && resourceInstanceIds.containsKey(parent)) {
+                    WorkflowResourceIdsUtils.setResourceIdByWorkflowType(workflowResourceIds, parent.getResourceType(),
+                            resourceInstanceIds.get(parent));
+                }
+                if (resource.hasParent() && WorkflowType.SERVICE.equals(resourceType)
+                        && WorkflowType.SERVICE.equals(parent.getResourceType())) {
+                    String childServiceInstanceId = resource.isGenerated() ? resourceId : resource.getResourceId();
+                    workflowResourceIds.setChildServiceInstanceId(childServiceInstanceId);
+                    workflowResourceIds.setChildServiceInstanceName(resource.getInstanceName());
+                } else {
+                    WorkflowResourceIdsUtils.setInstanceNameByWorkflowType(workflowResourceIds, resourceType,
+                            resource.getInstanceName());
+                    WorkflowResourceIdsUtils.setResourceIdByWorkflowType(workflowResourceIds, resourceType, resourceId);
+                }
                 ebb.setWorkflowResourceIds(workflowResourceIds);
+                assignedFlows.add(flowName + action);
             }
             if (virtualLinkKey != null && ebb.getBuildingBlock().isVirtualLink()
                     && virtualLinkKey.equalsIgnoreCase(ebb.getBuildingBlock().getVirtualLinkKey())) {
@@ -691,6 +775,14 @@ public class WorkflowAction {
         }
     }
 
+    private boolean isFlowAssignable(Set<String> assignedFlows, ExecuteBuildingBlock ebb, WorkflowType resourceType,
+            String assignedFlowName) {
+        String id = WorkflowType.SERVICE.equals(resourceType)
+                ? StringUtils.defaultString(ebb.getWorkflowResourceIds().getChildServiceInstanceId())
+                : WorkflowResourceIdsUtils.getResourceIdByWorkflowType(ebb.getWorkflowResourceIds(), resourceType);
+        return !assignedFlows.contains(assignedFlowName) && id.isEmpty();
+    }
+
     protected WorkflowResourceIds populateResourceIdsFromApiHandler(DelegateExecution execution) {
         return WorkflowResourceIdsUtils.getWorkflowResourceIdsFromExecution(execution);
     }
@@ -724,7 +816,7 @@ public class WorkflowAction {
                     type = action;
                 }
             }
-            return new Resource(WorkflowType.fromString(convertTypeFromPlural(type)), id, generated);
+            return new Resource(WorkflowType.fromString(convertTypeFromPlural(type)), id, generated, null);
         } else {
             throw new IllegalArgumentException("Uri could not be parsed: " + uri);
         }
@@ -887,7 +979,7 @@ public class WorkflowAction {
     protected boolean isRequestMacroServiceResume(boolean aLaCarte, WorkflowType resourceType, String requestAction,
             String serviceInstanceId) {
         return (!aLaCarte && resourceType == WorkflowType.SERVICE
-                && (requestAction.equalsIgnoreCase(ASSIGNINSTANCE) || requestAction.equalsIgnoreCase(CREATE_INSTANCE))
+                && (requestAction.equalsIgnoreCase(ASSIGN_INSTANCE) || requestAction.equalsIgnoreCase(CREATE_INSTANCE))
                 && (serviceInstanceId != null && serviceInstanceId.trim().length() > 1)
                 && (bbInputSetupUtils.getAAIServiceInstanceById(serviceInstanceId) != null));
     }