From 6563ce72688dacd99c7badd0c9e94ad7fa22da23 Mon Sep 17 00:00:00 2001 From: FrancescoFioraEst Date: Tue, 28 May 2024 16:18:42 +0100 Subject: Remove Map in ACM-R for timeout Priming/Depriming Issue-ID: POLICY-5025 Change-Id: I779d57715a82986bd19f541bc88b12163362b396 Signed-off-by: FrancescoFioraEst --- .../concepts/AutomationCompositionDefinition.java | 6 +++- .../JpaAutomationCompositionDefinition.java | 11 ++++++-- .../persistence/provider/AcDefinitionProvider.java | 3 ++ .../provider/AcDefinitionProviderTest.java | 26 ++++++++++++++++++ .../commissioning/CommissioningProvider.java | 3 +- .../runtime/supervision/SupervisionScanner.java | 32 ++++++---------------- .../comm/ParticipantPrimePublisher.java | 4 +++ .../supervision/SupervisionScannerTest.java | 3 +- .../clamp/acm/runtime/util/CommonTestData.java | 1 + 9 files changed, 61 insertions(+), 28 deletions(-) diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionDefinition.java b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionDefinition.java index 548bc4549..987cb8832 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionDefinition.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionDefinition.java @@ -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 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; } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionDefinition.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionDefinition.java index 28689e2fd..1cab89d5d 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionDefinition.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionDefinition.java @@ -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 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()); diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProvider.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProvider.java index 9eb5e7a32..46b43f950 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProvider.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProvider.java @@ -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); diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProviderTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProviderTest.java index 1e067c8f6..85dadc3de 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProviderTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProviderTest.java @@ -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()); diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java index ad39a68d4..74ccb9cc6 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java @@ -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()); diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java index 881969a90..96e75df62 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java @@ -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 acTimeout = new TimeoutHandler<>(); private final Map 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 set = new HashSet<>(); - set.addAll(acDefinitionList - .stream().map(AutomationCompositionDefinition::getCompositionId).collect(Collectors.toSet())); var acList = automationCompositionProvider.getAcInstancesInTransition(); HashMap 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()); diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantPrimePublisher.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantPrimePublisher.java index 67246a5db..89763a2b6 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantPrimePublisher.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantPrimePublisher.java @@ -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 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 supportedElementMap = new HashMap<>(); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java index 7d0b4252a..8ed250fba 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java @@ -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); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java index 431a1ba55..e031e0f5a 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java @@ -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); -- cgit 1.2.3-korg