From 5ba17489da76d1012c376efacd1f087a8a8fda25 Mon Sep 17 00:00:00 2001 From: FrancescoFioraEst Date: Thu, 13 Mar 2025 13:06:12 +0000 Subject: [PATCH] Add support for stage in Prepare event Issue-ID: POLICY-5264 Change-Id: I1d5f3b2f329a2aa5713066aa9681dcaca597085e Signed-off-by: FrancescoFioraEst --- ...va => AutomationCompositionElementHandler.java} | 15 +-- .../sim/main/handler/SimulatorService.java | 36 ++++++- ...> AutomationCompositionElementHandlerTest.java} | 38 +++---- .../sim/main/handler/SimulatorServiceTest.java | 6 +- .../api/AutomationCompositionElementListener.java | 4 +- .../intermediary/api/impl/AcElementListenerV3.java | 78 +------------- .../intermediary/api/impl/AcElementListenerV4.java | 119 +++++++++++++++++++++ .../AutomationCompositionElementListenerV3.java | 59 ++++++++++ .../intermediary/handler/AcSubStateHandler.java | 18 ++-- .../handler/AutomationCompositionOutHandler.java | 14 +-- .../intermediary/handler/ThreadHandler.java | 12 ++- .../handler/AcSubStateHandlerTest.java | 6 +- .../intermediary/handler/ThreadHandlerTest.java | 10 +- ...AutomationCompositionInstantiationProvider.java | 29 +++-- .../runtime/supervision/SupervisionAcHandler.java | 9 +- .../supervision/comm/AcPreparePublisher.java | 6 +- .../supervision/scanner/MonitoringScanner.java | 6 +- .../runtime/supervision/scanner/StageScanner.java | 35 ++++-- ...mationCompositionInstantiationProviderTest.java | 41 ++++--- .../supervision/SupervisionAcHandlerTest.java | 8 +- .../supervision/SupervisionScannerTest.java | 10 +- .../supervision/comm/SupervisionMessagesTest.java | 4 +- .../supervision/scanner/StageScannerTest.java | 61 ++++++++++- 23 files changed, 424 insertions(+), 200 deletions(-) rename participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/{AutomationCompositionElementHandlerV3.java => AutomationCompositionElementHandler.java} (93%) rename participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/{AutomationCompositionElementHandlerV3Test.java => AutomationCompositionElementHandlerTest.java} (96%) create mode 100644 participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV4.java create mode 100644 participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AutomationCompositionElementListenerV3.java diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java similarity index 93% rename from participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3.java rename to participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java index 2246883d4..510708292 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2024-2025 Nordix Foundation. + * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElement import org.onap.policy.clamp.acm.participant.intermediary.api.ElementState; import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; -import org.onap.policy.clamp.acm.participant.intermediary.api.impl.AcElementListenerV3; +import org.onap.policy.clamp.acm.participant.intermediary.api.impl.AcElementListenerV4; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -38,13 +38,13 @@ import org.springframework.stereotype.Component; @Getter @Setter @Component -public class AutomationCompositionElementHandlerV3 extends AcElementListenerV3 { +public class AutomationCompositionElementHandler extends AcElementListenerV4 { - private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionElementHandlerV3.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionElementHandler.class); private final SimulatorService simulatorService; - public AutomationCompositionElementHandlerV3(ParticipantIntermediaryApi intermediaryApi, + public AutomationCompositionElementHandler(ParticipantIntermediaryApi intermediaryApi, SimulatorService simulatorService) { super(intermediaryApi); this.simulatorService = simulatorService; @@ -145,9 +145,10 @@ public class AutomationCompositionElementHandlerV3 extends AcElementListenerV3 { } @Override - public void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + public void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement, int stage) { LOGGER.debug("prepare call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); - simulatorService.prepare(instanceElement.instanceId(), instanceElement.elementId()); + simulatorService.prepare(instanceElement.instanceId(), instanceElement.elementId(), + stage, compositionElement.inProperties(), instanceElement.outProperties()); } @Override diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java index b689a7863..93a9ee70f 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java @@ -55,6 +55,8 @@ public class SimulatorService { private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorService.class); private static final String INTERNAL_STATE = "InternalState"; + private static final String MIGRATION_PROPERTY = "stage"; + private static final String PREPARE_PROPERTY = "prepareStage"; @Getter @Setter @@ -358,6 +360,8 @@ public class SimulatorService { * @param instanceId the instanceId * @param elementId the elementId * @param stage the stage + * @param compositionInProperties in Properties from composition definition element + * @param instanceOutProperties in Properties from instance element */ public void migrate(UUID instanceId, UUID elementId, int stage, Map compositionInProperties, Map instanceOutProperties) { @@ -374,9 +378,9 @@ public class SimulatorService { nextStage = Math.min(s, nextStage); } } - instanceOutProperties.putIfAbsent("stage", new ArrayList<>()); + instanceOutProperties.putIfAbsent(MIGRATION_PROPERTY, new ArrayList<>()); @SuppressWarnings("unchecked") - var stageList = (List) instanceOutProperties.get("stage"); + var stageList = (List) instanceOutProperties.get(MIGRATION_PROPERTY); stageList.add(stage); intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, instanceOutProperties); if (nextStage == 1000) { @@ -421,16 +425,38 @@ public class SimulatorService { * * @param instanceId the instanceId * @param elementId the elementId + * @param stage the stage + * @param compositionInProperties in Properties from composition definition element + * @param instanceOutProperties in Properties from instance element */ - public void prepare(UUID instanceId, UUID elementId) { + public void prepare(UUID instanceId, UUID elementId, int stage, Map compositionInProperties, + Map instanceOutProperties) { if (!execution(config.getPrepareTimerMs(), "Current Thread prepare is Interrupted during execution {}", elementId)) { return; } if (config.isPrepare()) { - intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Prepare completed"); + var stageSet = ParticipantUtils.findStageSetPrepare(compositionInProperties); + var nextStage = 1000; + for (var s : stageSet) { + if (s > stage) { + nextStage = Math.min(s, nextStage); + } + } + instanceOutProperties.putIfAbsent(PREPARE_PROPERTY, new ArrayList<>()); + @SuppressWarnings("unchecked") + var stageList = (List) instanceOutProperties.get(PREPARE_PROPERTY); + stageList.add(stage); + intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, instanceOutProperties); + if (nextStage == 1000) { + intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Prepare completed"); + } else { + intermediaryApi.updateAutomationCompositionElementStage( + instanceId, elementId, + StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Prepared"); + } } else { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Prepare failed"); diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3Test.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java similarity index 96% rename from participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3Test.java rename to participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java index 8b947e873..57c13ce90 100644 --- a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3Test.java +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2024-2025 Nordix Foundation. + * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,7 +40,7 @@ import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; -class AutomationCompositionElementHandlerV3Test { +class AutomationCompositionElementHandlerTest { private static final ToscaConceptIdentifier ELEMENT_DEFINITION_ID = new ToscaConceptIdentifier("name", "1.0.0"); private static final CompositionElementDto COMPOSITION_ELEMENT = @@ -55,7 +55,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); acElementHandler.deploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( @@ -74,7 +74,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); acElementHandler.undeploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( @@ -93,7 +93,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); acElementHandler.lock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( @@ -112,7 +112,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); acElementHandler.unlock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( @@ -131,7 +131,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); var instanceElementUpdated = new InstanceElementDto( INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), @@ -153,7 +153,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); acElementHandler.delete(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( @@ -172,7 +172,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); acElementHandler.prime(COMPOSITION); verify(intermediaryApi).updateCompositionState( @@ -189,7 +189,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); acElementHandler.deprime(COMPOSITION); verify(intermediaryApi).updateCompositionState( @@ -206,7 +206,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); var compositionElementTarget = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); @@ -232,7 +232,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); var compositionElementTarget = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of("stage", List.of(1, 2)), Map.of()); @@ -250,7 +250,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); var compositionElement = new CompositionElementDto( UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of(), ElementState.NOT_PRESENT); @@ -274,7 +274,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); var compoElTargetRemove = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), @@ -297,7 +297,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); var compositionElementTarget = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); @@ -325,15 +325,15 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); - acElementHandler.prepare(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + acElementHandler.prepare(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, 0); verify(intermediaryApi).updateAutomationCompositionElementState( INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Prepare completed"); config.setPrepare(false); - acElementHandler.prepare(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + acElementHandler.prepare(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, 0); verify(intermediaryApi).updateAutomationCompositionElementState( INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Prepare failed"); @@ -344,7 +344,7 @@ class AutomationCompositionElementHandlerV3Test { var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); - var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); acElementHandler.review(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorServiceTest.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorServiceTest.java index 174497966..308718326 100644 --- a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorServiceTest.java +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorServiceTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2024-2025 Nordix Foundation. + * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -144,10 +144,8 @@ class SimulatorServiceTest { simulatorService.delete(UUID.randomUUID(), UUID.randomUUID()); simulatorService.update(UUID.randomUUID(), UUID.randomUUID()); simulatorService.review(UUID.randomUUID(), UUID.randomUUID()); - simulatorService.prepare(UUID.randomUUID(), UUID.randomUUID()); + simulatorService.prepare(UUID.randomUUID(), UUID.randomUUID(), 0, new HashMap<>(), new HashMap<>()); simulatorService.migratePrecheck(UUID.randomUUID(), UUID.randomUUID()); verify(intermediaryApi, times(0)).sendAcDefinitionInfo(any(), any(), any()); - } - } 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 5994328d5..c4edf6e39 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 @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation. + * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -106,6 +106,6 @@ public interface AutomationCompositionElementListener { void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; - void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement, int nextStage) throws PfModelException; } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3.java index d63323d1a..0d5a6c599 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation. + * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,13 +21,10 @@ package org.onap.policy.clamp.acm.participant.intermediary.api.impl; import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener; -import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto; import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; -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.clamp.models.acm.concepts.StateChangeResult; import org.onap.policy.models.base.PfModelException; @@ -35,78 +32,11 @@ import org.onap.policy.models.base.PfModelException; * Wrapper of AutomationCompositionElementListener. * Valid since 8.0.1 release. */ -public abstract class AcElementListenerV3 implements AutomationCompositionElementListener { - protected final ParticipantIntermediaryApi intermediaryApi; +public abstract class AcElementListenerV3 extends AcElementListenerV4 + implements AutomationCompositionElementListener, AutomationCompositionElementListenerV3 { protected AcElementListenerV3(ParticipantIntermediaryApi intermediaryApi) { - this.intermediaryApi = intermediaryApi; - } - - @Override - public void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { - intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), - instanceElement.elementId(), null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); - } - - @Override - public void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { - intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), - instanceElement.elementId(), null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked"); - } - - @Override - public void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { - intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), - instanceElement.elementId(), DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); - } - - @Override - public void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement, - InstanceElementDto instanceElementUpdated) throws PfModelException { - intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), - instanceElement.elementId(), DeployState.DEPLOYED, null, - StateChangeResult.NO_ERROR, "Update not supported"); - - } - - @Override - public void prime(CompositionDto composition) throws PfModelException { - intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED, - StateChangeResult.NO_ERROR, "Primed"); - } - - @Override - public void deprime(CompositionDto composition) throws PfModelException { - intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED, - StateChangeResult.NO_ERROR, "Deprimed"); - } - - @Override - public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, - InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate, int stage) - throws PfModelException { - intermediaryApi.updateAutomationCompositionElementState(instanceElementMigrate.instanceId(), - instanceElementMigrate.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); - } - - @Override - public void migratePrecheck(CompositionElementDto compositionElement, - CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, - InstanceElementDto instanceElementMigrate) throws PfModelException { - intermediaryApi.updateAutomationCompositionElementState(instanceElementMigrate.instanceId(), - instanceElementMigrate.elementId(), DeployState.DEPLOYED, null, - StateChangeResult.NO_ERROR, "Migration Precheck completed"); - } - - @Override - public void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { - intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), - instanceElement.elementId(), DeployState.DEPLOYED, null, - StateChangeResult.NO_ERROR, "Review completed"); + super(intermediaryApi); } @Override diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV4.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV4.java new file mode 100644 index 000000000..002b67d19 --- /dev/null +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV4.java @@ -0,0 +1,119 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.participant.intermediary.api.impl; + +import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener; +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; +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.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.models.base.PfModelException; + +/** + * Wrapper of AutomationCompositionElementListener. + * Valid since 8.1.1 release. + */ +public abstract class AcElementListenerV4 implements AutomationCompositionElementListener { + protected final ParticipantIntermediaryApi intermediaryApi; + + protected AcElementListenerV4(ParticipantIntermediaryApi intermediaryApi) { + this.intermediaryApi = intermediaryApi; + } + + @Override + public void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); + } + + @Override + public void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked"); + } + + @Override + public void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); + } + + @Override + public void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement, + InstanceElementDto instanceElementUpdated) throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Update not supported"); + + } + + @Override + public void prime(CompositionDto composition) throws PfModelException { + intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED, + StateChangeResult.NO_ERROR, "Primed"); + } + + @Override + public void deprime(CompositionDto composition) throws PfModelException { + intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED, + StateChangeResult.NO_ERROR, "Deprimed"); + } + + @Override + public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate, int stage) + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElementMigrate.instanceId(), + instanceElementMigrate.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); + } + + @Override + public void migratePrecheck(CompositionElementDto compositionElement, + CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, + InstanceElementDto instanceElementMigrate) throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElementMigrate.instanceId(), + instanceElementMigrate.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration Precheck completed"); + } + + @Override + public void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Review completed"); + } + + @Override + public void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement, int nextStage) + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.UNDEPLOYED, null, + StateChangeResult.NO_ERROR, "Prepare completed"); + } +} diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AutomationCompositionElementListenerV3.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AutomationCompositionElementListenerV3.java new file mode 100644 index 000000000..1e5bb564d --- /dev/null +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AutomationCompositionElementListenerV3.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.participant.intermediary.api.impl; + +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; +import org.onap.policy.models.base.PfModelException; + +public interface AutomationCompositionElementListenerV3 { + + void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; + + void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; + + void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; + + void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; + + void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; + + void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement, + InstanceElementDto instanceElementUpdated) throws PfModelException; + + void prime(CompositionDto composition) throws PfModelException; + + void deprime(CompositionDto composition) throws PfModelException; + + void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate, + int nextStage) throws PfModelException; + + void migratePrecheck(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) throws PfModelException; + + void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException; + + void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException; +} diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandler.java index 4c5baf6fd..5b33221fe 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandler.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandler.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation. + * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; 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.ParticipantUtils; import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionPrepare; @@ -155,7 +156,7 @@ public class AcSubStateHandler { acPrepareMsg.getAutomationCompositionId(), participantPrepare, DeployState.UNDEPLOYED, SubState.PREPARING); callParticipanPrepare(acPrepareMsg.getMessageId(), participantPrepare.getAcElementList(), - acPrepareMsg.getAutomationCompositionId()); + acPrepareMsg.getStage(), acPrepareMsg.getAutomationCompositionId()); } } } else { @@ -166,7 +167,8 @@ public class AcSubStateHandler { } } - private void callParticipanPrepare(UUID messageId, List acElementList, UUID instanceId) { + private void callParticipanPrepare(UUID messageId, List acElementList, Integer stageMsg, + UUID instanceId) { var automationComposition = cacheProvider.getAutomationComposition(instanceId); for (var elementDeploy : acElementList) { var element = automationComposition.getElements().get(elementDeploy.getId()); @@ -174,9 +176,13 @@ public class AcSubStateHandler { .getCommonProperties(automationComposition.getCompositionId(), element.getDefinition()); var compositionElement = cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(), element, compositionInProperties); - var instanceElement = new InstanceElementDto(instanceId, elementDeploy.getId(), - elementDeploy.getProperties(), element.getOutProperties()); - listener.prepare(messageId, compositionElement, instanceElement); + var stageSet = ParticipantUtils.findStageSetPrepare(compositionInProperties); + if (stageSet.contains(stageMsg)) { + var instanceElement = + new InstanceElementDto(instanceId, elementDeploy.getId(), elementDeploy.getProperties(), + element.getOutProperties()); + listener.prepare(messageId, compositionElement, instanceElement, stageMsg); + } } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java index d9f2b7acd..9fc6b1dad 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. + * Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -155,11 +155,9 @@ public class AutomationCompositionOutHandler { return; } - if (deployState != null && !SubState.NONE.equals(element.getSubState())) { - handleSubState(automationComposition, element); + if (!SubState.NONE.equals(element.getSubState())) { if (!StateChangeResult.NO_ERROR.equals(stateChangeResult)) { - stateChangeResult = StateChangeResult.NO_ERROR; - LOGGER.warn("SubState has always NO_ERROR result!"); + handleSubState(automationComposition, element, stateChangeResult); } } else if (deployState != null) { handleDeployState(automationComposition, element, deployState, stateChangeResult); @@ -225,7 +223,11 @@ public class AutomationCompositionOutHandler { } } - private void handleSubState(AutomationComposition automationComposition, AutomationCompositionElement element) { + private void handleSubState(AutomationComposition automationComposition, AutomationCompositionElement element, + StateChangeResult stateChangeResult) { + if (StateChangeResult.FAILED.equals(stateChangeResult)) { + return; + } element.setSubState(SubState.NONE); var checkOpt = automationComposition.getElements().values().stream() .filter(acElement -> !SubState.NONE.equals(acElement.getSubState())).findAny(); 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 c422b22b5..027127ac8 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 @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. + * Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -397,17 +397,19 @@ public class ThreadHandler implements Closeable { * @param messageId the messageId * @param compositionElement the information of the Automation Composition Definition Element * @param instanceElement the information of the Automation Composition Instance Element + * @param stage the stage */ public void prepare(UUID messageId, CompositionElementDto compositionElement, - InstanceElementDto instanceElement) { + InstanceElementDto instanceElement, int stage) { cleanExecution(instanceElement.elementId(), messageId); - var result = executor.submit(() -> this.prepareProcess(compositionElement, instanceElement)); + var result = executor.submit(() -> this.prepareProcess(compositionElement, instanceElement, stage)); executionMap.put(instanceElement.elementId(), result); } - private void prepareProcess(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + private void prepareProcess(CompositionElementDto compositionElement, InstanceElementDto instanceElement, + int stage) { try { - listener.prepare(compositionElement, instanceElement); + listener.prepare(compositionElement, instanceElement, stage); } catch (PfModelException e) { LOGGER.error("Automation composition element prepare Pre Deploy failed {} {}", instanceElement.elementId(), e.getMessage()); diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandlerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandlerTest.java index 8fad1d22b..d9df764a2 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandlerTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandlerTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation. + * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ package org.onap.policy.clamp.acm.participant.intermediary.handler; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -141,6 +142,7 @@ class AcSubStateHandlerTest { var acPrepareMsg = new AutomationCompositionPrepare(); acPrepareMsg.setPreDeploy(true); + acPrepareMsg.setStage(0); assertDoesNotThrow(() -> ach.handleAcPrepare(acPrepareMsg)); acPrepareMsg.setParticipantId(CommonTestData.getParticipantId()); @@ -165,7 +167,7 @@ class AcSubStateHandlerTest { .thenReturn(Map.of(automationComposition.getCompositionId(), map)); ach.handleAcPrepare(acPrepareMsg); - verify(listener, times(automationComposition.getElements().size())).prepare(any(), any(), any()); + verify(listener, times(automationComposition.getElements().size())).prepare(any(), any(), any(), anyInt()); } @Test 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 8502becbb..7e5ca57c8 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 @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. + * Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -260,8 +260,8 @@ class ThreadHandlerTest { var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), properties, properties); var messageId = UUID.randomUUID(); - threadHandler.prepare(messageId, compositionElement, instanceElement); - verify(listener, timeout(TIMEOUT)).prepare(compositionElement, instanceElement); + threadHandler.prepare(messageId, compositionElement, instanceElement, 0); + verify(listener, timeout(TIMEOUT)).prepare(compositionElement, instanceElement, 0); clearInvocations(listener); threadHandler.review(messageId, compositionElement, instanceElement); @@ -295,9 +295,9 @@ class ThreadHandlerTest { var element = new AcElementDeploy(); element.setId(elementId); doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) - .prepare(compositionElement, instanceElement); + .prepare(compositionElement, instanceElement, 0); var messageId = UUID.randomUUID(); - threadHandler.prepare(messageId, compositionElement, instanceElement); + threadHandler.prepare(messageId, compositionElement, instanceElement, 0); verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Automation composition element prepare Pre Deploy failed"); diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java index 0966ab30f..1ae309d5d 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2025 Nordix Foundation. + * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -427,25 +427,22 @@ public class AutomationCompositionInstantiationProvider { throw new PfModelRuntimeException(Status.BAD_REQUEST, automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId); } - if (!DeployState.UNDEPLOYED.equals(automationComposition.getDeployState()) - && !DeployState.DELETING.equals(automationComposition.getDeployState())) { - throw new PfModelRuntimeException(Status.BAD_REQUEST, - "Automation composition state is still " + automationComposition.getDeployState()); - } - if (DeployState.DELETING.equals(automationComposition.getDeployState()) - && StateChangeResult.NO_ERROR.equals(automationComposition.getStateChangeResult())) { - throw new PfModelRuntimeException(Status.BAD_REQUEST, - "Automation composition state is still " + automationComposition.getDeployState()); - } var acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId()); var participantIds = acDefinition.getElementStateMap().values().stream() .map(NodeTemplateState::getParticipantId).collect(Collectors.toSet()); participantProvider.verifyParticipantState(participantIds); + var result = acInstanceStateResolver.resolve(DeployOrder.DELETE, + null, null, + automationComposition.getDeployState(), automationComposition.getLockState(), + automationComposition.getSubState(), automationComposition.getStateChangeResult()); + if (!DeployOrder.DELETE.name().equals(result)) { + var msg = String.format(NOT_VALID_ORDER, DeployOrder.DELETE, + automationComposition.getDeployState(), automationComposition.getLockState(), + automationComposition.getSubState(), automationComposition.getStateChangeResult()); + throw new PfModelRuntimeException(Status.BAD_REQUEST, msg); + } supervisionAcHandler.delete(automationComposition, acDefinition); - var response = new InstantiationResponse(); - response.setInstanceId(automationComposition.getInstanceId()); - response.setAffectedAutomationComposition(automationComposition.getKey().asIdentifier()); - return response; + return createInstantiationResponse(automationComposition); } /** @@ -506,7 +503,7 @@ public class AutomationCompositionInstantiationProvider { break; case "PREPARE": - supervisionAcHandler.prepare(automationComposition); + supervisionAcHandler.prepare(automationComposition, acDefinition); break; case "REVIEW": diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java index f436eb287..d332339ea 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2025 Nordix Foundation. + * Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -156,15 +156,18 @@ public class SupervisionAcHandler { * Handle prepare Pre Deploy an AutomationComposition instance. * * @param automationComposition the AutomationComposition + * @param acDefinition the AutomationCompositionDefinition */ - public void prepare(AutomationComposition automationComposition) { + public void prepare(AutomationComposition automationComposition, AutomationCompositionDefinition acDefinition) { AcmUtils.setCascadedState(automationComposition, DeployState.UNDEPLOYED, LockState.NONE, SubState.PREPARING); automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); + var stage = ParticipantUtils.getFirstStage(automationComposition, acDefinition.getServiceTemplate()); + automationComposition.setPhase(stage); automationCompositionProvider.updateAutomationComposition(automationComposition); executor.execute(() -> { var acToSend = new AutomationComposition(automationComposition); decryptInstanceProperties(acToSend); - acPreparePublisher.sendPrepare(acToSend); + acPreparePublisher.sendPrepare(acToSend, stage); }); } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AcPreparePublisher.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AcPreparePublisher.java index acf403595..fd465b700 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AcPreparePublisher.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AcPreparePublisher.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation. + * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,11 +42,13 @@ public class AcPreparePublisher extends AbstractParticipantPublisher instantiationProvider.deleteAutomationComposition(wrongCompositionId, instanceId)) .hasMessageMatching(compositionId + DO_NOT_MATCH + wrongCompositionId); - assertThatDeleteThrownBy(automationComposition, DeployState.DEPLOYED, LockState.LOCKED); - assertThatDeleteThrownBy(automationComposition, DeployState.DEPLOYING, LockState.NONE); - assertThatDeleteThrownBy(automationComposition, DeployState.UNDEPLOYING, LockState.LOCKED); - assertThatDeleteThrownBy(automationComposition, DeployState.DELETING, LockState.NONE); - automationComposition.setDeployState(DeployState.UNDEPLOYED); automationComposition.setLockState(LockState.NONE); when(acProvider.deleteAutomationComposition(instanceId)).thenReturn(automationComposition); - instantiationProvider.deleteAutomationComposition(compositionId, instanceId); verify(supervisionAcHandler).delete(any(), any()); } + @Test + void testInstantiationDeleteError() { + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Delete"); + automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); + assertThatDeleteThrownBy(automationComposition, DeployState.DEPLOYED, LockState.LOCKED); + assertThatDeleteThrownBy(automationComposition, DeployState.DEPLOYING, LockState.NONE); + assertThatDeleteThrownBy(automationComposition, DeployState.UNDEPLOYING, LockState.LOCKED); + assertThatDeleteThrownBy(automationComposition, DeployState.DELETING, LockState.NONE); + } + private void assertThatDeleteThrownBy(AutomationComposition automationComposition, DeployState deployState, LockState lockState) { automationComposition.setDeployState(deployState); automationComposition.setLockState(lockState); var acProvider = mock(AutomationCompositionProvider.class); + when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) + .thenReturn(automationComposition); var acDefinitionProvider = mock(AcDefinitionProvider.class); var acRuntimeParamaterGroup = mock(AcRuntimeParameterGroup.class); var instantiationProvider = - new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, null, null, null, + new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, + new AcInstanceStateResolver(), null, mock(ParticipantProvider.class), acRuntimeParamaterGroup, null); - when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) - .thenReturn(automationComposition); + var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + var compositionId = acDefinition.getCompositionId(); + when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acDefinition); + automationComposition.setCompositionId(compositionId); - var compositionId = automationComposition.getCompositionId(); var instanceId = automationComposition.getInstanceId(); assertThatThrownBy(() -> instantiationProvider.deleteAutomationComposition(compositionId, instanceId)) - .hasMessageMatching(String.format(DELETE_BAD_REQUEST, deployState)); + .hasMessageStartingWith(String.format(DELETE_BAD_REQUEST)); } @Test @@ -762,7 +771,7 @@ class AutomationCompositionInstantiationProviderTest { acInstanceStateUpdate.setLockOrder(LockOrder.NONE); acInstanceStateUpdate.setSubOrder(SubOrder.PREPARE); provider.compositionInstanceState(compositionId, instanceId, acInstanceStateUpdate); - verify(supervisionAcHandler).prepare(any(AutomationComposition.class)); + verify(supervisionAcHandler).prepare(any(AutomationComposition.class), any()); automationComposition.setDeployState(DeployState.DEPLOYED); automationComposition.setLockState(LockState.LOCKED); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java index e3baa6f63..22189329c 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2025 Nordix Foundation. + * Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -437,10 +437,12 @@ class SupervisionAcHandlerTest { mock(AutomationCompositionDeployPublisher.class), mock(AutomationCompositionStateChangePublisher.class), mock(AcElementPropertiesPublisher.class), mock(AutomationCompositionMigrationPublisher.class), acPreparePublisher, mock(MessageProvider.class), mock(EncryptionUtils.class)); + var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Migrate"); - handler.prepare(automationComposition); - verify(acPreparePublisher, timeout(1000)).sendPrepare(any(AutomationComposition.class)); + handler.prepare(automationComposition, acDefinition); + verify(acPreparePublisher, timeout(1000)).sendPrepare(any(AutomationComposition.class), anyInt()); } @Test 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 bd1850050..2f75ba0ad 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 @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2025 Nordix Foundation. + * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -322,14 +322,6 @@ class SupervisionScannerTest { verify(simpleScanner).simpleScan(automationComposition, new UpdateSync()); verify(messageProvider).removeJob(JOB_ID); - clearInvocations(simpleScanner); - clearInvocations(messageProvider); - automationComposition.setDeployState(DeployState.UNDEPLOYED); - automationComposition.setSubState(SubState.PREPARING); - supervisionScanner.run(); - verify(simpleScanner).simpleScan(automationComposition, new UpdateSync()); - verify(messageProvider).removeJob(JOB_ID); - clearInvocations(simpleScanner); clearInvocations(messageProvider); automationComposition.setDeployState(DeployState.DEPLOYED); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java index 4e862c4e9..ad3feebe0 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation. + * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -243,7 +243,7 @@ class SupervisionMessagesTest { publisher.active(topicSink); var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); - publisher.sendPrepare(automationComposition); + publisher.sendPrepare(automationComposition, 0); verify(topicSink).send(anyString()); } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScannerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScannerTest.java index 077580ded..1cd1146a5 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScannerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScannerTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2025 Nordix Foundation. + * Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,12 +35,14 @@ import java.util.UUID; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils; +import org.onap.policy.clamp.acm.runtime.supervision.comm.AcPreparePublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionMigrationPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher; import org.onap.policy.clamp.acm.runtime.util.CommonTestData; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; 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.SubState; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; import org.onap.policy.clamp.models.acm.utils.TimestampHelper; @@ -69,12 +71,11 @@ class StageScannerTest { var acProvider = mock(AutomationCompositionProvider.class); when(acProvider.updateAutomationComposition(any())).thenReturn(automationComposition); - var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup); var supervisionScanner = new StageScanner(acProvider, mock(ParticipantSyncPublisher.class), - mock(AutomationCompositionMigrationPublisher.class), acRuntimeParameterGroup, encryptionUtils); - + mock(AutomationCompositionMigrationPublisher.class), mock(AcPreparePublisher.class), + acRuntimeParameterGroup, encryptionUtils); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); supervisionScanner.scanStage(automationComposition, serviceTemplate, new UpdateSync()); verify(acProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class)); @@ -99,4 +100,56 @@ class StageScannerTest { assertEquals(DeployState.DEPLOYED, automationComposition.getDeployState()); assertEquals(compositionTargetId, automationComposition.getCompositionId()); } + + @Test + void testSendAutomationCompositionPrepare() { + var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud"); + automationComposition.setDeployState(DeployState.UNDEPLOYED); + automationComposition.setSubState(SubState.PREPARING); + automationComposition.setLockState(LockState.NONE); + automationComposition.setCompositionId(COMPOSITION_ID); + automationComposition.setLastMsg(TimestampHelper.now()); + automationComposition.setPhase(0); + for (var element : automationComposition.getElements().values()) { + element.setDeployState(DeployState.UNDEPLOYED); + element.setLockState(LockState.NONE); + element.setSubState(SubState.NONE); + } + // first element is not prepared yet + var element = automationComposition.getElements().entrySet().iterator().next().getValue(); + element.setSubState(SubState.PREPARING); + + var acProvider = mock(AutomationCompositionProvider.class); + when(acProvider.updateAutomationComposition(any())).thenReturn(automationComposition); + + var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); + var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup); + var supervisionScanner = new StageScanner(acProvider, mock(ParticipantSyncPublisher.class), + mock(AutomationCompositionMigrationPublisher.class), mock(AcPreparePublisher.class), + acRuntimeParameterGroup, encryptionUtils); + + var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + supervisionScanner.scanStage(automationComposition, serviceTemplate, new UpdateSync()); + verify(acProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class)); + assertEquals(SubState.PREPARING, automationComposition.getSubState()); + + // send message for next stage + clearInvocations(acProvider); + var toscaNodeTemplate = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() + .get(element.getDefinition().getName()); + var prepare = Map.of("prepare", List.of(1)); + toscaNodeTemplate.setProperties(Map.of("stage", prepare)); + + supervisionScanner.scanStage(automationComposition, serviceTemplate, new UpdateSync()); + verify(acProvider).updateAutomationComposition(any(AutomationComposition.class)); + assertEquals(SubState.PREPARING, automationComposition.getSubState()); + + // first element is prepared + clearInvocations(acProvider); + element.setSubState(SubState.NONE); + supervisionScanner.scanStage(automationComposition, serviceTemplate, new UpdateSync()); + verify(acProvider).updateAutomationComposition(any(AutomationComposition.class)); + + assertEquals(SubState.NONE, automationComposition.getSubState()); + } } -- 2.16.6