Allow migration to be performed in stages in ACM model 81/138581/1
authorFrancescoFioraEst <francesco.fiora@est.tech>
Fri, 26 Jul 2024 10:22:52 +0000 (11:22 +0100)
committerFrancesco Fiora <francesco.fiora@est.tech>
Fri, 26 Jul 2024 11:54:36 +0000 (11:54 +0000)
Issue-ID: POLICY-5089
Change-Id: I5192028cc4c7bc8a5744be0675fdea422dc49c1e
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionElement.java
models/src/main/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtils.java
models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionDeployAck.java
models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionMigration.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionElement.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java
models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java
models/src/test/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtilsTest.java
models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionElementTest.java
models/src/test/resources/examples/acm/test-pm-subscription-handling.yaml

index 16398e5..7d3acaa 100644 (file)
@@ -58,6 +58,8 @@ public class AutomationCompositionElement {
     @NonNull
     private SubState subState = SubState.NONE;
 
+    private Integer stage;
+
     private String operationalState;
     private String useState;
     private String description;
@@ -87,6 +89,7 @@ public class AutomationCompositionElement {
         this.subState = otherElement.subState;
         this.operationalState = otherElement.operationalState;
         this.useState = otherElement.useState;
+        this.stage = otherElement.stage;
         this.message = otherElement.message;
     }
 }
index d6079d0..9c827d7 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2023 Nordix Foundation.
+ *  Copyright (C) 2021-2024 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 package org.onap.policy.clamp.models.acm.concepts;
 
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
@@ -50,8 +54,26 @@ public final class ParticipantUtils {
         }
 
         return DeployState.DEPLOYING.equals(automationComposition.getDeployState())
-            || LockState.UNLOCKING.equals(automationComposition.getLockState()) ? minStartPhase
-                : maxStartPhase;
+            || LockState.UNLOCKING.equals(automationComposition.getLockState()) ? minStartPhase : maxStartPhase;
+    }
+
+    /**
+     * Get the First Stage.
+     *
+     * @param automationComposition the automation composition
+     * @param toscaServiceTemplate the ToscaServiceTemplate
+     * @return the First stage
+     */
+    public static int getFirstStage(
+        AutomationComposition automationComposition, ToscaServiceTemplate toscaServiceTemplate) {
+        Set<Integer> minStage = new HashSet<>();
+        for (var element : automationComposition.getElements().values()) {
+            var toscaNodeTemplate = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates()
+                .get(element.getDefinition().getName());
+            var stage = ParticipantUtils.findStageSet(toscaNodeTemplate.getProperties());
+            minStage.addAll(stage);
+        }
+        return minStage.stream().min(Integer::compare).orElse(0);
     }
 
     /**
@@ -63,8 +85,25 @@ public final class ParticipantUtils {
     public static int findStartPhase(Map<String, Object> properties) {
         var objStartPhase = properties.get("startPhase");
         if (objStartPhase != null) {
-            return Integer.valueOf(objStartPhase.toString());
+            return Integer.parseInt(objStartPhase.toString());
         }
         return 0;
     }
+
+
+    /**
+     * Finds stage from a map of properties.
+     *
+     * @param properties Map of properties
+     * @return stage
+     */
+    public static Set<Integer> findStageSet(Map<String, Object> properties) {
+        var objStage = properties.get("stage");
+        if (objStage instanceof List<?> stageSet) {
+            return stageSet.stream()
+                .map(obj -> Integer.valueOf(obj.toString()))
+                .collect(Collectors.toSet());
+        }
+        return Set.of(0);
+    }
 }
index 2c7d51f..9807ff9 100644 (file)
@@ -41,7 +41,7 @@ import org.onap.policy.models.base.PfUtils;
 public class AutomationCompositionDeployAck extends ParticipantAckMessage {
 
     private UUID automationCompositionId;
-    private Integer startPhase;
+    private Integer stage;
 
     // A map with AutomationCompositionElementID as its key, and a pair of result and message as value per
     // AutomationCompositionElement.
@@ -63,7 +63,7 @@ public class AutomationCompositionDeployAck extends ParticipantAckMessage {
     public AutomationCompositionDeployAck(final AutomationCompositionDeployAck source) {
         super(source);
         this.automationCompositionId = source.automationCompositionId;
-        this.startPhase = source.startPhase;
+        this.stage = source.stage;
         this.automationCompositionResultMap =
             PfUtils.mapMap(source.automationCompositionResultMap, UnaryOperator.identity());
     }
index 6ae812c..2d7608a 100644 (file)
@@ -38,6 +38,7 @@ public class AutomationCompositionMigration extends ParticipantMessage {
     private List<ParticipantDeploy> participantUpdatesList = new ArrayList<>();
 
     private Boolean precheck = false;
+    private Integer stage = 0;
 
     public AutomationCompositionMigration() {
         super(ParticipantMessageType.AUTOMATION_COMPOSITION_MIGRATION);
index 79ca961..e511ba1 100644 (file)
@@ -104,6 +104,9 @@ public class JpaAutomationCompositionElement extends Validated
     @Column
     private String useState;
 
+    @Column
+    private Integer stage;
+
     @Column
     private String description;
 
@@ -185,6 +188,7 @@ public class JpaAutomationCompositionElement extends Validated
         this.subState = copyConcept.subState;
         this.operationalState = copyConcept.operationalState;
         this.useState = copyConcept.useState;
+        this.stage = copyConcept.stage;
         this.message = copyConcept.message;
     }
 
@@ -213,6 +217,7 @@ public class JpaAutomationCompositionElement extends Validated
         element.setSubState(subState);
         element.setOperationalState(operationalState);
         element.setUseState(useState);
+        element.setStage(stage);
         element.setMessage(message);
 
         return element;
@@ -231,6 +236,7 @@ public class JpaAutomationCompositionElement extends Validated
         this.subState = element.getSubState();
         this.operationalState = element.getOperationalState();
         this.useState = element.getUseState();
+        this.stage = element.getStage();
         this.message = element.getMessage();
     }
 
@@ -288,6 +294,11 @@ public class JpaAutomationCompositionElement extends Validated
             return result;
         }
 
+        result = ObjectUtils.compare(stage, other.stage);
+        if (result != 0) {
+            return result;
+        }
+
         result = ObjectUtils.compare(operationalState, other.operationalState);
         if (result != 0) {
             return result;
index 9b73648..2d532b4 100644 (file)
@@ -262,6 +262,7 @@ public class AutomationCompositionProvider {
         jpaAcElement.setDeployState(element.getDeployState());
         jpaAcElement.setLockState(element.getLockState());
         jpaAcElement.setSubState(element.getSubState());
+        jpaAcElement.setStage(element.getStage());
         jpaAcElement.setRestarting(element.getRestarting());
 
         ProviderUtils.validate(element, jpaAcElement, "AutomationCompositionElement");
index 50b8d14..aaf41dd 100644 (file)
@@ -413,6 +413,7 @@ public final class AcmUtils {
             element.setLockState(lockState);
             element.setSubState(subState);
             element.setMessage(null);
+            element.setStage(null);
         }
     }
 
index 6bb7f1e..bac0842 100644 (file)
@@ -46,10 +46,32 @@ class ParticipantUtilsTest {
 
     @Test
     void testGetFirstStartPhase() throws CoderException {
+        var serviceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML);
+        var automationComposition =
+            CODER.decode(ResourceUtils.getResourceAsString(AUTOMATION_COMPOSITION_JSON), AutomationCompositions.class)
+                    .getAutomationCompositionList().get(0);
+        automationComposition.setDeployState(DeployState.DEPLOYING);
+        automationComposition.setLockState(LockState.NONE);
+        var result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate);
+        assertThat(result).isZero();
+
+        automationComposition.setDeployState(DeployState.DEPLOYED);
+        automationComposition.setLockState(LockState.UNLOCKING);
+        result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate);
+        assertThat(result).isZero();
+
+        automationComposition.setDeployState(DeployState.UNDEPLOYING);
+        automationComposition.setLockState(LockState.NONE);
+        result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate);
+        assertThat(result).isEqualTo(1);
+    }
+
+    @Test
+    void testGetFirstStage() throws CoderException {
         var serviceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML);
         var automationCompositions =
             CODER.decode(ResourceUtils.getResourceAsString(AUTOMATION_COMPOSITION_JSON), AutomationCompositions.class);
-        var result = ParticipantUtils.getFirstStartPhase(automationCompositions.getAutomationCompositionList().get(0),
+        var result = ParticipantUtils.getFirstStage(automationCompositions.getAutomationCompositionList().get(0),
             serviceTemplate);
         assertThat(result).isZero();
     }
index 609d4c1..fab3dac 100644 (file)
@@ -217,6 +217,11 @@ class JpaAutomationCompositionElementTest {
         testJpaAcElement.setOperationalState("DEFAULT");
         assertEquals(0, testJpaAcElement.compareTo(otherJpaAcElement));
 
+        testJpaAcElement.setStage(1);
+        assertNotEquals(0, testJpaAcElement.compareTo(otherJpaAcElement));
+        testJpaAcElement.setStage(null);
+        assertEquals(0, testJpaAcElement.compareTo(otherJpaAcElement));
+
         testJpaAcElement.setMessage("Message");
         assertNotEquals(0, testJpaAcElement.compareTo(otherJpaAcElement));
         testJpaAcElement.setMessage(null);
index 2b0b4fe..6539a9c 100644 (file)
@@ -317,6 +317,15 @@ node_types:
       provider:
         type: string
         required: false
+      stage:
+        type: array
+        required: false
+        items:
+          type: integer
+          constraints:
+            - greater-or-equal: 0
+        metadata:
+          common: true
       startPhase:
         type: integer
         required: false
@@ -394,6 +403,7 @@ topology_template:
       description: Participant for DCAE microservices
       properties:
         provider: ONAP
+        startPhase: 0
     org.onap.policy.acm.PolicyAutomationCompositionParticipant:
       version: 2.3.1
       type: org.onap.policy.clamp.acm.Participant
@@ -401,6 +411,7 @@ topology_template:
       description: Participant for DCAE microservices
       properties:
         provider: ONAP
+        startPhase: 0
     org.onap.ccsdk.cds.acm.CdsAutomationCompositionParticipant:
       version: 2.2.1
       type: org.onap.policy.clamp.acm.Participant
@@ -408,6 +419,7 @@ topology_template:
       description: Participant for DCAE microservices
       properties:
         provider: ONAP
+        startPhase: 1
     org.onap.domain.pmsh.PMSH_DCAEMicroservice:
       version: 1.2.3
       type: org.onap.policy.clamp.acm.DCAEMicroserviceAutomationCompositionElement
@@ -415,6 +427,7 @@ topology_template:
       description: Automation composition element for the DCAE microservice for Performance Management Subscription Handling
       properties:
         provider: Ericsson
+        startPhase: 1
         dcae_blueprint:
           tosca_definitions_version: cloudify_dsl_1_3
           imports:
@@ -641,6 +654,7 @@ topology_template:
           version: 1.0.0
         policy_id:
           get_input: pmsh_monitoring_policy
+        stage: [0,1,2]
     org.onap.domain.pmsh.PMSH_OperationalPolicyAutomationCompositionElement:
       version: 1.2.3
       type: org.onap.policy.clamp.acm.PolicyAutomationCompositionElement