From ef0a60deb046c5bf5ed1a6209493dfde6a6457a9 Mon Sep 17 00:00:00 2001 From: FrancescoFioraEst Date: Tue, 4 Jul 2023 09:26:41 +0100 Subject: Add restart support inside participants Issue-ID: POLICY-4747 Change-Id: I09ca3e373f8271fbfe612c031920058b744cf413 Signed-off-by: FrancescoFioraEst --- .../AutomationCompositionElementHandler.java | 40 +++++++++++- .../a1pms/handler/AcElementHandlerTest.java | 63 ++++++++++++++++++ .../AutomationCompositionElementHandler.java | 23 +++++++ .../http/handler/AcElementHandlerTest.java | 44 +++++++++++++ .../AutomationCompositionElementHandler.java | 40 +++++++++++- .../kserve/handler/AcElementHandlerTest.java | 44 +++++++++++++ .../AutomationCompositionElementHandler.java | 37 +++++++++++ .../AutomationCompositionElementHandlerTest.java | 75 ++++++++++++++++------ .../kubernetes/parameters/CommonTestData.java | 18 ++++++ .../AutomationCompositionElementHandler.java | 32 +++++++++ .../AutomationCompositionElementHandlerTest.java | 49 ++++++++++++++ .../AutomationCompositionElementHandler.java | 58 ++++++++++++++++- .../AutomationCompositionElementHandlerTest.java | 68 +++++++++++++++++++- .../api/AutomationCompositionElementListener.java | 10 +++ .../api/ParticipantIntermediaryApi.java | 16 ++++- .../api/impl/ParticipantIntermediaryApiImpl.java | 11 ++++ .../intermediary/handler/ThreadHandler.java | 44 ++++++++++++- .../impl/ParticipantIntermediaryApiImplTest.java | 17 ++++- .../handler/DummyAcElementListener.java | 16 ++++- .../intermediary/handler/ThreadHandlerTest.java | 27 ++++++++ 20 files changed, 700 insertions(+), 32 deletions(-) diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AutomationCompositionElementHandler.java index d653c5ad3..e2a5367f6 100755 --- a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AutomationCompositionElementHandler.java +++ b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AutomationCompositionElementHandler.java @@ -21,10 +21,10 @@ package org.onap.policy.clamp.acm.participant.a1pms.handler; import java.lang.invoke.MethodHandles; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import javax.validation.Validation; import javax.validation.ValidationException; import lombok.AccessLevel; @@ -42,6 +42,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDef import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; @@ -67,7 +68,7 @@ public class AutomationCompositionElementHandler implements AutomationCompositio // Map of acElement Id and A1PMS services @Getter(AccessLevel.PACKAGE) - private final Map configRequestMap = new HashMap<>(); + private final Map configRequestMap = new ConcurrentHashMap<>(); /** * Handle a automation composition element state change. @@ -162,4 +163,39 @@ public class AutomationCompositionElementHandler implements AutomationCompositio intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); } + + @Override + public void handleRestartComposition(UUID compositionId, + List elementDefinitionList, AcTypeState state) + throws PfModelException { + var finalState = AcTypeState.PRIMED.equals(state) || AcTypeState.PRIMING.equals(state) ? AcTypeState.PRIMED + : AcTypeState.COMMISSIONED; + intermediaryApi.updateCompositionState(compositionId, finalState, StateChangeResult.NO_ERROR, "Restarted"); + } + + @Override + public void handleRestartInstance(UUID automationCompositionId, AcElementDeploy element, + Map properties, DeployState deployState, LockState lockState) throws PfModelException { + if (DeployState.DEPLOYING.equals(deployState)) { + deploy(automationCompositionId, element, properties); + return; + } + if (DeployState.UNDEPLOYING.equals(deployState) || DeployState.DEPLOYED.equals(deployState) + || DeployState.UPDATING.equals(deployState)) { + try { + var configurationEntity = CODER.convert(properties, ConfigurationEntity.class); + configRequestMap.put(element.getId(), configurationEntity); + } catch (ValidationException | CoderException e) { + throw new A1PolicyServiceException(HttpStatus.SC_BAD_REQUEST, "Invalid Configuration", e); + } + } + if (DeployState.UNDEPLOYING.equals(deployState)) { + undeploy(automationCompositionId, element.getId()); + return; + } + deployState = AcmUtils.deployCompleted(deployState); + lockState = AcmUtils.lockCompleted(deployState, lockState); + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), deployState, + lockState, StateChangeResult.NO_ERROR, "Restarted"); + } } diff --git a/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AcElementHandlerTest.java b/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AcElementHandlerTest.java index 50f493299..dec11fd4e 100755 --- a/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AcElementHandlerTest.java +++ b/participant/participant-impl/participant-impl-a1pms/src/test/java/org/onap/policy/clamp/acm/participant/a1pms/handler/AcElementHandlerTest.java @@ -213,4 +213,67 @@ class AcElementHandlerTest { verify(participantIntermediaryApi).updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); } + + @Test + void testHandleRestartComposition() throws PfModelException { + var participantIntermediaryApi = mock(ParticipantIntermediaryApi.class); + var automationCompositionElementHandler = + new AutomationCompositionElementHandler(participantIntermediaryApi, acA1PmsClient); + + var compositionId = UUID.randomUUID(); + automationCompositionElementHandler.handleRestartComposition(compositionId, List.of(), AcTypeState.PRIMED); + + verify(participantIntermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, + StateChangeResult.NO_ERROR, "Restarted"); + } + + @Test + void testHandleRestartInstanceDeploying() throws PfModelException { + var participantIntermediaryApi = mock(ParticipantIntermediaryApi.class); + var automationCompositionElementHandler = + new AutomationCompositionElementHandler(participantIntermediaryApi, acA1PmsClient); + + var automationCompositionId = UUID.randomUUID(); + var element = commonTestData.getAutomationCompositionElement(); + var automationCompositionElementId = element.getId(); + var nodeTemplatesMap = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + automationCompositionElementHandler.handleRestartInstance(automationCompositionId, element, + nodeTemplatesMap.get(A1_AUTOMATION_COMPOSITION_ELEMENT).getProperties(), DeployState.DEPLOYING, + LockState.NONE); + verify(participantIntermediaryApi).updateAutomationCompositionElementState(automationCompositionId, + automationCompositionElementId, DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); + } + + @Test + void testHandleRestartInstanceDeployed() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var automationCompositionElementHandler = + new AutomationCompositionElementHandler(intermediaryApi, acA1PmsClient); + + var automationCompositionId = UUID.randomUUID(); + var element = commonTestData.getAutomationCompositionElement(); + var nodeTemplatesMap = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + automationCompositionElementHandler.handleRestartInstance(automationCompositionId, element, + nodeTemplatesMap.get(A1_AUTOMATION_COMPOSITION_ELEMENT).getProperties(), DeployState.DEPLOYED, + LockState.LOCKED); + verify(intermediaryApi).updateAutomationCompositionElementState(automationCompositionId, element.getId(), + DeployState.DEPLOYED, LockState.LOCKED, StateChangeResult.NO_ERROR, "Restarted"); + } + + @Test + void testHandleRestartInstanceUndeployed() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var automationCompositionElementHandler = + new AutomationCompositionElementHandler(intermediaryApi, acA1PmsClient); + + var automationCompositionId = UUID.randomUUID(); + var element = commonTestData.getAutomationCompositionElement(); + var automationCompositionElementId = element.getId(); + var nodeTemplatesMap = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + automationCompositionElementHandler.handleRestartInstance(automationCompositionId, element, + nodeTemplatesMap.get(A1_AUTOMATION_COMPOSITION_ELEMENT).getProperties(), DeployState.UNDEPLOYING, + LockState.LOCKED); + verify(intermediaryApi).updateAutomationCompositionElementState(automationCompositionId, + automationCompositionElementId, DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); + } } diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/main/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/main/handler/AutomationCompositionElementHandler.java index e3ebf3bef..9d4718bea 100644 --- a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/main/handler/AutomationCompositionElementHandler.java +++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/main/handler/AutomationCompositionElementHandler.java @@ -39,6 +39,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDef import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; @@ -156,4 +157,26 @@ public class AutomationCompositionElementHandler implements AutomationCompositio intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); } + + @Override + public void handleRestartComposition(UUID compositionId, + List elementDefinitionList, AcTypeState state) + throws PfModelException { + var finalState = AcTypeState.PRIMED.equals(state) || AcTypeState.PRIMING.equals(state) ? AcTypeState.PRIMED + : AcTypeState.COMMISSIONED; + intermediaryApi.updateCompositionState(compositionId, finalState, StateChangeResult.NO_ERROR, "Restarted"); + } + + @Override + public void handleRestartInstance(UUID automationCompositionId, AcElementDeploy element, + Map properties, DeployState deployState, LockState lockState) throws PfModelException { + if (DeployState.DEPLOYING.equals(deployState)) { + deploy(automationCompositionId, element, properties); + return; + } + deployState = AcmUtils.deployCompleted(deployState); + lockState = AcmUtils.lockCompleted(deployState, lockState); + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), deployState, + lockState, StateChangeResult.NO_ERROR, "Restarted"); + } } diff --git a/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/acm/participant/http/handler/AcElementHandlerTest.java b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/acm/participant/http/handler/AcElementHandlerTest.java index f0f991302..de0d21e6d 100644 --- a/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/acm/participant/http/handler/AcElementHandlerTest.java +++ b/participant/participant-impl/participant-impl-http/src/test/java/org/onap/policy/clamp/acm/participant/http/handler/AcElementHandlerTest.java @@ -196,4 +196,48 @@ class AcElementHandlerTest { verify(participantIntermediaryApi).updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); } + + @Test + void testHandleRestartComposition() throws PfModelException { + var participantIntermediaryApi = mock(ParticipantIntermediaryApi.class); + var automationCompositionElementHandler = + new AutomationCompositionElementHandler(participantIntermediaryApi, mock(AcHttpClient.class)); + + var compositionId = UUID.randomUUID(); + automationCompositionElementHandler.handleRestartComposition(compositionId, List.of(), AcTypeState.PRIMED); + verify(participantIntermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, + StateChangeResult.NO_ERROR, "Restarted"); + } + + @Test + void testHandleRestartInstanceDeploying() throws PfModelException { + var serviceTemplate = ToscaUtils.readAutomationCompositionFromTosca(); + var nodeTemplatesMap = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + var map = new HashMap<>(nodeTemplatesMap.get(HTTP_AUTOMATION_COMPOSITION_ELEMENT).getProperties()); + var element = commonTestData.getAutomationCompositionElement(); + map.putAll(element.getProperties()); + var instanceId = commonTestData.getAutomationCompositionId(); + var participantIntermediaryApi = mock(ParticipantIntermediaryApi.class); + var automationCompositionElementHandler = + new AutomationCompositionElementHandler(participantIntermediaryApi, mock(AcHttpClient.class)); + + automationCompositionElementHandler.handleRestartInstance(instanceId, element, map, DeployState.DEPLOYING, + LockState.NONE); + verify(participantIntermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); + } + + @Test + void testHandleRestartInstanceDeployed() throws PfModelException { + var element = commonTestData.getAutomationCompositionElement(); + var instanceId = commonTestData.getAutomationCompositionId(); + var participantIntermediaryApi = mock(ParticipantIntermediaryApi.class); + var automationCompositionElementHandler = + new AutomationCompositionElementHandler(participantIntermediaryApi, mock(AcHttpClient.class)); + + automationCompositionElementHandler.handleRestartInstance(instanceId, element, element.getProperties(), + DeployState.DEPLOYED, LockState.LOCKED); + verify(participantIntermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + DeployState.DEPLOYED, LockState.LOCKED, StateChangeResult.NO_ERROR, "Restarted"); + } } diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/handler/AutomationCompositionElementHandler.java index ed02314cd..3a53a7aea 100755 --- a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/handler/AutomationCompositionElementHandler.java +++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/handler/AutomationCompositionElementHandler.java @@ -23,10 +23,10 @@ package org.onap.policy.clamp.acm.participant.kserve.handler; import io.kubernetes.client.openapi.ApiException; import java.io.IOException; import java.lang.invoke.MethodHandles; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -50,6 +50,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDef import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; @@ -76,7 +77,7 @@ public class AutomationCompositionElementHandler implements AutomationCompositio private final KserveClient kserveClient; @Getter(AccessLevel.PACKAGE) - private final Map configRequestMap = new HashMap<>(); + private final Map configRequestMap = new ConcurrentHashMap<>(); private static class ThreadConfig { @@ -206,4 +207,39 @@ public class AutomationCompositionElementHandler implements AutomationCompositio intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); } + + @Override + public void handleRestartComposition(UUID compositionId, + List elementDefinitionList, AcTypeState state) + throws PfModelException { + var finalState = AcTypeState.PRIMED.equals(state) || AcTypeState.PRIMING.equals(state) ? AcTypeState.PRIMED + : AcTypeState.COMMISSIONED; + intermediaryApi.updateCompositionState(compositionId, finalState, StateChangeResult.NO_ERROR, "Restarted"); + } + + @Override + public void handleRestartInstance(UUID automationCompositionId, AcElementDeploy element, + Map properties, DeployState deployState, LockState lockState) throws PfModelException { + if (DeployState.DEPLOYING.equals(deployState)) { + deploy(automationCompositionId, element, properties); + return; + } + if (DeployState.UNDEPLOYING.equals(deployState) || DeployState.DEPLOYED.equals(deployState) + || DeployState.UPDATING.equals(deployState)) { + try { + var configurationEntity = CODER.convert(properties, ConfigurationEntity.class); + configRequestMap.put(element.getId(), configurationEntity); + } catch (CoderException e) { + throw new KserveException(HttpStatus.SC_BAD_REQUEST, "Invalid inference service configuration", e); + } + } + if (DeployState.UNDEPLOYING.equals(deployState)) { + undeploy(automationCompositionId, element.getId()); + return; + } + deployState = AcmUtils.deployCompleted(deployState); + lockState = AcmUtils.lockCompleted(deployState, lockState); + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), deployState, + lockState, StateChangeResult.NO_ERROR, "Restarted"); + } } diff --git a/participant/participant-impl/participant-impl-kserve/src/test/java/org/onap/policy/clamp/acm/participant/kserve/handler/AcElementHandlerTest.java b/participant/participant-impl/participant-impl-kserve/src/test/java/org/onap/policy/clamp/acm/participant/kserve/handler/AcElementHandlerTest.java index 6112488bf..1c1699f23 100755 --- a/participant/participant-impl/participant-impl-kserve/src/test/java/org/onap/policy/clamp/acm/participant/kserve/handler/AcElementHandlerTest.java +++ b/participant/participant-impl/participant-impl-kserve/src/test/java/org/onap/policy/clamp/acm/participant/kserve/handler/AcElementHandlerTest.java @@ -49,6 +49,9 @@ import org.onap.policy.clamp.acm.participant.kserve.exception.KserveException; import org.onap.policy.clamp.acm.participant.kserve.k8s.KserveClient; import org.onap.policy.clamp.acm.participant.kserve.utils.CommonTestData; import org.onap.policy.clamp.acm.participant.kserve.utils.ToscaUtils; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +import org.onap.policy.clamp.models.acm.concepts.DeployState; +import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -165,4 +168,45 @@ class AcElementHandlerTest { void testDeprime() throws PfModelException { assertDoesNotThrow(() -> automationCompositionElementHandler.deprime(UUID.randomUUID())); } + + @Test + void testHandleRestartComposition() throws PfModelException { + assertDoesNotThrow(() -> automationCompositionElementHandler.handleRestartComposition(UUID.randomUUID(), + List.of(), AcTypeState.PRIMED)); + } + + @Test + void testHandleRestartInstanceDeploying() throws PfModelException { + var element = commonTestData.getAutomationCompositionElement(); + + var nodeTemplatesMap = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + assertDoesNotThrow(() -> automationCompositionElementHandler.handleRestartInstance( + commonTestData.getAutomationCompositionId(), element, + nodeTemplatesMap.get(KSERVE_AUTOMATION_COMPOSITION_ELEMENT).getProperties(), DeployState.DEPLOYING, + LockState.NONE)); + assertThat(automationCompositionElementHandler.getConfigRequestMap()).containsKey(element.getId()); + } + + @Test + void testHandleRestartInstanceDeployed() throws PfModelException { + var element = commonTestData.getAutomationCompositionElement(); + + var nodeTemplatesMap = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + assertDoesNotThrow(() -> automationCompositionElementHandler.handleRestartInstance( + commonTestData.getAutomationCompositionId(), element, + nodeTemplatesMap.get(KSERVE_AUTOMATION_COMPOSITION_ELEMENT).getProperties(), DeployState.DEPLOYED, + LockState.LOCKED)); + assertThat(automationCompositionElementHandler.getConfigRequestMap()).containsKey(element.getId()); + } + + @Test + void testHandleRestartInstanceUndeployed() throws PfModelException { + var element = commonTestData.getAutomationCompositionElement(); + + var nodeTemplatesMap = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + assertDoesNotThrow(() -> automationCompositionElementHandler.handleRestartInstance( + commonTestData.getAutomationCompositionId(), element, + nodeTemplatesMap.get(KSERVE_AUTOMATION_COMPOSITION_ELEMENT).getProperties(), DeployState.UNDEPLOYING, + LockState.LOCKED)); + } } diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/acm/participant/kubernetes/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/acm/participant/kubernetes/handler/AutomationCompositionElementHandler.java index 7385a1f3b..a0ea31673 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/acm/participant/kubernetes/handler/AutomationCompositionElementHandler.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/acm/participant/kubernetes/handler/AutomationCompositionElementHandler.java @@ -44,6 +44,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDef import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; @@ -212,4 +213,40 @@ public class AutomationCompositionElementHandler implements AutomationCompositio intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); } + + @Override + public void handleRestartComposition(UUID compositionId, + List elementDefinitionList, AcTypeState state) + throws PfModelException { + var finalState = AcTypeState.PRIMED.equals(state) || AcTypeState.PRIMING.equals(state) ? AcTypeState.PRIMED + : AcTypeState.COMMISSIONED; + intermediaryApi.updateCompositionState(compositionId, finalState, StateChangeResult.NO_ERROR, "Restarted"); + } + + @Override + public void handleRestartInstance(UUID automationCompositionId, AcElementDeploy element, + Map properties, DeployState deployState, LockState lockState) throws PfModelException { + if (DeployState.DEPLOYING.equals(deployState)) { + deploy(automationCompositionId, element, properties); + return; + } + if (DeployState.UNDEPLOYING.equals(deployState) || DeployState.DEPLOYED.equals(deployState) + || DeployState.UPDATING.equals(deployState)) { + try { + var chartInfo = getChartInfo(properties); + chartMap.put(element.getId(), chartInfo); + } catch (AutomationCompositionException e) { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, e.getMessage()); + } + } + if (DeployState.UNDEPLOYING.equals(deployState)) { + undeploy(automationCompositionId, element.getId()); + return; + } + deployState = AcmUtils.deployCompleted(deployState); + lockState = AcmUtils.lockCompleted(deployState, lockState); + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), deployState, + lockState, StateChangeResult.NO_ERROR, "Restarted"); + } } diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/handler/AutomationCompositionElementHandlerTest.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/handler/AutomationCompositionElementHandlerTest.java index 6b24c0f8a..6cf344feb 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/handler/AutomationCompositionElementHandlerTest.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/handler/AutomationCompositionElementHandlerTest.java @@ -52,14 +52,13 @@ import org.onap.policy.clamp.acm.participant.kubernetes.models.ChartList; import org.onap.policy.clamp.acm.participant.kubernetes.parameters.CommonTestData; import org.onap.policy.clamp.acm.participant.kubernetes.service.ChartService; import org.onap.policy.clamp.acm.participant.kubernetes.utils.TestUtils; -import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; -import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; -import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +import org.onap.policy.clamp.models.acm.concepts.DeployState; +import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.models.base.PfModelException; -import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -121,12 +120,7 @@ class AutomationCompositionElementHandlerTest { void test_AutomationCompositionElementUpdate() throws PfModelException, IOException, ServiceException, ExecutionException, InterruptedException { doNothing().when(automationCompositionElementHandler).checkPodStatus(any(), any(), any(), anyInt(), anyInt()); - var elementId1 = UUID.randomUUID(); - var element = new AcElementDeploy(); - element.setId(elementId1); - element.setDefinition(new ToscaConceptIdentifier(KEY_NAME, "1.0.1")); - element.setOrderedState(DeployOrder.DEPLOY); - + var element = CommonTestData.createAcElementDeploy(); var nodeTemplatesMap = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates(); doReturn(false).when(chartService).installChart(any()); @@ -137,7 +131,7 @@ class AutomationCompositionElementHandlerTest { automationCompositionElementHandler.deploy(commonTestData.getAutomationCompositionId(), element, nodeTemplatesMap.get(K8S_AUTOMATION_COMPOSITION_ELEMENT).getProperties()); - assertThat(automationCompositionElementHandler.getChartMap()).hasSize(1).containsKey(elementId1); + assertThat(automationCompositionElementHandler.getChartMap()).hasSize(1).containsKey(element.getId()); doThrow(new ServiceException("Error installing the chart")).when(chartService).installChart(Mockito.any()); @@ -154,18 +148,13 @@ class AutomationCompositionElementHandlerTest { void test_checkPodStatus() throws ExecutionException, InterruptedException { var chartInfo = charts.get(0); var automationCompositionId = UUID.randomUUID(); - var element = new AutomationCompositionElement(); assertThrows(ServiceException.class, () -> automationCompositionElementHandler - .checkPodStatus(automationCompositionId, element.getId(), chartInfo, 1, 1)); + .checkPodStatus(automationCompositionId, UUID.randomUUID(), chartInfo, 1, 1)); } @Test void testUpdate() throws PfModelException { - var elementId1 = UUID.randomUUID(); - var element = new AcElementDeploy(); - element.setId(elementId1); - element.setDefinition(new ToscaConceptIdentifier(KEY_NAME, "1.0.1")); - element.setOrderedState(DeployOrder.DEPLOY); + var element = CommonTestData.createAcElementDeploy(); var automationCompositionId = commonTestData.getAutomationCompositionId(); assertDoesNotThrow( () -> automationCompositionElementHandler.update(automationCompositionId, element, Map.of())); @@ -195,4 +184,54 @@ class AutomationCompositionElementHandlerTest { void testDeprime() throws PfModelException { assertDoesNotThrow(() -> automationCompositionElementHandler.deprime(UUID.randomUUID())); } + + @Test + void testHandleRestartComposition() throws PfModelException { + assertDoesNotThrow(() -> automationCompositionElementHandler.handleRestartComposition(UUID.randomUUID(), + List.of(), AcTypeState.PRIMED)); + } + + @Test + void testHandleRestartInstanceDeploying() + throws PfModelException, InterruptedException, ServiceException, IOException { + doNothing().when(automationCompositionElementHandler).checkPodStatus(any(), any(), any(), anyInt(), anyInt()); + var element = CommonTestData.createAcElementDeploy(); + var nodeTemplatesMap = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + + doReturn(true).when(chartService).installChart(any()); + assertDoesNotThrow(() -> automationCompositionElementHandler.handleRestartInstance( + commonTestData.getAutomationCompositionId(), element, + nodeTemplatesMap.get(K8S_AUTOMATION_COMPOSITION_ELEMENT).getProperties(), DeployState.DEPLOYING, + LockState.NONE)); + + assertThat(automationCompositionElementHandler.getChartMap()).containsKey(element.getId()); + } + + @Test + void testHandleRestartInstanceDeployed() + throws PfModelException, InterruptedException, ServiceException, IOException { + doNothing().when(automationCompositionElementHandler).checkPodStatus(any(), any(), any(), anyInt(), anyInt()); + var element = CommonTestData.createAcElementDeploy(); + var nodeTemplatesMap = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + + assertDoesNotThrow(() -> automationCompositionElementHandler.handleRestartInstance( + commonTestData.getAutomationCompositionId(), element, + nodeTemplatesMap.get(K8S_AUTOMATION_COMPOSITION_ELEMENT).getProperties(), DeployState.DEPLOYED, + LockState.LOCKED)); + + assertThat(automationCompositionElementHandler.getChartMap()).containsKey(element.getId()); + } + + @Test + void testHandleRestartInstanceUndeploying() + throws PfModelException, InterruptedException, ServiceException, IOException { + doNothing().when(automationCompositionElementHandler).checkPodStatus(any(), any(), any(), anyInt(), anyInt()); + var element = CommonTestData.createAcElementDeploy(); + var nodeTemplatesMap = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + + assertDoesNotThrow(() -> automationCompositionElementHandler.handleRestartInstance( + commonTestData.getAutomationCompositionId(), element, + nodeTemplatesMap.get(K8S_AUTOMATION_COMPOSITION_ELEMENT).getProperties(), DeployState.UNDEPLOYING, + LockState.LOCKED)); + } } diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/parameters/CommonTestData.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/parameters/CommonTestData.java index 8041a4ea5..8de972bfe 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/parameters/CommonTestData.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/parameters/CommonTestData.java @@ -26,10 +26,13 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.UUID; +import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; import org.onap.policy.common.endpoints.parameters.TopicParameters; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; public class CommonTestData { @@ -39,6 +42,8 @@ public class CommonTestData { public static final List TOPIC_PARAMS = List.of(getTopicParams()); public static final Coder CODER = new StandardCoder(); private static final UUID AC_ID = UUID.randomUUID(); + private static final String KEY_NAME = + "org.onap.domain.database.HelloWorld_K8SMicroserviceAutomationCompositionElement"; /** * Get ParticipantK8sParameters. @@ -154,4 +159,17 @@ public class CommonTestData { public UUID getAutomationCompositionId() { return AC_ID; } + + /** + * Create an AcElementDeploy. + * + * @return an AcElementDeploy + */ + public static AcElementDeploy createAcElementDeploy() { + var element = new AcElementDeploy(); + element.setId(UUID.randomUUID()); + element.setDefinition(new ToscaConceptIdentifier(KEY_NAME, "1.0.1")); + element.setOrderedState(DeployOrder.DEPLOY); + return element; + } } diff --git a/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java index 29622149a..6b94a79ad 100644 --- a/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java +++ b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java @@ -40,6 +40,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDef import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.pdp.concepts.DeploymentSubGroup; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; @@ -244,4 +245,35 @@ public class AutomationCompositionElementHandler implements AutomationCompositio intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); } + + @Override + public void handleRestartComposition(UUID compositionId, + List elementDefinitionList, AcTypeState state) + throws PfModelException { + var finalState = AcTypeState.PRIMED.equals(state) || AcTypeState.PRIMING.equals(state) ? AcTypeState.PRIMED + : AcTypeState.COMMISSIONED; + intermediaryApi.updateCompositionState(compositionId, finalState, StateChangeResult.NO_ERROR, "Restarted"); + } + + @Override + public void handleRestartInstance(UUID automationCompositionId, AcElementDeploy element, + Map properties, DeployState deployState, LockState lockState) throws PfModelException { + if (DeployState.DEPLOYING.equals(deployState)) { + deploy(automationCompositionId, element, properties); + return; + } + if (DeployState.UNDEPLOYING.equals(deployState) || DeployState.DEPLOYED.equals(deployState) + || DeployState.UPDATING.equals(deployState)) { + var automationCompositionDefinition = element.getToscaServiceTemplateFragment(); + serviceTemplateMap.put(element.getId(), automationCompositionDefinition); + } + if (DeployState.UNDEPLOYING.equals(deployState)) { + undeploy(automationCompositionId, element.getId()); + return; + } + deployState = AcmUtils.deployCompleted(deployState); + lockState = AcmUtils.lockCompleted(deployState, lockState); + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), deployState, + lockState, StateChangeResult.NO_ERROR, "Restarted"); + } } diff --git a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java index 84ddeed74..16530d69f 100644 --- a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java +++ b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java @@ -218,4 +218,53 @@ class AutomationCompositionElementHandlerTest { verify(intermediaryApi).updateCompositionState(AC_ID, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); } + + @Test + void testHandleRestartComposition() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var automationCompositionElementHandler = + new AutomationCompositionElementHandler(mock(PolicyApiHttpClient.class), + mock(PolicyPapHttpClient.class), intermediaryApi); + + var compositionId = UUID.randomUUID(); + automationCompositionElementHandler.handleRestartComposition(compositionId, List.of(), AcTypeState.PRIMED); + + verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, + StateChangeResult.NO_ERROR, "Restarted"); + } + + @Test + void testHandleRestartInstanceDeploying() throws PfModelException { + // Mock success scenario for policy creation and deployment + var api = mock(PolicyApiHttpClient.class); + doReturn(Response.ok().build()).when(api).createPolicyType(any()); + doReturn(Response.ok().build()).when(api).createPolicy(any()); + + var pap = mock(PolicyPapHttpClient.class); + doReturn(Response.accepted().build()).when(pap).handlePolicyDeployOrUndeploy(any(), any(), any()); + + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var handler = new AutomationCompositionElementHandler(api, pap, intermediaryApi); + var element = getTestingAcElement(); + + handler.handleRestartInstance(AC_ID, element, Map.of(), DeployState.DEPLOYING, LockState.NONE); + verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); + + handler.handleRestartInstance(AC_ID, element, Map.of(), DeployState.UNDEPLOYING, LockState.LOCKED); + verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); + } + + @Test + void testHandleRestartInstanceDeployed() throws PfModelException { + var api = mock(PolicyApiHttpClient.class); + var pap = mock(PolicyPapHttpClient.class); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var handler = new AutomationCompositionElementHandler(api, pap, intermediaryApi); + var element = getTestingAcElement(); + handler.handleRestartInstance(AC_ID, element, Map.of(), DeployState.DEPLOYED, LockState.LOCKED); + verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId, + DeployState.DEPLOYED, LockState.LOCKED, StateChangeResult.NO_ERROR, "Restarted"); + } } diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java index 7554c0b3c..eaf94552b 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java @@ -40,6 +40,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions; import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.models.base.PfModelException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -188,7 +189,7 @@ public class AutomationCompositionElementHandler implements AutomationCompositio @Override public void update(UUID automationCompositionId, AcElementDeploy element, Map properties) throws PfModelException { - LOGGER.debug("updat call"); + LOGGER.debug("update call"); if (!execution(config.getUpdateTimerMs(), "Current Thread update is Interrupted during execution {}", element.getId())) { @@ -233,6 +234,7 @@ public class AutomationCompositionElementHandler implements AutomationCompositio @Override public void prime(UUID compositionId, List elementDefinitionList) throws PfModelException { + LOGGER.debug("prime call"); if (!execution(config.getPrimeTimerMs(), "Current Thread prime is Interrupted during execution {}", compositionId)) { @@ -250,6 +252,7 @@ public class AutomationCompositionElementHandler implements AutomationCompositio @Override public void deprime(UUID compositionId) throws PfModelException { + LOGGER.debug("deprime call"); if (!execution(config.getDeprimeTimerMs(), "Current Thread deprime is Interrupted during execution {}", compositionId)) { @@ -287,4 +290,57 @@ public class AutomationCompositionElementHandler implements AutomationCompositio } return result; } + + @Override + public void handleRestartComposition(UUID compositionId, + List elementDefinitionList, AcTypeState state) + throws PfModelException { + LOGGER.debug("restart composition definition call"); + switch (state) { + case PRIMING: + prime(compositionId, elementDefinitionList); + break; + + case DEPRIMING: + deprime(compositionId); + break; + + default: + intermediaryApi.updateCompositionState(compositionId, state, StateChangeResult.NO_ERROR, "Restarted"); + } + } + + @Override + public void handleRestartInstance(UUID automationCompositionId, AcElementDeploy element, + Map properties, DeployState deployState, LockState lockState) throws PfModelException { + LOGGER.debug("restart instance call"); + if (!AcmUtils.isInTransitionalState(deployState, lockState)) { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), + deployState, lockState, StateChangeResult.NO_ERROR, "Restarted"); + return; + } + if (DeployState.DEPLOYING.equals(deployState)) { + deploy(automationCompositionId, element, properties); + return; + } + if (DeployState.UNDEPLOYING.equals(deployState)) { + undeploy(automationCompositionId, element.getId()); + return; + } + if (DeployState.UPDATING.equals(deployState)) { + update(automationCompositionId, element, properties); + return; + } + if (DeployState.DELETING.equals(deployState)) { + delete(automationCompositionId, element.getId()); + return; + } + if (LockState.LOCKING.equals(lockState)) { + lock(automationCompositionId, element.getId()); + return; + } + if (LockState.UNLOCKING.equals(lockState)) { + unlock(automationCompositionId, element.getId()); + } + } } diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java index 977b9d8e4..70111cb52 100644 --- a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java @@ -192,9 +192,9 @@ class AutomationCompositionElementHandlerTest { when(intermediaryApi.getAutomationCompositions()).thenReturn(map); var result = acElementHandler.getDataList(); var data = result.getList().get(0); - var autocomposition = map.values().iterator().next(); - assertEquals(autocomposition.getInstanceId(), data.getAutomationCompositionId()); - var element = autocomposition.getElements().values().iterator().next(); + var automationcomposition = map.values().iterator().next(); + assertEquals(automationcomposition.getInstanceId(), data.getAutomationCompositionId()); + var element = automationcomposition.getElements().values().iterator().next(); assertEquals(element.getId(), data.getAutomationCompositionElementId()); } @@ -233,4 +233,66 @@ class AutomationCompositionElementHandlerTest { verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.FAILED, "Deprime failed!"); } + + @Test + void testHandleRestartComposition() throws PfModelException { + var config = new SimConfig(); + config.setPrimeTimerMs(1); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + acElementHandler.setConfig(config); + var compositionId = UUID.randomUUID(); + acElementHandler.handleRestartComposition(compositionId, List.of(), AcTypeState.PRIMING); + verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, + "Primed"); + + acElementHandler.handleRestartComposition(compositionId, List.of(), AcTypeState.PRIMED); + verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, + "Restarted"); + + acElementHandler.handleRestartComposition(compositionId, List.of(), AcTypeState.DEPRIMING); + verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.COMMISSIONED, + StateChangeResult.NO_ERROR, "Deprimed"); + } + + @Test + void testHandleRestartInstance() throws PfModelException { + var config = new SimConfig(); + config.setDeployTimerMs(1); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + acElementHandler.setConfig(config); + var instanceId = UUID.randomUUID(); + var element = new AcElementDeploy(); + element.setId(UUID.randomUUID()); + acElementHandler.handleRestartInstance(instanceId, element, Map.of(), DeployState.DEPLOYING, LockState.NONE); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); + + acElementHandler.handleRestartInstance(instanceId, element, Map.of(), DeployState.DEPLOYED, LockState.LOCKED); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + DeployState.DEPLOYED, LockState.LOCKED, StateChangeResult.NO_ERROR, "Restarted"); + + acElementHandler.handleRestartInstance(instanceId, element, Map.of(), DeployState.UPDATING, LockState.LOCKED); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated"); + + acElementHandler.handleRestartInstance(instanceId, element, Map.of(), DeployState.UNDEPLOYING, + LockState.LOCKED); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); + + acElementHandler.handleRestartInstance(instanceId, element, Map.of(), DeployState.DELETING, LockState.NONE); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); + + acElementHandler.handleRestartInstance(instanceId, element, Map.of(), DeployState.DEPLOYED, LockState.LOCKING); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), null, + LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); + + acElementHandler.handleRestartInstance(instanceId, element, Map.of(), DeployState.DEPLOYED, + LockState.UNLOCKING); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), null, + LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked"); + } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java index 48b60dc76..2002ba48d 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java @@ -24,7 +24,10 @@ import java.util.List; import java.util.Map; import java.util.UUID; import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition; +import org.onap.policy.clamp.models.acm.concepts.DeployState; +import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.models.base.PfModelException; /** @@ -63,4 +66,11 @@ public interface AutomationCompositionElementListener { throws PfModelException; void deprime(UUID compositionId) throws PfModelException; + + void handleRestartComposition(UUID compositionId, + List elementDefinitionList, AcTypeState state) + throws PfModelException; + + void handleRestartInstance(UUID automationCompositionId, AcElementDeploy element, Map properties, + DeployState deployState, LockState lockState) throws PfModelException; } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ParticipantIntermediaryApi.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ParticipantIntermediaryApi.java index c75750c0d..8b800a8fd 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ParticipantIntermediaryApi.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ParticipantIntermediaryApi.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.UUID; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; @@ -38,22 +39,31 @@ public interface ParticipantIntermediaryApi { * Update the state of a automation composition element. * * @param automationCompositionId the ID of the automation composition to update the state on - * @param id the ID of the automation composition element to update the state on + * @param elementId the ID of the automation composition element to update the state on * @param deployState the Deploy State of the automation composition element * @param lockState the Lock State of the automation composition element * @param stateChangeResult the indicator if error occurs * @param message the message */ - void updateAutomationCompositionElementState(UUID automationCompositionId, UUID id, DeployState deployState, + void updateAutomationCompositionElementState(UUID automationCompositionId, UUID elementId, DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message); /** - * Get AutomationCompositions. + * Get a copy of all AutomationCompositions. * * @return get all AutomationCompositions */ Map getAutomationCompositions(); + /** + * Get a copy of the AutomationCompositionElement by automationCompositionId and elementId. + * + * @param automationCompositionId the ID of the automation composition to update the state on + * @param elementId the ID of the automation composition element to update the state on + * @return get the AutomationCompositionElement + */ + AutomationCompositionElement getAutomationCompositionElement(UUID automationCompositionId, UUID elementId); + /** * Send Automation Composition Element update Info to AC-runtime. * diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java index 96d96cac9..ca5f08793 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java @@ -29,6 +29,7 @@ import org.onap.policy.clamp.acm.participant.intermediary.handler.AutomationComp import org.onap.policy.clamp.acm.participant.intermediary.handler.CacheProvider; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; @@ -70,4 +71,14 @@ public class ParticipantIntermediaryApiImpl implements ParticipantIntermediaryAp String message) { automationCompositionHandler.updateCompositionState(compositionId, state, stateChangeResult, message); } + + @Override + public AutomationCompositionElement getAutomationCompositionElement(UUID automationCompositionId, UUID elementId) { + var automationComposition = cacheProvider.getAutomationCompositions().get(automationCompositionId); + if (automationComposition == null) { + return null; + } + var element = automationComposition.getElements().get(elementId); + return element != null ? new AutomationCompositionElement(element) : null; + } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java index 65ad131df..2018d435f 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java @@ -22,6 +22,7 @@ package org.onap.policy.clamp.acm.participant.intermediary.handler; import java.io.Closeable; import java.io.IOException; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; @@ -33,6 +34,7 @@ import lombok.RequiredArgsConstructor; import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener; import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.concepts.AcElementRestart; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition; import org.onap.policy.clamp.models.acm.concepts.DeployState; @@ -272,7 +274,47 @@ public class ThreadHandler implements Closeable { */ public void restarted(UUID messageId, UUID compositionId, List list, AcTypeState state, List automationCompositionList) { - // TODO + try { + listener.handleRestartComposition(compositionId, list, state); + } catch (PfModelException e) { + LOGGER.error("Composition Defintion restarted failed {} {}", compositionId, e.getMessage()); + intermediaryApi.updateCompositionState(compositionId, state, StateChangeResult.FAILED, + "Composition Defintion restarted failed"); + } + + for (var automationComposition : automationCompositionList) { + for (var element : automationComposition.getAcElementList()) { + cleanExecution(element.getId(), messageId); + var result = executor.submit(() -> this + .restartedInstanceProcess(automationComposition.getAutomationCompositionId(), element)); + executionMap.put(element.getId(), result); + } + } + } + + private void restartedInstanceProcess(UUID instanceId, AcElementRestart element) { + try { + var map = new HashMap<>(cacheProvider.getCommonProperties(instanceId, element.getId())); + map.putAll(element.getProperties()); + + listener.handleRestartInstance(instanceId, getAcElementDeploy(element), map, element.getDeployState(), + element.getLockState()); + executionMap.remove(element.getId()); + } catch (PfModelException e) { + LOGGER.error("Automation composition element deploy failed {} {}", instanceId, e.getMessage()); + intermediaryApi.updateAutomationCompositionElementState(instanceId, element.getId(), + element.getDeployState(), element.getLockState(), StateChangeResult.FAILED, + "Automation composition element restart failed"); + } + } + + private AcElementDeploy getAcElementDeploy(AcElementRestart element) { + var acElementDeploy = new AcElementDeploy(); + acElementDeploy.setId(element.getId()); + acElementDeploy.setDefinition(element.getDefinition()); + acElementDeploy.setProperties(element.getProperties()); + acElementDeploy.setToscaServiceTemplateFragment(element.getToscaServiceTemplateFragment()); + return acElementDeploy; } /** diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImplTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImplTest.java index fcd8650ea..acf86f20a 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImplTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImplTest.java @@ -20,6 +20,7 @@ package org.onap.policy.clamp.acm.participant.intermediary.api.impl; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -32,6 +33,7 @@ import org.onap.policy.clamp.acm.participant.intermediary.handler.AutomationComp import org.onap.policy.clamp.acm.participant.intermediary.handler.CacheProvider; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; @@ -65,11 +67,24 @@ class ParticipantIntermediaryApiImplTest { verify(automationComposiitonHandler).updateAutomationCompositionElementState(automationCompositionId, uuid, DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, ""); - var map = Map.of(uuid, new AutomationComposition()); + var map = Map.of(automationCompositionId, new AutomationComposition()); when(cacheProvider.getAutomationCompositions()).thenReturn(map); + var acElement = new AutomationCompositionElement(); + acElement.setId(uuid); + map.get(automationCompositionId).setElements(Map.of(uuid, acElement)); + var result = apiImpl.getAutomationCompositions(); assertEquals(map, result); + var element = apiImpl.getAutomationCompositionElement(UUID.randomUUID(), UUID.randomUUID()); + assertThat(element).isNull(); + + element = apiImpl.getAutomationCompositionElement(automationCompositionId, UUID.randomUUID()); + assertThat(element).isNull(); + + element = apiImpl.getAutomationCompositionElement(automationCompositionId, uuid); + assertEquals(acElement, element); + apiImpl.updateCompositionState(uuid, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, ""); verify(automationComposiitonHandler).updateCompositionState(uuid, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, ""); diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/DummyAcElementListener.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/DummyAcElementListener.java index 0a724ed69..a4994cbf0 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/DummyAcElementListener.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/DummyAcElementListener.java @@ -25,7 +25,10 @@ import java.util.Map; import java.util.UUID; import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener; import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition; +import org.onap.policy.clamp.models.acm.concepts.DeployState; +import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.models.base.PfModelException; public class DummyAcElementListener implements AutomationCompositionElementListener { @@ -36,7 +39,7 @@ public class DummyAcElementListener implements AutomationCompositionElementListe @Override public void deploy(UUID automationCompositionId, AcElementDeploy element, Map properties) - throws PfModelException { + throws PfModelException { } @@ -65,4 +68,15 @@ public class DummyAcElementListener implements AutomationCompositionElementListe @Override public void deprime(UUID compositionId) throws PfModelException { } + + @Override + public void handleRestartComposition(UUID compositionId, + List elementDefinitionList, AcTypeState state) + throws PfModelException { + } + + @Override + public void handleRestartInstance(UUID automationCompositionId, AcElementDeploy element, + Map properties, DeployState deployState, LockState lockState) throws PfModelException { + } } diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java index 55d84c5fc..2776ed8df 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java @@ -20,6 +20,7 @@ package org.onap.policy.clamp.acm.participant.intermediary.handler; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -35,10 +36,12 @@ import org.junit.jupiter.api.Test; import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener; import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.concepts.AcElementRestart; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition; import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; +import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; import org.onap.policy.models.base.PfModelException; @@ -164,6 +167,30 @@ class ThreadHandlerTest { threadHandler.deprime(messageId, compositionId); verify(intermediaryApi, timeout(TIMEOUT)).updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.FAILED, "Composition Defintion deprime failed"); + + clearInvocations(listener); + doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) + .handleRestartComposition(compositionId, List.of(), AcTypeState.PRIMING); + threadHandler.restarted(messageId, compositionId, List.of(), AcTypeState.PRIMING, List.of()); + verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.FAILED, + "Composition Defintion deprime failed"); + } + } + + @Test + void testRestarted() throws IOException, PfModelException { + var listener = mock(AutomationCompositionElementListener.class); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var cacheProvider = mock(CacheProvider.class); + try (var threadHandler = new ThreadHandler(listener, intermediaryApi, cacheProvider)) { + var messageId = UUID.randomUUID(); + var compositionId = UUID.randomUUID(); + var participantRestartAc = new ParticipantRestartAc(); + participantRestartAc.setAutomationCompositionId(UUID.randomUUID()); + participantRestartAc.getAcElementList().add(new AcElementRestart()); + threadHandler.restarted(messageId, compositionId, List.of(new AutomationCompositionElementDefinition()), + AcTypeState.PRIMED, List.of(participantRestartAc)); + verify(listener, timeout(TIMEOUT)).handleRestartInstance(any(), any(), any(), any(), any()); } } } -- cgit 1.2.3-korg