From: adheli.tavares Date: Thu, 8 May 2025 09:44:41 +0000 (+0100) Subject: Add rollback signatures for participant intermediary X-Git-Tag: 8.2.0~12 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F54%2F140854%2F2;p=policy%2Fclamp.git Add rollback signatures for participant intermediary Issue-ID: POLICY-5334 Change-Id: I9728f9285d2cbb85069f1db010d70e76c8e86937 Signed-off-by: adheli.tavares --- 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 510708292..270aa0385 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 @@ -51,7 +51,7 @@ public class AutomationCompositionElementHandler extends AcElementListenerV4 { } /** - * Handle a deploy on a automation composition element. + * Handle deploying an automation composition element. * * @param compositionElement the information of the Automation Composition Definition Element * @param instanceElement the information of the Automation Composition Instance Element @@ -64,7 +64,7 @@ public class AutomationCompositionElementHandler extends AcElementListenerV4 { } /** - * Handle a automation composition element state change. + * Handle an automation composition element state change. * * @param compositionElement the information of the Automation Composition Definition Element * @param instanceElement the information of the Automation Composition Instance Element @@ -156,4 +156,11 @@ public class AutomationCompositionElementHandler extends AcElementListenerV4 { LOGGER.debug("review call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); simulatorService.review(instanceElement.instanceId(), instanceElement.elementId()); } + + @Override + public void rollbackMigration(CompositionElementDto compositionElement, + InstanceElementDto instanceElement, int nextStage) { + LOGGER.debug("rollback call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); + simulatorService.rollback(instanceElement.instanceId(), instanceElement.elementId()); + } } 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 93a9ee70f..dfced7cf4 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 @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.locks.LockSupport; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; @@ -80,16 +81,16 @@ public class SimulatorService { /** * Set OutProperties. * - * @param instanceId the automationComposition Id - * @param elementId the automationComposition Element Id - * @param useState the useState + * @param instanceId the automationComposition Id + * @param elementId the automationComposition Element Id + * @param useState the useState * @param operationalState the operationalState - * @param outProperties the outProperties + * @param outProperties the outProperties */ public void setOutProperties(UUID instanceId, UUID elementId, String useState, String operationalState, Map outProperties) { intermediaryApi.sendAcElementInfo(instanceId, elementId, useState, operationalState, - outProperties); + outProperties); } /** @@ -130,7 +131,7 @@ public class SimulatorService { internalData.setCompositionId(entry.getKey()); internalData.setCompositionDefinitionElementId(acElementsDefinition.getAcElementDefinitionId()); internalData.setIntProperties( - acElementsDefinition.getAutomationCompositionElementToscaNodeTemplate().getProperties()); + acElementsDefinition.getAutomationCompositionElementToscaNodeTemplate().getProperties()); internalData.setOutProperties(acElementsDefinition.getOutProperties()); internalDatas.getList().add(internalData); } @@ -144,34 +145,28 @@ public class SimulatorService { } - protected boolean execution(int timeMs, String msg, UUID elementId) { - long endTime = System.currentTimeMillis() + timeMs; - while (System.currentTimeMillis() < endTime) { - try { - if (Thread.currentThread().isInterrupted()) { - LOGGER.debug(msg, elementId); - return false; - } - Thread.sleep(10L); - } catch (InterruptedException e) { + protected boolean isInterrupted(int timeMs, String msg, UUID elementId) { + long endTime = System.nanoTime() + (timeMs * 1_000_000L); + while (System.nanoTime() < endTime) { + if (Thread.interrupted()) { LOGGER.debug(msg, elementId); - Thread.currentThread().interrupt(); - return false; + return true; } + LockSupport.parkNanos(10_000_000L); } - return true; + return false; } /** - * Handle a deploy on a automation composition element. + * Handle deploying an automation composition element. * - * @param instanceId the instanceId - * @param elementId the elementId + * @param instanceId the instanceId + * @param elementId the elementId * @param outProperties the outProperties */ public void deploy(UUID instanceId, UUID elementId, Map outProperties) { - if (!execution(getConfig().getDeployTimerMs(), - "Current Thread deploy is Interrupted during execution {}", elementId)) { + if (isInterrupted(getConfig().getDeployTimerMs(), + "Current Thread deploy is Interrupted during execution {}", elementId)) { return; } @@ -180,26 +175,26 @@ public class SimulatorService { intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties); intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); } else { outProperties.put(INTERNAL_STATE, DeployState.UNDEPLOYED.name()); intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties); intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!"); + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!"); } } /** - * Handle an udeploy on a automation composition element. + * Handle undeploying an automation composition element. * - * @param instanceId the instanceId - * @param elementId the elementId + * @param instanceId the instanceId + * @param elementId the elementId * @param outProperties the outProperties */ public void undeploy(UUID instanceId, UUID elementId, Map outProperties) { - if (!execution(getConfig().getUndeployTimerMs(), - "Current Thread undeploy is Interrupted during execution {}", elementId)) { + if (isInterrupted(getConfig().getUndeployTimerMs(), + "Current Thread undeploy is Interrupted during execution {}", elementId)) { return; } @@ -208,119 +203,119 @@ public class SimulatorService { intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties); intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); } else { outProperties.put(INTERNAL_STATE, DeployState.DEPLOYED.name()); intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, outProperties); intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Undeploy failed!"); + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Undeploy failed!"); } } /** - * Handle a lock on a automation composition element. + * Handle locking an automation composition element. * * @param instanceId the instanceId - * @param elementId the elementId + * @param elementId the elementId */ public void lock(UUID instanceId, UUID elementId) { - if (!execution(getConfig().getLockTimerMs(), - "Current Thread lock is Interrupted during execution {}", elementId)) { + if (isInterrupted(getConfig().getLockTimerMs(), + "Current Thread lock is Interrupted during execution {}", elementId)) { return; } if (getConfig().isLockSuccess()) { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); + null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); } else { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!"); + null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!"); } } /** - * Handle an unlock on a automation composition element. + * Handle unlocking an automation composition element. * * @param instanceId the instanceId - * @param elementId the elementId + * @param elementId the elementId */ public void unlock(UUID instanceId, UUID elementId) { - if (!execution(getConfig().getUnlockTimerMs(), - "Current Thread unlock is Interrupted during execution {}", elementId)) { + if (isInterrupted(getConfig().getUnlockTimerMs(), + "Current Thread unlock is Interrupted during execution {}", elementId)) { return; } if (getConfig().isUnlockSuccess()) { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked"); + null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked"); } else { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!"); + null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!"); } } /** - * Handle a delete on a automation composition element. + * Handle deleting an automation composition element. * * @param instanceId the instanceId - * @param elementId the elementId + * @param elementId the elementId */ public void delete(UUID instanceId, UUID elementId) { - if (!execution(getConfig().getDeleteTimerMs(), - "Current Thread delete is Interrupted during execution {}", elementId)) { + if (isInterrupted(getConfig().getDeleteTimerMs(), + "Current Thread delete is Interrupted during execution {}", elementId)) { return; } if (getConfig().isDeleteSuccess()) { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); + DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); } else { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Delete failed!"); + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Delete failed!"); } } /** - * Handle an update on a automation composition element. + * Handle an update on an automation composition element. * * @param instanceId the instanceId - * @param elementId the elementId + * @param elementId the elementId */ public void update(UUID instanceId, UUID elementId) { - if (!execution(getConfig().getUpdateTimerMs(), - "Current Thread update is Interrupted during execution {}", elementId)) { + if (isInterrupted(getConfig().getUpdateTimerMs(), + "Current Thread update is Interrupted during execution {}", elementId)) { return; } if (getConfig().isUpdateSuccess()) { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated"); + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated"); } else { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!"); + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!"); } } /** - * Handle a prime on a automation composition definition. + * Handle a prime on an automation composition definition. * * @param composition the information of the Automation Composition Definition */ public void prime(CompositionDto composition) { - if (!execution(getConfig().getPrimeTimerMs(), - "Current Thread prime is Interrupted during execution {}", composition.compositionId())) { + if (isInterrupted(getConfig().getPrimeTimerMs(), + "Current Thread prime is Interrupted during execution {}", composition.compositionId())) { return; } if (getConfig().isPrimeSuccess()) { sendOutProperties(composition, AcTypeState.PRIMED.name()); intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED, - StateChangeResult.NO_ERROR, "Primed"); + StateChangeResult.NO_ERROR, "Primed"); } else { sendOutProperties(composition, AcTypeState.COMMISSIONED.name()); intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED, - StateChangeResult.FAILED, "Prime failed!"); + StateChangeResult.FAILED, "Prime failed!"); } } @@ -328,45 +323,45 @@ public class SimulatorService { for (var elementEntry : composition.outPropertiesMap().entrySet()) { elementEntry.getValue().put(INTERNAL_STATE, data); intermediaryApi.sendAcDefinitionInfo( - composition.compositionId(), elementEntry.getKey(), elementEntry.getValue()); + composition.compositionId(), elementEntry.getKey(), elementEntry.getValue()); } } /** - * Handle a deprime on a automation composition definition. + * Handle a deprime on an automation composition definition. * * @param composition the information of the Automation Composition Definition */ public void deprime(CompositionDto composition) { - if (!execution(getConfig().getDeprimeTimerMs(), - "Current Thread deprime is Interrupted during execution {}", composition.compositionId())) { + if (isInterrupted(getConfig().getDeprimeTimerMs(), + "Current Thread deprime is Interrupted during execution {}", composition.compositionId())) { return; } if (getConfig().isDeprimeSuccess()) { sendOutProperties(composition, AcTypeState.COMMISSIONED.name()); intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED, - StateChangeResult.NO_ERROR, "Deprimed"); + StateChangeResult.NO_ERROR, "Deprimed"); } else { sendOutProperties(composition, AcTypeState.PRIMED.name()); intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED, - StateChangeResult.FAILED, "Deprime failed!"); + StateChangeResult.FAILED, "Deprime failed!"); } } /** - * Handle a migrate on a automation composition element. + * Handle a migration on an automation composition element. * - * @param instanceId the instanceId - * @param elementId the elementId - * @param stage the stage + * @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 + * @param instanceOutProperties in Properties from instance element */ public void migrate(UUID instanceId, UUID elementId, int stage, Map compositionInProperties, - Map instanceOutProperties) { - if (!execution(getConfig().getMigrateTimerMs(), - "Current Thread migrate is Interrupted during execution {}", elementId)) { + Map instanceOutProperties) { + if (isInterrupted(getConfig().getMigrateTimerMs(), + "Current Thread migrate is Interrupted during execution {}", elementId)) { return; } @@ -385,54 +380,54 @@ public class SimulatorService { intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, instanceOutProperties); if (nextStage == 1000) { intermediaryApi.updateAutomationCompositionElementState( - instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); + instanceId, elementId, + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); } else { intermediaryApi.updateAutomationCompositionElementStage( - instanceId, elementId, - StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Migrated"); + instanceId, elementId, + StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Migrated"); } } else { intermediaryApi.updateAutomationCompositionElementState( - instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!"); + instanceId, elementId, + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!"); } } /** - * Handle a Migrate Precheck on a automation composition element. + * Handle a Migrate Precheck on an automation composition element. * * @param instanceId the instanceId - * @param elementId the elementId + * @param elementId the elementId */ public void migratePrecheck(UUID instanceId, UUID elementId) { - if (!execution(config.getMigratePrecheckTimerMs(), - "Current Thread migrate precheck is Interrupted during execution {}", elementId)) { + if (isInterrupted(config.getMigratePrecheckTimerMs(), + "Current Thread migrate precheck is Interrupted during execution {}", elementId)) { return; } if (config.isMigratePrecheck()) { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migration precheck completed"); + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migration precheck completed"); } else { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migration precheck failed"); + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migration precheck failed"); } } /** - * Handle a Prepare on a automation composition element. + * Handle a Prepare on an automation composition element. * - * @param instanceId the instanceId - * @param elementId the elementId - * @param stage the stage + * @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 + * @param instanceOutProperties in Properties from instance element */ 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)) { + Map instanceOutProperties) { + if (isInterrupted(config.getPrepareTimerMs(), + "Current Thread prepare is Interrupted during execution {}", elementId)) { return; } @@ -451,36 +446,58 @@ public class SimulatorService { intermediaryApi.sendAcElementInfo(instanceId, elementId, null, null, instanceOutProperties); if (nextStage == 1000) { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Prepare completed"); + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Prepare completed"); } else { intermediaryApi.updateAutomationCompositionElementStage( - instanceId, elementId, - StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Prepared"); + instanceId, elementId, + StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Prepared"); } } else { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Prepare failed"); + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Prepare failed"); } } /** - * Handle a Review on a automation composition element. + * Handle a Review on an automation composition element. * * @param instanceId the instanceId - * @param elementId the elementId + * @param elementId the elementId */ public void review(UUID instanceId, UUID elementId) { - if (!execution(config.getReviewTimerMs(), - "Current Thread review is Interrupted during execution {}", elementId)) { + if (isInterrupted(config.getReviewTimerMs(), + "Current Thread review is Interrupted during execution {}", elementId)) { return; } if (config.isReview()) { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Review completed"); + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Review completed"); } else { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Review failed"); + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Review failed"); + } + } + + /** + * Handle rollback of an automation composition. + * + * @param instanceId AC instance ID + * @param elementId AC element ID + */ + public void rollback(UUID instanceId, UUID elementId) { + if (isInterrupted(getConfig().getRollbackTimerMs(), + "Current Thread for rollback was Interrupted during execution {}", instanceId)) { + LOGGER.debug("Rollback interrupted"); + return; + } + + if (config.isRollback()) { + intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration rollback done"); + } else { + intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, null, + StateChangeResult.FAILED, "Migration rollback failed"); } } } diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java index f38f3079b..546ee4d43 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-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. @@ -48,6 +48,8 @@ public class SimConfig { private boolean deprimeSuccess = true; + private boolean rollback = true; + private int deployTimerMs = 1000; private int undeployTimerMs = 1000; @@ -71,4 +73,6 @@ public class SimConfig { private int primeTimerMs = 100; private int deprimeTimerMs = 100; + + private int rollbackTimerMs = 100; } 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 57c13ce90..baf1b2a9e 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 @@ -20,8 +20,15 @@ package org.onap.policy.clamp.acm.participant.sim.main.handler; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; import java.util.HashMap; import java.util.List; @@ -44,11 +51,11 @@ class AutomationCompositionElementHandlerTest { private static final ToscaConceptIdentifier ELEMENT_DEFINITION_ID = new ToscaConceptIdentifier("name", "1.0.0"); private static final CompositionElementDto COMPOSITION_ELEMENT = - new CompositionElementDto(UUID.randomUUID(), ELEMENT_DEFINITION_ID, Map.of(), Map.of()); + new CompositionElementDto(UUID.randomUUID(), ELEMENT_DEFINITION_ID, Map.of(), Map.of()); private static final InstanceElementDto INSTANCE_ELEMENT = - new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), new HashMap<>()); + new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), new HashMap<>()); private static final CompositionDto COMPOSITION = new CompositionDto(UUID.randomUUID(), - Map.of(ELEMENT_DEFINITION_ID, Map.of()), Map.of(ELEMENT_DEFINITION_ID, new HashMap<>())); + Map.of(ELEMENT_DEFINITION_ID, Map.of()), Map.of(ELEMENT_DEFINITION_ID, new HashMap<>())); @Test void testDeploy() { @@ -59,14 +66,14 @@ class AutomationCompositionElementHandlerTest { simulatorService.setConfig(config); acElementHandler.deploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, - null, StateChangeResult.NO_ERROR, "Deployed"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.NO_ERROR, "Deployed"); config.setDeploySuccess(false); acElementHandler.deploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, - null, StateChangeResult.FAILED, "Deploy failed!"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.FAILED, "Deploy failed!"); } @Test @@ -78,14 +85,14 @@ class AutomationCompositionElementHandlerTest { simulatorService.setConfig(config); acElementHandler.undeploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, - null, StateChangeResult.NO_ERROR, "Undeployed"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.NO_ERROR, "Undeployed"); config.setUndeploySuccess(false); acElementHandler.undeploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, - null, StateChangeResult.FAILED, "Undeploy failed!"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.FAILED, "Undeploy failed!"); } @Test @@ -97,14 +104,14 @@ class AutomationCompositionElementHandlerTest { simulatorService.setConfig(config); acElementHandler.lock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.LOCKED, - StateChangeResult.NO_ERROR, "Locked"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.LOCKED, + StateChangeResult.NO_ERROR, "Locked"); config.setLockSuccess(false); acElementHandler.lock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.UNLOCKED, - StateChangeResult.FAILED, "Lock failed!"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.UNLOCKED, + StateChangeResult.FAILED, "Lock failed!"); } @Test @@ -116,14 +123,14 @@ class AutomationCompositionElementHandlerTest { simulatorService.setConfig(config); acElementHandler.unlock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.UNLOCKED, - StateChangeResult.NO_ERROR, "Unlocked"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.UNLOCKED, + StateChangeResult.NO_ERROR, "Unlocked"); config.setUnlockSuccess(false); acElementHandler.unlock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.LOCKED, - StateChangeResult.FAILED, "Unlock failed!"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.LOCKED, + StateChangeResult.FAILED, "Unlock failed!"); } @Test @@ -134,18 +141,18 @@ class AutomationCompositionElementHandlerTest { var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); var instanceElementUpdated = new InstanceElementDto( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - Map.of("key", "value"), Map.of()); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + Map.of("key", "value"), Map.of()); acElementHandler.update(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, instanceElementUpdated); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated"); config.setUpdateSuccess(false); acElementHandler.update(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, instanceElementUpdated); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!"); } @Test @@ -157,14 +164,14 @@ class AutomationCompositionElementHandlerTest { simulatorService.setConfig(config); acElementHandler.delete(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DELETED, - null, StateChangeResult.NO_ERROR, "Deleted"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DELETED, + null, StateChangeResult.NO_ERROR, "Deleted"); config.setDeleteSuccess(false); acElementHandler.delete(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, - null, StateChangeResult.FAILED, "Delete failed!"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.FAILED, "Delete failed!"); } @Test @@ -176,12 +183,12 @@ class AutomationCompositionElementHandlerTest { simulatorService.setConfig(config); acElementHandler.prime(COMPOSITION); verify(intermediaryApi).updateCompositionState( - COMPOSITION.compositionId(), AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed"); + COMPOSITION.compositionId(), AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed"); config.setPrimeSuccess(false); acElementHandler.prime(COMPOSITION); verify(intermediaryApi).updateCompositionState( - COMPOSITION.compositionId(), AcTypeState.COMMISSIONED, StateChangeResult.FAILED, "Prime failed!"); + COMPOSITION.compositionId(), AcTypeState.COMMISSIONED, StateChangeResult.FAILED, "Prime failed!"); } @Test @@ -193,12 +200,12 @@ class AutomationCompositionElementHandlerTest { simulatorService.setConfig(config); acElementHandler.deprime(COMPOSITION); verify(intermediaryApi).updateCompositionState( - COMPOSITION.compositionId(), AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); + COMPOSITION.compositionId(), AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); config.setDeprimeSuccess(false); acElementHandler.deprime(COMPOSITION); verify(intermediaryApi).updateCompositionState( - COMPOSITION.compositionId(), AcTypeState.PRIMED, StateChangeResult.FAILED, "Deprime failed!"); + COMPOSITION.compositionId(), AcTypeState.PRIMED, StateChangeResult.FAILED, "Deprime failed!"); } @Test @@ -209,22 +216,22 @@ class AutomationCompositionElementHandlerTest { var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); var compositionElementTarget = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), - Map.of(), Map.of()); + Map.of(), Map.of()); var instanceElementMigrated = new InstanceElementDto( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - Map.of("key", "value"), new HashMap<>()); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + Map.of("key", "value"), new HashMap<>()); acElementHandler - .migrate(COMPOSITION_ELEMENT, compositionElementTarget, INSTANCE_ELEMENT, instanceElementMigrated, 0); + .migrate(COMPOSITION_ELEMENT, compositionElementTarget, INSTANCE_ELEMENT, instanceElementMigrated, 0); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); config.setMigrateSuccess(false); acElementHandler - .migrate(COMPOSITION_ELEMENT, compositionElementTarget, INSTANCE_ELEMENT, instanceElementMigrated, 0); + .migrate(COMPOSITION_ELEMENT, compositionElementTarget, INSTANCE_ELEMENT, instanceElementMigrated, 0); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!"); } @Test @@ -235,14 +242,14 @@ class AutomationCompositionElementHandlerTest { 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()); + Map.of("stage", List.of(1, 2)), Map.of()); var instanceElementMigrated = new InstanceElementDto(INSTANCE_ELEMENT.instanceId(), - INSTANCE_ELEMENT.elementId(), Map.of(), new HashMap<>()); + INSTANCE_ELEMENT.elementId(), Map.of(), new HashMap<>()); acElementHandler - .migrate(COMPOSITION_ELEMENT, compositionElementTarget, INSTANCE_ELEMENT, instanceElementMigrated, 1); + .migrate(COMPOSITION_ELEMENT, compositionElementTarget, INSTANCE_ELEMENT, instanceElementMigrated, 1); verify(intermediaryApi).updateAutomationCompositionElementStage( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - StateChangeResult.NO_ERROR, 2, "stage 1 Migrated"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + StateChangeResult.NO_ERROR, 2, "stage 1 Migrated"); } @Test @@ -253,20 +260,20 @@ class AutomationCompositionElementHandlerTest { var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); var compositionElement = new CompositionElementDto( - UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of(), ElementState.NOT_PRESENT); + UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of(), ElementState.NOT_PRESENT); var instanceElement = new InstanceElementDto( - UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of(), ElementState.NOT_PRESENT); + UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of(), ElementState.NOT_PRESENT); var compoElTargetAdd = new CompositionElementDto( - UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of(), ElementState.NEW); + UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of(), ElementState.NEW); var inElMigratedAdd = new InstanceElementDto(instanceElement.instanceId(), instanceElement.elementId(), - Map.of(), new HashMap<>(), ElementState.NEW); + Map.of(), new HashMap<>(), ElementState.NEW); acElementHandler - .migrate(compositionElement, compoElTargetAdd, instanceElement, inElMigratedAdd, 0); + .migrate(compositionElement, compoElTargetAdd, instanceElement, inElMigratedAdd, 0); verify(intermediaryApi).updateAutomationCompositionElementState( - instanceElement.instanceId(), instanceElement.elementId(), - DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); + instanceElement.instanceId(), instanceElement.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); } @Test @@ -278,18 +285,18 @@ class AutomationCompositionElementHandlerTest { simulatorService.setConfig(config); var compoElTargetRemove = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), - Map.of(), Map.of(), ElementState.REMOVED); + Map.of(), Map.of(), ElementState.REMOVED); var inElMigratedRemove = new InstanceElementDto( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - Map.of("key", "value"), Map.of(), ElementState.REMOVED); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + Map.of("key", "value"), Map.of(), ElementState.REMOVED); acElementHandler - .migrate(COMPOSITION_ELEMENT, compoElTargetRemove, INSTANCE_ELEMENT, inElMigratedRemove, 0); + .migrate(COMPOSITION_ELEMENT, compoElTargetRemove, INSTANCE_ELEMENT, inElMigratedRemove, 0); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); } @Test @@ -300,24 +307,24 @@ class AutomationCompositionElementHandlerTest { var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); simulatorService.setConfig(config); var compositionElementTarget = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), - Map.of(), Map.of()); + Map.of(), Map.of()); var instanceElementMigrated = new InstanceElementDto( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - Map.of("key", "value"), Map.of()); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + Map.of("key", "value"), Map.of()); acElementHandler.migratePrecheck(COMPOSITION_ELEMENT, compositionElementTarget, - INSTANCE_ELEMENT, instanceElementMigrated); + INSTANCE_ELEMENT, instanceElementMigrated); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - DeployState.DEPLOYED, null, - StateChangeResult.NO_ERROR, "Migration precheck completed"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration precheck completed"); config.setMigratePrecheck(false); acElementHandler.migratePrecheck(COMPOSITION_ELEMENT, compositionElementTarget, - INSTANCE_ELEMENT, instanceElementMigrated); + INSTANCE_ELEMENT, instanceElementMigrated); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), - DeployState.DEPLOYED, null, - StateChangeResult.FAILED, "Migration precheck failed"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, + StateChangeResult.FAILED, "Migration precheck failed"); } @Test @@ -329,14 +336,14 @@ class AutomationCompositionElementHandlerTest { simulatorService.setConfig(config); acElementHandler.prepare(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, 0); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, - null, StateChangeResult.NO_ERROR, "Prepare completed"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.NO_ERROR, "Prepare completed"); config.setPrepare(false); acElementHandler.prepare(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, 0); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, - null, StateChangeResult.FAILED, "Prepare failed"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.FAILED, "Prepare failed"); } @Test @@ -348,13 +355,52 @@ class AutomationCompositionElementHandlerTest { simulatorService.setConfig(config); acElementHandler.review(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, - null, StateChangeResult.NO_ERROR, "Review completed"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.NO_ERROR, "Review completed"); config.setReview(false); acElementHandler.review(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); verify(intermediaryApi).updateAutomationCompositionElementState( - INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, - null, StateChangeResult.FAILED, "Review failed"); + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.FAILED, "Review failed"); + } + + @Test + void testRollback() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + + acElementHandler.rollbackMigration(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, DeployState.DEPLOYED.ordinal()); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.NO_ERROR, "Migration rollback done"); + + config.setRollback(false); + acElementHandler.rollbackMigration(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, DeployState.DEPLOYED.ordinal()); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.FAILED, "Migration rollback failed"); + } + + @Test + void testRollbackTimeout() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = mock(SimulatorService.class, withSettings().useConstructor(intermediaryApi)); + + when(simulatorService.getConfig()).thenReturn(config); + when(simulatorService.isInterrupted(anyInt(), anyString(), any())).thenReturn(true); + doCallRealMethod().when(simulatorService).rollback(INSTANCE_ELEMENT.instanceId(), + INSTANCE_ELEMENT.elementId()); + + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi, simulatorService); + acElementHandler.rollbackMigration(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, DeployState.DEPLOYED.ordinal()); + verify(simulatorService).rollback(INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId()); + verify(intermediaryApi, times(0)).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.NO_ERROR, "Migration rollback done"); } } 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 308718326..ca92ad157 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 @@ -22,6 +22,7 @@ package org.onap.policy.clamp.acm.participant.sim.main.handler; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -32,6 +33,7 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto; import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; import org.onap.policy.clamp.acm.participant.sim.comm.CommonTestData; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition; @@ -132,8 +134,8 @@ class SimulatorServiceTest { var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi) { @Override - protected boolean execution(int timeMs, String msg, UUID elementId) { - return false; + protected boolean isInterrupted(int timeMs, String msg, UUID elementId) { + return true; } }; @@ -143,9 +145,27 @@ class SimulatorServiceTest { simulatorService.unlock(UUID.randomUUID(), UUID.randomUUID()); simulatorService.delete(UUID.randomUUID(), UUID.randomUUID()); simulatorService.update(UUID.randomUUID(), UUID.randomUUID()); + simulatorService.prime(mock(CompositionDto.class)); + simulatorService.deprime(mock(CompositionDto.class)); + simulatorService.migrate(UUID.randomUUID(), UUID.randomUUID(), 0, new HashMap<>(), new HashMap<>()); simulatorService.review(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()); } + + @Test + void testImmediateInterruption() throws InterruptedException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + + Thread testThread = new Thread(() -> { + boolean result = simulatorService.isInterrupted(5000, "test", UUID.randomUUID()); + assertTrue(result, "Thread was supposed to be interrupted"); + }); + + testThread.start(); + testThread.interrupt(); + testThread.join(); + } } 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 c4edf6e39..63db854ab 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 @@ -27,85 +27,98 @@ import org.onap.policy.models.base.PfModelException; */ public interface AutomationCompositionElementListener { /** - * Handle a deploy on a automation composition element. + * Handle a deployment on an automation composition element. * * @param compositionElement the information of the Automation Composition Definition Element - * @param instanceElement the information of the Automation Composition Instance Element + * @param instanceElement the information of the Automation Composition Instance Element * @throws PfModelException from Policy framework */ void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; /** - * Handle an udeploy on a automation composition element. + * Handle an udeploy on an automation composition element. * * @param compositionElement the information of the Automation Composition Definition Element - * @param instanceElement the information of the Automation Composition Instance Element + * @param instanceElement the information of the Automation Composition Instance Element * @throws PfModelException in case of a model exception */ void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; /** - * Handle a lock on a automation composition element. + * Handle a lock on an automation composition element. * * @param compositionElement the information of the Automation Composition Definition Element - * @param instanceElement the information of the Automation Composition Instance Element + * @param instanceElement the information of the Automation Composition Instance Element * @throws PfModelException in case of a model exception */ void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; /** - * Handle an unlock on a automation composition element. + * Handle an unlock on an automation composition element. * * @param compositionElement the information of the Automation Composition Definition Element - * @param instanceElement the information of the Automation Composition Instance Element + * @param instanceElement the information of the Automation Composition Instance Element * @throws PfModelException in case of a model exception */ void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; /** - * Handle a delete on a automation composition element. + * Handle delete on an automation composition element. * * @param compositionElement the information of the Automation Composition Definition Element - * @param instanceElement the information of the Automation Composition Instance Element + * @param instanceElement the information of the Automation Composition Instance Element * @throws PfModelException in case of a model exception */ void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; /** - * Handle an update on a automation composition element. + * Handle an update on an automation composition element. * - * @param compositionElement the information of the Automation Composition Definition Element - * @param instanceElement the information of the Automation Composition Instance Element + * @param compositionElement the information of the Automation Composition Definition Element + * @param instanceElement the information of the Automation Composition Instance Element * @param instanceElementUpdated the information of the Automation Composition Instance Element updated * @throws PfModelException from Policy framework */ void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement, - InstanceElementDto instanceElementUpdated) throws PfModelException; + InstanceElementDto instanceElementUpdated) throws PfModelException; void prime(CompositionDto composition) throws PfModelException; void deprime(CompositionDto composition) throws PfModelException; /** - * Handle an update on a automation composition element. + * Handle an update on an automation composition element. * * @param compositionElement the information of the Automation Composition Definition Element * @param compositionElementTarget the information of the Automation Composition Definition Element Target * @param instanceElement the information of the Automation Composition Instance Element * @param instanceElementMigrate the information of the Automation Composition Instance Element updated - * @param nextStage the next stage + * @param nextStage the next stage * @throws PfModelException from Policy framework */ void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, - InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate, - int nextStage) throws PfModelException; + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate, + int nextStage) throws PfModelException; void migratePrecheck(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, - InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) throws PfModelException; + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) + throws PfModelException; void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement, int nextStage) throws PfModelException; + + /** + * Rollback migration changes done to a composition. + * + * @param compositionElement the composition to roll back the changes + * @param instanceElement instance to roll back the changes + * @param nextStage in which stage should the instance be after the rollback + * @throws PfModelException if anything goes wrong + */ + void rollbackMigration(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/ParticipantIntermediaryApi.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ParticipantIntermediaryApi.java index c06ffe62e..e74b4607a 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 @@ -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"); @@ -38,7 +38,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; public interface ParticipantIntermediaryApi { /** - * Update the state of a AutomationComposition Instance Element. + * Update the state of an AutomationComposition Instance Element. * * @param instance the ID of the AutomationComposition Instance to update the state on * @param elementId the ID of the AutomationComposition Instance element to update the state on @@ -51,7 +51,7 @@ public interface ParticipantIntermediaryApi { LockState lockState, StateChangeResult stateChangeResult, String message); /** - * Update the stage of a AutomationComposition Instance Element. + * Update the stage of an AutomationComposition Instance Element. * * @param instance the ID of the AutomationComposition Instance to update the state on * @param elementId the ID of the AutomationComposition Instance Element to update the state on @@ -69,7 +69,7 @@ public interface ParticipantIntermediaryApi { Map getAutomationCompositions(); /** - * Get a copy of the AutomationComposition Instance by AutomationComposition Instance Id. + * Get a copy of the AutomationComposition Instance by AutomationComposition instanceId. * * @param instanceId the ID of the AutomationComposition Instance to update the state on * @return get the AutomationComposition Instance @@ -77,7 +77,7 @@ public interface ParticipantIntermediaryApi { AutomationComposition getAutomationComposition(UUID instanceId); /** - * Get a copy of the AutomationCompositionElement by AutomationComposition Instance Id and elementId. + * Get a copy of the AutomationCompositionElement by AutomationComposition instanceId and elementId. * * @param instanceId the ID of the AutomationComposition Instance to update the state on * @param elementId the ID of the AutomationComposition Instance Element to update the state on @@ -96,15 +96,15 @@ public interface ParticipantIntermediaryApi { * Get a copy of AutomationCompositionElementDefinitions of a composition. * * @param compositionId the composition id - * @return a Map by element definition Id of AutomationCompositionElementDefinitions + * @return a Map by element definition id of AutomationCompositionElementDefinitions */ Map getAcElementsDefinitions(UUID compositionId); /** - * Get a copy of the AutomationCompositionElementDefinition by compositionId and element definition Id. + * Get a copy of the AutomationCompositionElementDefinition by compositionId and element definition id. * * @param compositionId the composition id - * @param elementId the element definition Id + * @param elementId the element definition id * @return the AutomationCompositionElementDefinition */ AutomationCompositionElementDefinition getAcElementDefinition(UUID compositionId, ToscaConceptIdentifier elementId); @@ -125,13 +125,13 @@ public interface ParticipantIntermediaryApi { * Send Automation Composition Definition update Info to AC-runtime. * * @param compositionId the composition id - * @param elementId the element definition Id + * @param elementId the element definition id * @param outProperties the output Properties Map */ void sendAcDefinitionInfo(UUID compositionId, ToscaConceptIdentifier elementId, Map outProperties); /** - * Update the state of a Automation Composition Definition. + * Update the state of an Automation Composition Definition. * * @param compositionId the composition id * @param state the state of Automation Composition Definition 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 index 002b67d19..a167085b0 100644 --- 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 @@ -94,26 +94,34 @@ public abstract class AcElementListenerV4 implements AutomationCompositionElemen @Override public void migratePrecheck(CompositionElementDto compositionElement, - CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, - InstanceElementDto instanceElementMigrate) throws PfModelException { + CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, + InstanceElementDto instanceElementMigrate) throws PfModelException { intermediaryApi.updateAutomationCompositionElementState(instanceElementMigrate.instanceId(), - instanceElementMigrate.elementId(), DeployState.DEPLOYED, null, - StateChangeResult.NO_ERROR, "Migration Precheck completed"); + instanceElementMigrate.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration Precheck completed"); } @Override public void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { + throws PfModelException { intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), - instanceElement.elementId(), DeployState.DEPLOYED, null, - StateChangeResult.NO_ERROR, "Review completed"); + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Review completed"); } @Override public void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement, int nextStage) - throws PfModelException { + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.UNDEPLOYED, null, + StateChangeResult.NO_ERROR, "Prepare completed"); + } + + @Override + public void rollbackMigration(CompositionElementDto compositionElement, + InstanceElementDto instanceElement, int nextStage) { intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), - instanceElement.elementId(), DeployState.UNDEPLOYED, null, - StateChangeResult.NO_ERROR, "Prepare completed"); + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration rollback done"); } } diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.java index 8dbefe29f..a2b652120 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.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. @@ -164,6 +164,19 @@ class AcElementListenerV3Test { StateChangeResult.NO_ERROR, "Prepare completed"); } + @Test + void testRollbackMigration() { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV3 = createAcElementListenerV3(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), Map.of(), Map.of()); + acElementListenerV3.rollbackMigration(compositionElement, instanceElement, 1); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration rollback done"); + } + private AcElementListenerV3 createAcElementListenerV3(ParticipantIntermediaryApi intermediaryApi) { return new AcElementListenerV3(intermediaryApi) { @Override