Remove Map in ACM-R for timeout Priming/Depriming 32/138132/1
authorFrancescoFioraEst <francesco.fiora@est.tech>
Tue, 28 May 2024 15:18:42 +0000 (16:18 +0100)
committerFrancescoFioraEst <francesco.fiora@est.tech>
Tue, 4 Jun 2024 09:40:23 +0000 (10:40 +0100)
Issue-ID: POLICY-5025
Change-Id: I779d57715a82986bd19f541bc88b12163362b396
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionDefinition.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionDefinition.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProvider.java
models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProviderTest.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantPrimePublisher.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java

index 548bc45..987cb88 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2022-2023 Nordix Foundation.
+ *  Copyright (C) 2022-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.
@@ -48,6 +48,9 @@ public class AutomationCompositionDefinition {
 
     private StateChangeResult stateChangeResult;
 
+    @NonNull
+    private String lastMsg;
+
     @NonNull
     // Map used to store prime state with key as NodeTemplate Name and value as NodeTemplateState
     private Map<String, NodeTemplateState> elementStateMap = new HashMap<>();
@@ -62,6 +65,7 @@ public class AutomationCompositionDefinition {
         this.serviceTemplate = new ToscaServiceTemplate(otherAcmDefinition.serviceTemplate);
         this.restarting = otherAcmDefinition.restarting;
         this.state = otherAcmDefinition.state;
+        this.lastMsg = otherAcmDefinition.lastMsg;
         this.elementStateMap = PfUtils.mapMap(otherAcmDefinition.elementStateMap, NodeTemplateState::new);
         this.stateChangeResult = otherAcmDefinition.stateChangeResult;
     }
index 28689e2..1cab89d 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2022-2023 Nordix Foundation.
+ *  Copyright (C) 2022-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.
@@ -33,6 +33,7 @@ import jakarta.persistence.JoinColumn;
 import jakarta.persistence.Lob;
 import jakarta.persistence.OneToMany;
 import jakarta.persistence.Table;
+import java.sql.Timestamp;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.UUID;
@@ -42,8 +43,8 @@ import lombok.NonNull;
 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
-import org.onap.policy.clamp.models.acm.document.base.ToscaServiceTemplateValidation;
 import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
 import org.onap.policy.common.parameters.BeanValidationResult;
 import org.onap.policy.common.parameters.annotations.NotNull;
 import org.onap.policy.common.parameters.annotations.Pattern;
@@ -87,6 +88,10 @@ public class JpaAutomationCompositionDefinition extends Validated
     @Column
     private StateChangeResult stateChangeResult;
 
+    @Column
+    @NotNull
+    private Timestamp lastMsg;
+
     @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
     @JoinColumn(name = "compositionId", foreignKey = @ForeignKey(name = "dt_element_fk"))
     private Set<JpaNodeTemplateState> elements = new HashSet<>();
@@ -105,6 +110,7 @@ public class JpaAutomationCompositionDefinition extends Validated
         acmDefinition.setRestarting(this.restarting);
         acmDefinition.setState(this.state);
         acmDefinition.setStateChangeResult(this.stateChangeResult);
+        acmDefinition.setLastMsg(this.lastMsg.toString());
         acmDefinition.setServiceTemplate(this.serviceTemplate.toAuthorative());
         for (var element : this.elements) {
             var key = element.getNodeTemplateId().getName();
@@ -119,6 +125,7 @@ public class JpaAutomationCompositionDefinition extends Validated
         this.restarting = copyConcept.getRestarting();
         this.state = copyConcept.getState();
         this.stateChangeResult = copyConcept.getStateChangeResult();
+        this.lastMsg = TimestampHelper.toTimestamp(copyConcept.getLastMsg());
         this.serviceTemplate = new DocToscaServiceTemplate(copyConcept.getServiceTemplate());
         setName(this.serviceTemplate.getName());
         setVersion(this.serviceTemplate.getVersion());
index 9eb5e7a..46b43f9 100644 (file)
@@ -37,6 +37,7 @@ import org.onap.policy.clamp.models.acm.persistence.concepts.JpaNodeTemplateStat
 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionDefinitionRepository;
 import org.onap.policy.clamp.models.acm.persistence.repository.NodeTemplateStateRepository;
 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
 import org.onap.policy.common.parameters.BeanValidationResult;
 import org.onap.policy.models.base.PfModelRuntimeException;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
@@ -68,6 +69,7 @@ public class AcDefinitionProvider {
         if (serviceTemplate.getMetadata() == null) {
             serviceTemplate.setMetadata(new HashMap<>());
         }
+        acmDefinition.setLastMsg(TimestampHelper.now());
         serviceTemplate.getMetadata().put("compositionId", compositionId);
         acmDefinition.setServiceTemplate(serviceTemplate);
         var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate, toscaElementName);
@@ -100,6 +102,7 @@ public class AcDefinitionProvider {
         var acmDefinition = new AutomationCompositionDefinition();
         acmDefinition.setCompositionId(compositionId);
         acmDefinition.setState(AcTypeState.COMMISSIONED);
+        acmDefinition.setLastMsg(TimestampHelper.now());
         acmDefinition.setServiceTemplate(serviceTemplate);
         var acElements =
                 AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate, toscaElementName);
index 1e067c8..85dadc3 100644 (file)
@@ -45,8 +45,10 @@ import org.onap.policy.clamp.models.acm.persistence.concepts.JpaNodeTemplateStat
 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionDefinitionRepository;
 import org.onap.policy.clamp.models.acm.persistence.repository.NodeTemplateStateRepository;
 import org.onap.policy.clamp.models.acm.utils.CommonTestData;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate;
 import org.springframework.data.domain.Example;
 
 class AcDefinitionProviderTest {
@@ -62,6 +64,29 @@ class AcDefinitionProviderTest {
 
     private static ToscaServiceTemplate inputServiceTemplate;
 
+    @Test
+    void testBadRequest() {
+        var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
+
+        var compositionId = UUID.randomUUID();
+        var serviceTemplate = new ToscaServiceTemplate();
+        serviceTemplate.setToscaTopologyTemplate(new ToscaTopologyTemplate());
+        serviceTemplate.getToscaTopologyTemplate().setNodeTemplates(new HashMap<>());
+        assertThatThrownBy(() -> acDefinitionProvider.updateServiceTemplate(compositionId, serviceTemplate,
+                "ElementName", "CompositionName"))
+                .hasMessageMatching("NodeTemplate with element type ElementName must exist!");
+
+        var docServiceTemplate = new DocToscaServiceTemplate(inputServiceTemplate);
+        var acmDefinition = getAcDefinition(docServiceTemplate);
+        assertThatThrownBy(() -> acDefinitionProvider.updateAcDefinition(acmDefinition, "CompositionName"))
+                .hasMessageStartingWith("\"AutomationCompositionDefinition\" INVALID, item has status INVALID");
+
+        assertThatThrownBy(() -> acDefinitionProvider.updateAcDefinitionState(compositionId, AcTypeState.PRIMED,
+                StateChangeResult.NO_ERROR, false))
+                .hasMessageStartingWith("update of Automation Composition Definition");
+    }
+
     @BeforeAll
     static void loadServiceTemplate() {
         inputServiceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
@@ -304,6 +329,7 @@ class AcDefinitionProviderTest {
         var acmDefinition = new AutomationCompositionDefinition();
         acmDefinition.setCompositionId(UUID.randomUUID());
         acmDefinition.setState(AcTypeState.COMMISSIONED);
+        acmDefinition.setLastMsg(TimestampHelper.now());
         acmDefinition.setServiceTemplate(docServiceTemplate.toAuthorative());
         var nodeTemplateState = new NodeTemplateState();
         nodeTemplateState.setNodeTemplateStateId(UUID.randomUUID());
index ad39a68..74ccb9c 100644 (file)
@@ -39,6 +39,7 @@ import org.onap.policy.clamp.models.acm.messages.rest.commissioning.Commissionin
 import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
 import org.onap.policy.clamp.models.acm.persistence.provider.AcTypeStateResolver;
 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
 import org.onap.policy.models.base.PfModelRuntimeException;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplates;
@@ -209,7 +210,6 @@ public class CommissioningProvider {
     }
 
     private void prime(AutomationCompositionDefinition acmDefinition) {
-        acmDefinition.setStateChangeResult(StateChangeResult.NO_ERROR);
         var preparation = participantPrimePublisher.prepareParticipantPriming(acmDefinition);
         acDefinitionProvider.updateAcDefinition(acmDefinition,
                 acRuntimeParameterGroup.getAcmParameters().getToscaCompositionName());
@@ -232,6 +232,7 @@ public class CommissioningProvider {
             acmParticipantProvider.verifyParticipantState(participantIds);
         }
         acmDefinition.setState(AcTypeState.DEPRIMING);
+        acmDefinition.setLastMsg(TimestampHelper.now());
         acDefinitionProvider.updateAcDefinition(acmDefinition,
                 acRuntimeParameterGroup.getAcmParameters().getToscaCompositionName());
 
index 881969a..96e75df 100644 (file)
@@ -23,9 +23,7 @@
 package org.onap.policy.clamp.acm.runtime.supervision;
 
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
-import java.util.Set;
 import java.util.UUID;
 import java.util.stream.Collectors;
 import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
@@ -40,6 +38,7 @@ import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
 import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -55,6 +54,8 @@ public class SupervisionScanner {
     private final TimeoutHandler<UUID> acTimeout = new TimeoutHandler<>();
     private final Map<UUID, Integer> phaseMap = new HashMap<>();
 
+    private final long maxStatusWaitMs;
+
     private final AutomationCompositionProvider automationCompositionProvider;
     private final AcDefinitionProvider acDefinitionProvider;
     private final AutomationCompositionStateChangePublisher automationCompositionStateChangePublisher;
@@ -80,6 +81,7 @@ public class SupervisionScanner {
         this.automationCompositionDeployPublisher = automationCompositionDeployPublisher;
 
         acTimeout.setMaxWaitMs(acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs());
+        this.maxStatusWaitMs = acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs();
     }
 
     /**
@@ -92,9 +94,6 @@ public class SupervisionScanner {
         for (var acDefinition : acDefinitionList) {
             scanAutomationCompositionDefinition(acDefinition);
         }
-        Set<UUID> set = new HashSet<>();
-        set.addAll(acDefinitionList
-            .stream().map(AutomationCompositionDefinition::getCompositionId).collect(Collectors.toSet()));
 
         var acList = automationCompositionProvider.getAcInstancesInTransition();
         HashMap<UUID, AutomationCompositionDefinition> acDefinitionMap = new HashMap<>();
@@ -106,8 +105,7 @@ public class SupervisionScanner {
             }
             scanAutomationComposition(automationComposition, acDefinition.getServiceTemplate());
         }
-        set.addAll(
-            acList.stream().map(AutomationComposition::getInstanceId).collect(Collectors.toSet()));
+        var set = acList.stream().map(AutomationComposition::getInstanceId).collect(Collectors.toSet());
         acTimeout.removeIfNotPresent(set);
 
         LOGGER.debug("Automation composition scan complete . . .");
@@ -116,19 +114,9 @@ public class SupervisionScanner {
     private void scanAutomationCompositionDefinition(AutomationCompositionDefinition acDefinition) {
         if (StateChangeResult.FAILED.equals(acDefinition.getStateChangeResult())) {
             LOGGER.debug("automation definition {} scanned, OK", acDefinition.getCompositionId());
-
-            // Clear Timeout on ac Definition
-            acTimeout.remove(acDefinition.getCompositionId());
             return;
         }
 
-        if (acTimeout.isTimeout(acDefinition.getCompositionId())
-                && StateChangeResult.NO_ERROR.equals(acDefinition.getStateChangeResult())) {
-            // retry by the user
-            LOGGER.debug("clearing Timeout for the ac definition");
-            acTimeout.clear(acDefinition.getCompositionId());
-        }
-
         boolean completed = true;
         var finalState = AcTypeState.PRIMING.equals(acDefinition.getState())
             || AcTypeState.PRIMED.equals(acDefinition.getState()) ? AcTypeState.PRIMED : AcTypeState.COMMISSIONED;
@@ -140,7 +128,6 @@ public class SupervisionScanner {
         if (completed) {
             acDefinitionProvider.updateAcDefinitionState(acDefinition.getCompositionId(), finalState,
                 StateChangeResult.NO_ERROR, null);
-            acTimeout.remove(acDefinition.getCompositionId());
         } else {
             handleTimeout(acDefinition);
         }
@@ -252,15 +239,14 @@ public class SupervisionScanner {
     }
 
     private void handleTimeout(AutomationCompositionDefinition acDefinition) {
-        var compositionId = acDefinition.getCompositionId();
-        if (acTimeout.isTimeout(compositionId)) {
+        if (StateChangeResult.TIMEOUT.equals(acDefinition.getStateChangeResult())) {
             LOGGER.debug("The ac definition is in timeout {}", acDefinition.getCompositionId());
             return;
         }
-
-        if (acTimeout.getDuration(compositionId) > acTimeout.getMaxWaitMs()) {
+        var now = TimestampHelper.nowEpochMilli();
+        var lastMsg = TimestampHelper.toEpochMilli(acDefinition.getLastMsg());
+        if ((now - lastMsg) > maxStatusWaitMs) {
             LOGGER.debug("Report timeout for the ac definition {}", acDefinition.getCompositionId());
-            acTimeout.setTimeout(compositionId);
             acDefinition.setStateChangeResult(StateChangeResult.TIMEOUT);
             acDefinitionProvider.updateAcDefinitionState(acDefinition.getCompositionId(),
                 acDefinition.getState(), acDefinition.getStateChangeResult(), acDefinition.getRestarting());
index 67246a5..89763a2 100644 (file)
@@ -35,9 +35,11 @@ import org.onap.policy.clamp.acm.runtime.participants.AcmParticipantProvider;
 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
 import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition;
+import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
 import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrime;
 import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -84,7 +86,9 @@ public class ParticipantPrimePublisher extends AbstractParticipantPublisher<Part
      * @return list of ParticipantDefinition
      */
     public List<ParticipantDefinition> prepareParticipantPriming(AutomationCompositionDefinition acmDefinition) {
+        acmDefinition.setStateChangeResult(StateChangeResult.NO_ERROR);
         acmDefinition.setState(AcTypeState.PRIMING);
+        acmDefinition.setLastMsg(TimestampHelper.now());
         var acElements = AcmUtils.extractAcElementsFromServiceTemplate(acmDefinition.getServiceTemplate(),
                 acRuntimeParameterGroup.getAcmParameters().getToscaElementName());
         Map<ToscaConceptIdentifier, UUID> supportedElementMap = new HashMap<>();
index 7d0b425..8ed250f 100644 (file)
@@ -24,7 +24,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -51,6 +50,7 @@ import org.onap.policy.clamp.models.acm.concepts.NodeTemplateState;
 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
 import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
 
 class SupervisionScannerTest {
@@ -66,6 +66,7 @@ class SupervisionScannerTest {
         acDefinition.setState(acTypeState);
         acDefinition.setStateChangeResult(stateChangeResult);
         acDefinition.setCompositionId(compositionId);
+        acDefinition.setLastMsg(TimestampHelper.now());
         acDefinition.setServiceTemplate(serviceTemplate);
         var node = new NodeTemplateState();
         node.setState(AcTypeState.PRIMING);
index 431a1ba..e031e0f 100644 (file)
@@ -121,6 +121,7 @@ public class CommonTestData {
         var acDefinition = new AutomationCompositionDefinition();
         acDefinition.setCompositionId(UUID.randomUUID());
         acDefinition.setState(state);
+        acDefinition.setLastMsg(TimestampHelper.now());
         acDefinition.setServiceTemplate(serviceTemplate);
         var acElements = AcmUtils
                 .extractAcElementsFromServiceTemplate(serviceTemplate, TOSCA_ELEMENT_NAME);