diff options
19 files changed, 557 insertions, 97 deletions
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AcElementRestart.java b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AcElementRestart.java new file mode 100644 index 000000000..3815989f7 --- /dev/null +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AcElementRestart.java @@ -0,0 +1,73 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation. + * ================================================================================ + * 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.models.acm.concepts; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; +import java.util.function.UnaryOperator; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.NonNull; +import lombok.ToString; +import org.onap.policy.models.base.PfConceptKey; +import org.onap.policy.models.base.PfUtils; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; + +@NoArgsConstructor +@Data +@ToString +public class AcElementRestart { + + @NonNull + private UUID id = UUID.randomUUID(); + + @NonNull + private ToscaConceptIdentifier definition = new ToscaConceptIdentifier(PfConceptKey.getNullKey()); + + // State of the AutomationCompositionElement + private DeployState deployState; + + // State of the AutomationCompositionElement + private LockState lockState; + + private ToscaServiceTemplate toscaServiceTemplateFragment; + + // A map indexed by the property name. Each map entry is the serialized value of the property, + // which can be deserialized into an instance of the type of the property. + private Map<String, Object> properties = new LinkedHashMap<>(); + + /** + * Copy constructor, does a deep copy but as all fields here are immutable, it's just a regular copy. + * + * @param otherElement the other element to copy from + */ + public AcElementRestart(final AcElementRestart otherElement) { + this.id = otherElement.id; + this.definition = new ToscaConceptIdentifier(otherElement.definition); + this.deployState = otherElement.deployState; + this.lockState = otherElement.lockState; + this.toscaServiceTemplateFragment = otherElement.toscaServiceTemplateFragment; + this.properties = PfUtils.mapMap(otherElement.properties, UnaryOperator.identity()); + } + +} diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AcTypeState.java b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AcTypeState.java index 8e36f7a3b..76851b490 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AcTypeState.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AcTypeState.java @@ -25,6 +25,5 @@ public enum AcTypeState { COMMISSIONED, PRIMING, PRIMED, - DEPRIMING, - RESTARTING + DEPRIMING } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/ParticipantRestartAc.java b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/ParticipantRestartAc.java index b8ee0200d..e5f4ad4ae 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/ParticipantRestartAc.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/ParticipantRestartAc.java @@ -37,11 +37,7 @@ public class ParticipantRestartAc { private UUID automationCompositionId; - // current state of auto composition - private DeployState deployState; - private LockState lockState; - - private List<AcElementDeploy> acElementList = new ArrayList<>(); + private List<AcElementRestart> acElementList = new ArrayList<>(); /** * Copy constructor. @@ -50,8 +46,6 @@ public class ParticipantRestartAc { */ public ParticipantRestartAc(ParticipantRestartAc copyConstructor) { this.automationCompositionId = copyConstructor.automationCompositionId; - this.deployState = copyConstructor.deployState; - this.lockState = copyConstructor.lockState; - this.acElementList = PfUtils.mapList(copyConstructor.acElementList, AcElementDeploy::new); + this.acElementList = PfUtils.mapList(copyConstructor.acElementList, AcElementRestart::new); } } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantRestart.java b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantRestart.java index 6b801ce8d..c86a3e460 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantRestart.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantRestart.java @@ -25,6 +25,7 @@ import java.util.List; import lombok.Getter; import lombok.Setter; import lombok.ToString; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition; import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc; import org.onap.policy.models.base.PfUtils; @@ -34,11 +35,14 @@ import org.onap.policy.models.base.PfUtils; @ToString(callSuper = true) public class ParticipantRestart extends ParticipantMessage { - // priming + // composition state + AcTypeState state; + + // element definition private List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>(); - // autocomposition list - private List<ParticipantRestartAc> autocompositionList = new ArrayList<>(); + // automationcomposition instances list + private List<ParticipantRestartAc> automationcompositionList = new ArrayList<>(); /** * Constructor. @@ -56,6 +60,6 @@ public class ParticipantRestart extends ParticipantMessage { super(source); this.participantDefinitionUpdates = PfUtils.mapList(source.participantDefinitionUpdates, ParticipantDefinition::new); - this.autocompositionList = PfUtils.mapList(source.autocompositionList, ParticipantRestartAc::new); + this.automationcompositionList = PfUtils.mapList(source.automationcompositionList, ParticipantRestartAc::new); } } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java b/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java index ee8e010d2..ae49ec69f 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java @@ -36,6 +36,7 @@ import lombok.NoArgsConstructor; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.concepts.AcElementRestart; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; @@ -426,4 +427,19 @@ public final class AcmUtils { return acElementDeploy; } + /** + * Create a new AcElementRestart from an AutomationCompositionElement. + * + * @param element the AutomationCompositionElement + * @return the AcElementRestart + */ + public static AcElementRestart createAcElementRestart(AutomationCompositionElement element) { + var acElementRestart = new AcElementRestart(); + acElementRestart.setId(element.getId()); + acElementRestart.setDefinition(new ToscaConceptIdentifier(element.getDefinition())); + acElementRestart.setDeployState(element.getDeployState()); + acElementRestart.setLockState(element.getLockState()); + acElementRestart.setProperties(PfUtils.mapMap(element.getProperties(), UnaryOperator.identity())); + return acElementRestart; + } } diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantRestartTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantRestartTest.java index 1ae607ebe..ba84ac76f 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantRestartTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantRestartTest.java @@ -29,9 +29,7 @@ import java.time.Instant; import java.util.List; import java.util.UUID; import org.junit.jupiter.api.Test; -import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; -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.AcElementRestart; import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition; import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc; import org.onap.policy.clamp.models.acm.utils.CommonTestData; @@ -60,7 +58,7 @@ class ParticipantRestartTest { participantDefinitionUpdate.setAutomationCompositionElementDefinitionList(List.of(acDefinition)); orig.setParticipantDefinitionUpdates(List.of(participantDefinitionUpdate)); - var acElement = new AcElementDeploy(); + var acElement = new AcElementRestart(); acElement.setId(UUID.randomUUID()); var id = new ToscaConceptIdentifier("id", "1.2.3"); acElement.setDefinition(id); @@ -68,10 +66,8 @@ class ParticipantRestartTest { var acRestart = new ParticipantRestartAc(); acRestart.setAcElementList(List.of(acElement)); acRestart.setAutomationCompositionId(UUID.randomUUID()); - acRestart.setDeployState(DeployState.DEPLOYED); - acRestart.setLockState(LockState.LOCKED); - orig.setAutocompositionList(List.of(acRestart)); + orig.setAutomationcompositionList(List.of(acRestart)); assertEquals(removeVariableFields(orig.toString()), removeVariableFields(new ParticipantRestart(orig).toString())); diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java index 7e8f60525..a9bd25f81 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java @@ -66,6 +66,8 @@ class AcmUtilsTest { assertThat(AcmUtils.isInTransitionalState(DeployState.UNDEPLOYING, LockState.NONE)).isTrue(); assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYED, LockState.LOCKING)).isTrue(); assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYED, LockState.UNLOCKING)).isTrue(); + assertThat(AcmUtils.isInTransitionalState(DeployState.DELETING, LockState.NONE)).isTrue(); + assertThat(AcmUtils.isInTransitionalState(DeployState.UPDATING, LockState.LOCKED)).isTrue(); } @Test @@ -192,6 +194,16 @@ class AcmUtilsTest { assertEquals(element.getDefinition(), result.getDefinition()); } + @Test + void testCreateAcElementRestart() { + var element = getDummyAutomationComposition().getElements().values().iterator().next(); + var result = AcmUtils.createAcElementRestart(element); + assertEquals(element.getId(), result.getId()); + assertEquals(element.getDefinition(), result.getDefinition()); + assertEquals(element.getDeployState(), result.getDeployState()); + assertEquals(element.getLockState(), result.getLockState()); + } + private AutomationComposition getDummyAutomationComposition() { var automationComposition = new AutomationComposition(); automationComposition.setCompositionId(UUID.randomUUID()); diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java index c79e31726..961f12a5c 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java @@ -130,7 +130,7 @@ public class CommissioningProvider { var acDefinition = acDefinitionProvider.getAcDefinition(compositionId); if (!AcTypeState.COMMISSIONED.equals(acDefinition.getState())) { throw new PfModelRuntimeException(Status.BAD_REQUEST, - "ACM not in COMMISSIONED state, Update of ACM Definition not allowed"); + "ACM not in COMMISSIONED state, Delete of ACM Definition not allowed"); } var serviceTemplate = acDefinitionProvider.deleteAcDefintion(compositionId); return createCommissioningResponse(compositionId, serviceTemplate); @@ -184,6 +184,10 @@ public class CommissioningProvider { throw new PfModelRuntimeException(Status.BAD_REQUEST, "There are instances, Priming/Depriming not allowed"); } var acmDefinition = acDefinitionProvider.getAcDefinition(compositionId); + if (acmDefinition.getRestarting() != null) { + throw new PfModelRuntimeException(Status.BAD_REQUEST, + "There is a restarting process, Priming/Depriming not allowed"); + } var stateOrdered = acTypeStateResolver.resolve(acTypeStateUpdate.getPrimeOrder(), acmDefinition.getState(), acmDefinition.getStateChangeResult()); switch (stateOrdered) { @@ -220,7 +224,7 @@ public class CommissioningProvider { participantIds.add(participantId); } } - if (! participantIds.isEmpty()) { + if (!participantIds.isEmpty()) { acmParticipantProvider.verifyParticipantState(participantIds); } acmDefinition.setState(AcTypeState.DEPRIMING); 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 ab3b00d6d..710a975f0 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 @@ -155,6 +155,9 @@ public class AutomationCompositionInstantiationProvider { .putAll(automationComposition.getElements().get(elementId).getProperties()); } } + if (automationComposition.getRestarting() != null) { + throw new PfModelRuntimeException(Status.BAD_REQUEST, "There is a restarting process, Update not allowed"); + } var validationResult = validateAutomationComposition(acToBeUpdated); if (!validationResult.isValid()) { throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult()); @@ -187,10 +190,16 @@ public class AutomationCompositionInstantiationProvider { return result; } if (!AcTypeState.PRIMED.equals(acDefinitionOpt.get().getState())) { - result.addResult(new ObjectValidationResult("ServiceTemplate", acDefinitionOpt.get().getState(), + result.addResult(new ObjectValidationResult("ServiceTemplate.state", acDefinitionOpt.get().getState(), ValidationStatus.INVALID, "Commissioned automation composition definition not primed")); return result; } + if (acDefinitionOpt.get().getRestarting() != null) { + result.addResult( + new ObjectValidationResult("ServiceTemplate.restarting", acDefinitionOpt.get().getRestarting(), + ValidationStatus.INVALID, "There is a restarting process in composition")); + return result; + } var participantIds = acDefinitionOpt.get().getElementStateMap().values().stream() .map(NodeTemplateState::getParticipantId).collect(Collectors.toSet()); @@ -245,8 +254,10 @@ public class AutomationCompositionInstantiationProvider { throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, "Automation composition state is still " + automationComposition.getDeployState()); } - var acDefinition = acDefinitionProvider - .getAcDefinition(automationComposition.getCompositionId()); + if (automationComposition.getRestarting() != null) { + throw new PfModelRuntimeException(Status.BAD_REQUEST, "There is a restarting process, Delete not allowed"); + } + var acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId()); if (acDefinition != null) { var participantIds = acDefinition.getElementStateMap().values().stream() .map(NodeTemplateState::getParticipantId).collect(Collectors.toSet()); 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 536e3e246..5a2079b0d 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 @@ -22,6 +22,7 @@ package org.onap.policy.clamp.acm.runtime.supervision; import io.micrometer.core.annotation.Timed; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; import lombok.AllArgsConstructor; @@ -31,6 +32,7 @@ import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionS import org.onap.policy.clamp.models.acm.concepts.AcElementDeployAck; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils; @@ -78,8 +80,8 @@ public class SupervisionAcHandler { automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); automationCompositionProvider.updateAutomationComposition(automationComposition); var startPhase = ParticipantUtils.getFirstStartPhase(automationComposition, acDefinition.getServiceTemplate()); - automationCompositionDeployPublisher.send(automationComposition, acDefinition.getServiceTemplate(), - startPhase, true); + automationCompositionDeployPublisher.send(automationComposition, acDefinition.getServiceTemplate(), startPhase, + true); } /** @@ -261,9 +263,19 @@ public class SupervisionAcHandler { element.setUseState(acElementAck.getValue().getUseState()); element.setDeployState(acElementAck.getValue().getDeployState()); element.setLockState(acElementAck.getValue().getLockState()); + element.setRestarting(null); updated = true; } } + + if (automationComposition.getRestarting() != null) { + var restarting = automationComposition.getElements().values().stream() + .map(AutomationCompositionElement::getRestarting).filter(Objects::nonNull).findAny(); + if (restarting.isEmpty()) { + automationComposition.setRestarting(null); + } + } + return updated; } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAspect.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAspect.java index 7303fc84f..079f218ee 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAspect.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAspect.java @@ -68,13 +68,13 @@ public class SupervisionAspect implements Closeable { public void doCheck() { if (executor.getQueue().size() < 2) { LOGGER.debug("Add scanning Message"); - executor.execute(() -> supervisionScanner.run()); + executor.execute(supervisionScanner::run); } } - @Before("@annotation(MessageIntercept) && args(participantStatusMessage,..)") - public void handleParticipantStatus(ParticipantStatus participantStatusMessage) { - executor.execute(() -> partecipantScanner.handleParticipantStatus(participantStatusMessage.getParticipantId())); + @Before("@annotation(MessageIntercept) && args(participantStatusMsg,..)") + public void handleParticipantStatus(ParticipantStatus participantStatusMsg) { + executor.execute(() -> partecipantScanner.handleParticipantStatus(participantStatusMsg.getParticipantId())); } @Override diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java index a18ea19a9..4f58801c3 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java @@ -58,7 +58,7 @@ public class SupervisionHandler { } var acDefinition = acDefinitionOpt.get(); if (!AcTypeState.PRIMING.equals(acDefinition.getState()) - && !AcTypeState.DEPRIMING.equals(acDefinition.getState())) { + && !AcTypeState.DEPRIMING.equals(acDefinition.getState()) && acDefinition.getRestarting() == null) { LOGGER.error("AC Definition {} already primed/deprimed with participant {}", participantPrimeAckMessage.getCompositionId(), participantPrimeAckMessage.getParticipantId()); return; @@ -68,8 +68,8 @@ public class SupervisionHandler { private void handleParticipantPrimeAck(ParticipantPrimeAck participantPrimeAckMessage, AutomationCompositionDefinition acDefinition) { - var finalState = - AcTypeState.PRIMING.equals(acDefinition.getState()) ? AcTypeState.PRIMED : AcTypeState.COMMISSIONED; + var finalState = AcTypeState.PRIMING.equals(acDefinition.getState()) + || AcTypeState.PRIMED.equals(acDefinition.getState()) ? AcTypeState.PRIMED : AcTypeState.COMMISSIONED; var msgInErrors = StateChangeResult.FAILED.equals(participantPrimeAckMessage.getStateChangeResult()); boolean inProgress = !StateChangeResult.FAILED.equals(acDefinition.getStateChangeResult()); if (inProgress && msgInErrors) { @@ -77,14 +77,19 @@ public class SupervisionHandler { } boolean completed = true; + boolean restarting = false; for (var element : acDefinition.getElementStateMap().values()) { if (participantPrimeAckMessage.getParticipantId().equals(element.getParticipantId())) { element.setMessage(participantPrimeAckMessage.getMessage()); element.setState(participantPrimeAckMessage.getCompositionState()); + element.setRestarting(null); } if (!finalState.equals(element.getState())) { completed = false; } + if (element.getRestarting() != null) { + restarting = true; + } } if (inProgress && !msgInErrors && completed) { @@ -92,7 +97,9 @@ public class SupervisionHandler { if (StateChangeResult.TIMEOUT.equals(acDefinition.getStateChangeResult())) { acDefinition.setStateChangeResult(StateChangeResult.NO_ERROR); } - + } + if (!restarting) { + acDefinition.setRestarting(null); } acDefinitionProvider.updateAcDefinition(acDefinition); } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionPartecipantScanner.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionPartecipantScanner.java index 092fc3572..c07c584cd 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionPartecipantScanner.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionPartecipantScanner.java @@ -46,9 +46,8 @@ public class SupervisionPartecipantScanner { * @param participantProvider the Participant Provider * @param acRuntimeParameterGroup the parameters for the automation composition runtime */ - public SupervisionPartecipantScanner( - final ParticipantProvider participantProvider, - final AcRuntimeParameterGroup acRuntimeParameterGroup) { + public SupervisionPartecipantScanner(final ParticipantProvider participantProvider, + final AcRuntimeParameterGroup acRuntimeParameterGroup) { this.participantProvider = participantProvider; participantStatusTimeout.setMaxWaitMs(acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs()); @@ -70,11 +69,17 @@ public class SupervisionPartecipantScanner { private void scanParticipantStatus(Participant participant) { var id = participant.getParticipantId(); if (participantStatusTimeout.isTimeout(id)) { - LOGGER.debug("report Participant fault"); - return; + if (ParticipantState.ON_LINE.equals(participant.getParticipantState())) { + // restart scenario + LOGGER.debug("Participant is back ON_LINE {}", id); + participantStatusTimeout.clear(id); + } else { + LOGGER.debug("report Participant is still OFF_LINE {}", id); + return; + } } if (participantStatusTimeout.getDuration(id) > participantStatusTimeout.getMaxWaitMs()) { - LOGGER.debug("report Participant fault"); + LOGGER.debug("report Participant OFF_LINE {}", id); participantStatusTimeout.setTimeout(id); participant.setParticipantState(ParticipantState.OFF_LINE); participantProvider.updateParticipant(participant); @@ -85,6 +90,7 @@ public class SupervisionPartecipantScanner { * handle participant Status message. */ public void handleParticipantStatus(UUID id) { + LOGGER.debug("Participant is ON_LINE {}", id); participantStatusTimeout.clear(id); } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java index 6d438038d..e0d11ed9f 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java @@ -21,6 +21,7 @@ package org.onap.policy.clamp.acm.runtime.supervision; import io.micrometer.core.annotation.Timed; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -29,13 +30,18 @@ import lombok.AllArgsConstructor; import org.apache.commons.collections4.MapUtils; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantDeregisterAckPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantRegisterAckPublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantRestartPublisher; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; import org.onap.policy.clamp.models.acm.concepts.Participant; import org.onap.policy.clamp.models.acm.concepts.ParticipantState; import org.onap.policy.clamp.models.acm.concepts.ParticipantSupportedElementType; +import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantDeregister; -import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessage; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantRegister; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantStatus; +import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; import org.slf4j.Logger; @@ -54,6 +60,8 @@ public class SupervisionParticipantHandler { private final ParticipantRegisterAckPublisher participantRegisterAckPublisher; private final ParticipantDeregisterAckPublisher participantDeregisterAckPublisher; private final AutomationCompositionProvider automationCompositionProvider; + private final AcDefinitionProvider acDefinitionProvider; + private final ParticipantRestartPublisher participantRestartPublisher; /** * Handle a ParticipantRegister message from a participant. @@ -64,11 +72,24 @@ public class SupervisionParticipantHandler { @Timed(value = "listener.participant_register", description = "PARTICIPANT_REGISTER messages received") public void handleParticipantMessage(ParticipantRegister participantRegisterMsg) { LOGGER.debug("Participant Register received {}", participantRegisterMsg); - saveParticipantStatus(participantRegisterMsg, - listToMap(participantRegisterMsg.getParticipantSupportedElementType())); + var participantOpt = participantProvider.findParticipant(participantRegisterMsg.getParticipantId()); + + if (participantOpt.isPresent()) { + var participant = participantOpt.get(); + if (ParticipantState.OFF_LINE.equals(participant.getParticipantState())) { + participant.setParticipantState(ParticipantState.ON_LINE); + participantProvider.saveParticipant(participant); + } + handleRestart(participant.getParticipantId()); + } else { + var participant = createParticipant(participantRegisterMsg.getParticipantId(), + listToMap(participantRegisterMsg.getParticipantSupportedElementType())); + participantProvider.saveParticipant(participant); + + } participantRegisterAckPublisher.send(participantRegisterMsg.getMessageId(), - participantRegisterMsg.getParticipantId()); + participantRegisterMsg.getParticipantId()); } /** @@ -100,30 +121,81 @@ public class SupervisionParticipantHandler { @Timed(value = "listener.participant_status", description = "PARTICIPANT_STATUS messages received") public void handleParticipantMessage(ParticipantStatus participantStatusMsg) { LOGGER.debug("Participant Status received {}", participantStatusMsg); - saveParticipantStatus(participantStatusMsg, - listToMap(participantStatusMsg.getParticipantSupportedElementType())); + + var participantOpt = participantProvider.findParticipant(participantStatusMsg.getParticipantId()); + if (participantOpt.isEmpty()) { + var participant = createParticipant(participantStatusMsg.getParticipantId(), + listToMap(participantStatusMsg.getParticipantSupportedElementType())); + participantProvider.saveParticipant(participant); + } if (!participantStatusMsg.getAutomationCompositionInfoList().isEmpty()) { automationCompositionProvider.upgradeStates(participantStatusMsg.getAutomationCompositionInfoList()); } } - private void saveParticipantStatus(ParticipantMessage participantMessage, - Map<UUID, ParticipantSupportedElementType> participantSupportedElementType) { - var participantOpt = participantProvider.findParticipant(participantMessage.getParticipantId()); - - if (participantOpt.isEmpty()) { - var participant = new Participant(); - participant.setParticipantId(participantMessage.getParticipantId()); - participant.setParticipantSupportedElementTypes(participantSupportedElementType); - participant.setParticipantState(ParticipantState.ON_LINE); + private void handleRestart(UUID participantId) { + var compositionIds = participantProvider.getCompositionIds(participantId); + for (var compositionId : compositionIds) { + var acDefinition = acDefinitionProvider.getAcDefinition(compositionId); + LOGGER.debug("Scan Composition {} for restart", acDefinition.getCompositionId()); + handleRestart(participantId, acDefinition); + } + } - participantProvider.saveParticipant(participant); - } else { - var participant = participantOpt.get(); - participant.setParticipantState(ParticipantState.ON_LINE); + private void handleRestart(UUID participantId, AutomationCompositionDefinition acDefinition) { + if (AcTypeState.COMMISSIONED.equals(acDefinition.getState())) { + LOGGER.debug("Composition {} COMMISSIONED", acDefinition.getCompositionId()); + return; + } + LOGGER.debug("Composition to be send in Restart message {}", acDefinition.getCompositionId()); + for (var elementState : acDefinition.getElementStateMap().values()) { + if (participantId.equals(elementState.getParticipantId())) { + elementState.setRestarting(true); + } + } + var automationCompositionList = + automationCompositionProvider.getAcInstancesByCompositionId(acDefinition.getCompositionId()); + List<AutomationComposition> automationCompositions = new ArrayList<>(); + for (var automationComposition : automationCompositionList) { + if (isAcToBeRestarted(participantId, automationComposition)) { + automationCompositions.add(automationComposition); + } + } + // expected final state + if (StateChangeResult.TIMEOUT.equals(acDefinition.getStateChangeResult())) { + acDefinition.setStateChangeResult(StateChangeResult.NO_ERROR); + } + acDefinition.setRestarting(true); + acDefinitionProvider.updateAcDefinition(acDefinition); + participantRestartPublisher.send(participantId, acDefinition, automationCompositions); + } - participantProvider.updateParticipant(participant); + private boolean isAcToBeRestarted(UUID participantId, AutomationComposition automationComposition) { + boolean toAdd = false; + for (var element : automationComposition.getElements().values()) { + if (participantId.equals(element.getParticipantId())) { + element.setRestarting(true); + toAdd = true; + } + } + if (toAdd) { + automationComposition.setRestarting(true); + // expected final state + if (StateChangeResult.TIMEOUT.equals(automationComposition.getStateChangeResult())) { + automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); + } + automationCompositionProvider.updateAutomationComposition(automationComposition); } + return toAdd; + } + + private Participant createParticipant(UUID participantId, + Map<UUID, ParticipantSupportedElementType> participantSupportedElementType) { + var participant = new Participant(); + participant.setParticipantId(participantId); + participant.setParticipantSupportedElementTypes(participantSupportedElementType); + participant.setParticipantState(ParticipantState.ON_LINE); + return participant; } private Map<UUID, ParticipantSupportedElementType> listToMap(List<ParticipantSupportedElementType> elementList) { diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantRestartPublisher.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantRestartPublisher.java index cb00c8e4d..b086b1914 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantRestartPublisher.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantRestartPublisher.java @@ -34,7 +34,6 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition; import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantRestart; -import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; @@ -51,6 +50,9 @@ public class ParticipantRestartPublisher extends AbstractParticipantPublisher<Pa /** * Send Restart to Participant. * + * @param participantId the ParticipantId + * @param acmDefinition the AutomationComposition Definition + * @param automationCompositions the list of automationCompositions */ @Timed(value = "publisher.participant_restart", description = "Participant Restart published") public void send(UUID participantId, AutomationCompositionDefinition acmDefinition, @@ -61,21 +63,21 @@ public class ParticipantRestartPublisher extends AbstractParticipantPublisher<Pa message.setCompositionId(acmDefinition.getCompositionId()); message.setMessageId(UUID.randomUUID()); message.setTimestamp(Instant.now()); + message.setState(acmDefinition.getState()); message.setParticipantDefinitionUpdates(prepareParticipantRestarting(participantId, acmDefinition)); + var toscaServiceTemplateFragment = AcmUtils.getToscaServiceTemplateFragment(acmDefinition.getServiceTemplate()); for (var automationComposition : automationCompositions) { var restartAc = new ParticipantRestartAc(); restartAc.setAutomationCompositionId(automationComposition.getInstanceId()); - restartAc.setDeployState(automationComposition.getDeployState()); - restartAc.setLockState(automationComposition.getLockState()); for (var element : automationComposition.getElements().values()) { if (participantId.equals(element.getParticipantId())) { - var acElementDeploy = AcmUtils.createAcElementDeploy(element, DeployOrder.RESTARTING); - acElementDeploy.setToscaServiceTemplateFragment(acmDefinition.getServiceTemplate()); - restartAc.getAcElementList().add(acElementDeploy); + var acElementRestart = AcmUtils.createAcElementRestart(element); + acElementRestart.setToscaServiceTemplateFragment(toscaServiceTemplateFragment); + restartAc.getAcElementList().add(acElementRestart); } } - message.getAutocompositionList().add(restartAc); + message.getAutomationcompositionList().add(restartAc); } LOGGER.debug("Participant Restart sent {}", message); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java index 08d20bacc..d7c79bc3b 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java @@ -188,4 +188,57 @@ class CommissioningProviderTest { provider.compositionDefinitionPriming(compositionId, acTypeStateUpdate); verify(participantPrimePublisher, timeout(1000).times(1)).sendDepriming(compositionId); } + + @Test + void testBadRequest() { + var acProvider = mock(AutomationCompositionProvider.class); + var provider = new CommissioningProvider(mock(AcDefinitionProvider.class), acProvider, + mock(AcmParticipantProvider.class), new AcTypeStateResolver(), mock(ParticipantPrimePublisher.class)); + + var compositionId = UUID.randomUUID(); + when(acProvider.getAcInstancesByCompositionId(compositionId)).thenReturn(List.of(new AutomationComposition())); + + var toscaServiceTemplate = new ToscaServiceTemplate(); + assertThatThrownBy(() -> provider.updateCompositionDefinition(compositionId, toscaServiceTemplate)) + .hasMessageMatching("There are ACM instances, Update of ACM Definition not allowed"); + + var acTypeStateUpdate = new AcTypeStateUpdate(); + assertThatThrownBy(() -> provider.compositionDefinitionPriming(compositionId, acTypeStateUpdate)) + .hasMessageMatching("There are instances, Priming/Depriming not allowed"); + } + + @Test + void testPrimedBadRequest() { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var toscaServiceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + var acmDefinition = CommonTestData.createAcDefinition(toscaServiceTemplate, AcTypeState.PRIMED); + var compositionId = acmDefinition.getCompositionId(); + when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acmDefinition); + + var provider = new CommissioningProvider(acDefinitionProvider, mock(AutomationCompositionProvider.class), + mock(AcmParticipantProvider.class), new AcTypeStateResolver(), mock(ParticipantPrimePublisher.class)); + + assertThatThrownBy(() -> provider.updateCompositionDefinition(compositionId, toscaServiceTemplate)) + .hasMessageMatching("ACM not in COMMISSIONED state, Update of ACM Definition not allowed"); + + assertThatThrownBy(() -> provider.deleteAutomationCompositionDefinition(compositionId)) + .hasMessageMatching("ACM not in COMMISSIONED state, Delete of ACM Definition not allowed"); + } + + @Test + void testPrimingBadRequest() { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var toscaServiceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + var acmDefinition = CommonTestData.createAcDefinition(toscaServiceTemplate, AcTypeState.PRIMED); + acmDefinition.setRestarting(true); + var compositionId = acmDefinition.getCompositionId(); + when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acmDefinition); + + var provider = new CommissioningProvider(acDefinitionProvider, mock(AutomationCompositionProvider.class), + mock(AcmParticipantProvider.class), new AcTypeStateResolver(), mock(ParticipantPrimePublisher.class)); + + var acTypeStateUpdate = new AcTypeStateUpdate(); + assertThatThrownBy(() -> provider.compositionDefinitionPriming(compositionId, acTypeStateUpdate)) + .hasMessageMatching("There is a restarting process, Priming/Depriming not allowed"); + } } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java index 13da979c8..3ac2efc1a 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java @@ -145,6 +145,115 @@ class AutomationCompositionInstantiationProviderTest { } @Test + void testInstantiationUpdate() throws AutomationCompositionException { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + var compositionId = acDefinition.getCompositionId(); + when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(acDefinition)); + + var automationCompositionUpdate = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); + automationCompositionUpdate.setCompositionId(compositionId); + automationCompositionUpdate.setDeployState(DeployState.DEPLOYED); + automationCompositionUpdate.setLockState(LockState.LOCKED); + var acProvider = mock(AutomationCompositionProvider.class); + when(acProvider.getAutomationComposition(automationCompositionUpdate.getInstanceId())) + .thenReturn(automationCompositionUpdate); + when(acProvider.updateAutomationComposition(automationCompositionUpdate)) + .thenReturn(automationCompositionUpdate); + + var supervisionAcHandler = mock(SupervisionAcHandler.class); + var acmParticipantProvider = mock(AcmParticipantProvider.class); + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, + null, supervisionAcHandler, acmParticipantProvider); + var instantiationResponse = instantiationProvider.updateAutomationComposition( + automationCompositionUpdate.getCompositionId(), automationCompositionUpdate); + + verify(supervisionAcHandler).update(any()); + verify(acProvider).updateAutomationComposition(automationCompositionUpdate); + InstantiationUtils.assertInstantiationResponse(instantiationResponse, automationCompositionUpdate); + } + + @Test + void testUpdateBadRequest() throws AutomationCompositionException { + var automationCompositionUpdate = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); + automationCompositionUpdate.setDeployState(DeployState.DEPLOYING); + automationCompositionUpdate.setLockState(LockState.NONE); + var acProvider = mock(AutomationCompositionProvider.class); + when(acProvider.getAutomationComposition(automationCompositionUpdate.getInstanceId())) + .thenReturn(automationCompositionUpdate); + + var instantiationProvider = + new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class), null, + mock(SupervisionAcHandler.class), mock(AcmParticipantProvider.class)); + + var compositionId = automationCompositionUpdate.getCompositionId(); + assertThatThrownBy( + () -> instantiationProvider.updateAutomationComposition(compositionId, automationCompositionUpdate)) + .hasMessageMatching( + "Not allowed to update in the state " + automationCompositionUpdate.getDeployState()); + } + + @Test + void testUpdateRestartedBadRequest() throws AutomationCompositionException { + var automationCompositionUpdate = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); + automationCompositionUpdate.setDeployState(DeployState.DEPLOYED); + automationCompositionUpdate.setLockState(LockState.LOCKED); + automationCompositionUpdate.setRestarting(true); + var acProvider = mock(AutomationCompositionProvider.class); + when(acProvider.getAutomationComposition(automationCompositionUpdate.getInstanceId())) + .thenReturn(automationCompositionUpdate); + + var instantiationProvider = + new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class), null, + mock(SupervisionAcHandler.class), mock(AcmParticipantProvider.class)); + + var compositionId = automationCompositionUpdate.getCompositionId(); + assertThatThrownBy( + () -> instantiationProvider.updateAutomationComposition(compositionId, automationCompositionUpdate)) + .hasMessageMatching("There is a restarting process, Update not allowed"); + + automationCompositionUpdate.setDeployState(DeployState.UNDEPLOYED); + automationCompositionUpdate.setLockState(LockState.NONE); + + var instanceId = automationCompositionUpdate.getInstanceId(); + assertThatThrownBy(() -> instantiationProvider.deleteAutomationComposition(compositionId, instanceId)) + .hasMessageMatching("There is a restarting process, Delete not allowed"); + } + + @Test + void testUpdateCompositionRestartedBadRequest() throws AutomationCompositionException { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + acDefinition.setRestarting(true); + var compositionId = acDefinition.getCompositionId(); + when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(acDefinition)); + + var automationCompositionUpdate = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); + automationCompositionUpdate.setCompositionId(compositionId); + automationCompositionUpdate.setDeployState(DeployState.DEPLOYED); + automationCompositionUpdate.setLockState(LockState.LOCKED); + var acProvider = mock(AutomationCompositionProvider.class); + when(acProvider.getAutomationComposition(automationCompositionUpdate.getInstanceId())) + .thenReturn(automationCompositionUpdate); + when(acProvider.updateAutomationComposition(automationCompositionUpdate)) + .thenReturn(automationCompositionUpdate); + + var supervisionAcHandler = mock(SupervisionAcHandler.class); + var acmParticipantProvider = mock(AcmParticipantProvider.class); + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, + null, supervisionAcHandler, acmParticipantProvider); + assertThatThrownBy( + () -> instantiationProvider.updateAutomationComposition(compositionId, automationCompositionUpdate)) + .hasMessageMatching("\"AutomationComposition\" INVALID, item has status INVALID\n" + + " item \"ServiceTemplate.restarting\" value \"true\" INVALID," + + " There is a restarting process in composition\n"); + } + + @Test void testInstantiationDelete() { var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Delete"); @@ -154,8 +263,8 @@ class AutomationCompositionInstantiationProviderTest { var supervisionAcHandler = mock(SupervisionAcHandler.class); var acmParticipantProvider = mock(AcmParticipantProvider.class); - var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, - acDefinitionProvider, null, supervisionAcHandler, acmParticipantProvider); + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, + null, supervisionAcHandler, acmParticipantProvider); when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) .thenReturn(automationComposition); @@ -178,15 +287,15 @@ class AutomationCompositionInstantiationProviderTest { verify(supervisionAcHandler).delete(any(), any()); } - private void assertThatDeleteThrownBy(AutomationComposition automationComposition, - DeployState deployState, LockState lockState) { + private void assertThatDeleteThrownBy(AutomationComposition automationComposition, DeployState deployState, + LockState lockState) { automationComposition.setDeployState(deployState); automationComposition.setLockState(lockState); var acProvider = mock(AutomationCompositionProvider.class); var acDefinitionProvider = mock(AcDefinitionProvider.class); - var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, - acDefinitionProvider, null, null, null); + var instantiationProvider = + new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, null, null, null); when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) .thenReturn(automationComposition); @@ -214,8 +323,8 @@ class AutomationCompositionInstantiationProviderTest { .thenReturn(automationCompositionCreate); var acmParticipantProvider = mock(AcmParticipantProvider.class); - var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, - acDefinitionProvider, null, null, acmParticipantProvider); + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, + null, null, acmParticipantProvider); var instantiationResponse = instantiationProvider.createAutomationComposition( automationCompositionCreate.getCompositionId(), automationCompositionCreate); @@ -241,8 +350,8 @@ class AutomationCompositionInstantiationProviderTest { automationComposition.setCompositionId(compositionId); var acProvider = mock(AutomationCompositionProvider.class); - var provider = new AutomationCompositionInstantiationProvider(acProvider, - acDefinitionProvider, null, null, acmParticipantProvider); + var provider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, null, null, + acmParticipantProvider); assertThatThrownBy(() -> provider.createAutomationComposition(compositionId, automationComposition)) .hasMessageMatching(AC_ELEMENT_NAME_NOT_FOUND); @@ -262,8 +371,8 @@ class AutomationCompositionInstantiationProviderTest { var acProvider = mock(AutomationCompositionProvider.class); when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) .thenReturn(automationComposition); - var provider = new AutomationCompositionInstantiationProvider(acProvider, - mock(AcDefinitionProvider.class), null, null, null); + var provider = new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class), + null, null, null); var compositionId = automationComposition.getCompositionId(); assertThatThrownBy(() -> provider.createAutomationComposition(compositionId, automationComposition)) @@ -281,8 +390,8 @@ class AutomationCompositionInstantiationProviderTest { var acProvider = mock(AutomationCompositionProvider.class); when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) .thenReturn(automationComposition); - var provider = new AutomationCompositionInstantiationProvider(acProvider, - mock(AcDefinitionProvider.class), null, null, null); + var provider = new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class), + null, null, null); var compositionId = automationComposition.getCompositionId(); var wrongCompositionId = UUID.randomUUID(); @@ -315,7 +424,7 @@ class AutomationCompositionInstantiationProviderTest { automationComposition.setCompositionId(compositionId); assertThatThrownBy(() -> provider.createAutomationComposition(compositionId, automationComposition)) .hasMessageMatching("\"AutomationComposition\" INVALID, item has status INVALID\n" - + " item \"ServiceTemplate\" value \"COMMISSIONED\" INVALID," + + " item \"ServiceTemplate.state\" value \"COMMISSIONED\" INVALID," + " Commissioned automation composition definition not primed\n"); } @@ -332,8 +441,7 @@ class AutomationCompositionInstantiationProviderTest { automationComposition.setCompositionId(compositionId); automationComposition.setInstanceId(instanceId); var acProvider = mock(AutomationCompositionProvider.class); - when(acProvider.getAutomationComposition(instanceId)) - .thenReturn(automationComposition); + when(acProvider.getAutomationComposition(instanceId)).thenReturn(automationComposition); var supervisionAcHandler = mock(SupervisionAcHandler.class); var acmParticipantProvider = mock(AcmParticipantProvider.class); @@ -367,7 +475,6 @@ class AutomationCompositionInstantiationProviderTest { acInstanceStateUpdate.setDeployOrder(DeployOrder.NONE); acInstanceStateUpdate.setLockOrder(LockOrder.LOCK); provider.compositionInstanceState(compositionId, instanceId, acInstanceStateUpdate); - verify(supervisionAcHandler).lock(any(AutomationComposition.class), - any(AutomationCompositionDefinition.class)); + verify(supervisionAcHandler).lock(any(AutomationComposition.class), any(AutomationCompositionDefinition.class)); } } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java index e441befb2..ed8a85664 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java @@ -26,22 +26,34 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; 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.supervision.comm.ParticipantDeregisterAckPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantRegisterAckPublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantRestartPublisher; import org.onap.policy.clamp.acm.runtime.util.CommonTestData; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionInfo; +import org.onap.policy.clamp.models.acm.concepts.NodeTemplateState; +import org.onap.policy.clamp.models.acm.concepts.Participant; import org.onap.policy.clamp.models.acm.concepts.ParticipantState; import org.onap.policy.clamp.models.acm.concepts.ParticipantSupportedElementType; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantDeregister; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantRegister; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantStatus; +import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; class SupervisionParticipantHandlerTest { + + private static final String AC_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/acm/AutomationComposition.json"; + @Test void testHandleParticipantDeregister() { var participant = CommonTestData.createParticipant(CommonTestData.getParticipantId()); @@ -54,9 +66,10 @@ class SupervisionParticipantHandlerTest { participantDeregisterMessage.setMessageId(UUID.randomUUID()); participantDeregisterMessage.setParticipantId(CommonTestData.getParticipantId()); var participantDeregisterAckPublisher = mock(ParticipantDeregisterAckPublisher.class); - var handler = new SupervisionParticipantHandler(participantProvider, - mock(ParticipantRegisterAckPublisher.class), participantDeregisterAckPublisher, - mock(AutomationCompositionProvider.class)); + var handler = + new SupervisionParticipantHandler(participantProvider, mock(ParticipantRegisterAckPublisher.class), + participantDeregisterAckPublisher, mock(AutomationCompositionProvider.class), + mock(AcDefinitionProvider.class), mock(ParticipantRestartPublisher.class)); handler.handleParticipantMessage(participantDeregisterMessage); @@ -77,8 +90,8 @@ class SupervisionParticipantHandlerTest { var participantProvider = mock(ParticipantProvider.class); var participantRegisterAckPublisher = mock(ParticipantRegisterAckPublisher.class); var handler = new SupervisionParticipantHandler(participantProvider, participantRegisterAckPublisher, - mock(ParticipantDeregisterAckPublisher.class), - mock(AutomationCompositionProvider.class)); + mock(ParticipantDeregisterAckPublisher.class), mock(AutomationCompositionProvider.class), + mock(AcDefinitionProvider.class), mock(ParticipantRestartPublisher.class)); handler.handleParticipantMessage(participantRegisterMessage); verify(participantProvider).saveParticipant(any()); @@ -87,6 +100,58 @@ class SupervisionParticipantHandlerTest { } @Test + void testHandleParticipantRestart() { + var participantRegisterMessage = new ParticipantRegister(); + participantRegisterMessage.setMessageId(UUID.randomUUID()); + var participantId = CommonTestData.getParticipantId(); + participantRegisterMessage.setParticipantId(participantId); + var supportedElementType = new ParticipantSupportedElementType(); + supportedElementType.setTypeName("Type"); + supportedElementType.setTypeVersion("1.0.0"); + participantRegisterMessage.setParticipantSupportedElementType(List.of(supportedElementType)); + + var participant = new Participant(); + participant.setParticipantId(participantId); + var participantProvider = mock(ParticipantProvider.class); + when(participantProvider.findParticipant(participantId)).thenReturn(Optional.of(participant)); + var compositionId = UUID.randomUUID(); + var composition2Id = UUID.randomUUID(); + when(participantProvider.getCompositionIds(participantId)).thenReturn(Set.of(compositionId, composition2Id)); + + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var acDefinition = new AutomationCompositionDefinition(); + acDefinition.setState(AcTypeState.COMMISSIONED); + acDefinition.setCompositionId(composition2Id); + when(acDefinitionProvider.getAcDefinition(composition2Id)).thenReturn(acDefinition); + + acDefinition = new AutomationCompositionDefinition(); + acDefinition.setCompositionId(compositionId); + acDefinition.setState(AcTypeState.PRIMED); + var nodeTemplateState = new NodeTemplateState(); + nodeTemplateState.setParticipantId(participantId); + acDefinition.setElementStateMap(Map.of("code", nodeTemplateState)); + when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acDefinition); + + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); + automationComposition.getElements().values().iterator().next().setParticipantId(participantId); + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId)) + .thenReturn(List.of(automationComposition)); + + var participantRegisterAckPublisher = mock(ParticipantRegisterAckPublisher.class); + var participantRestartPublisher = mock(ParticipantRestartPublisher.class); + var handler = new SupervisionParticipantHandler(participantProvider, participantRegisterAckPublisher, + mock(ParticipantDeregisterAckPublisher.class), automationCompositionProvider, acDefinitionProvider, + participantRestartPublisher); + handler.handleParticipantMessage(participantRegisterMessage); + + verify(participantRegisterAckPublisher).send(participantRegisterMessage.getMessageId(), participantId); + verify(acDefinitionProvider).updateAcDefinition(any(AutomationCompositionDefinition.class)); + verify(participantRestartPublisher).send(any(), any(AutomationCompositionDefinition.class), any()); + } + + @Test void testHandleParticipantStatus() { var participantStatusMessage = new ParticipantStatus(); participantStatusMessage.setParticipantId(CommonTestData.getParticipantId()); @@ -98,14 +163,16 @@ class SupervisionParticipantHandlerTest { participantStatusMessage.setAutomationCompositionInfoList(List.of(new AutomationCompositionInfo())); var participantProvider = mock(ParticipantProvider.class); - var handler = new SupervisionParticipantHandler(participantProvider, - mock(ParticipantRegisterAckPublisher.class), mock(ParticipantDeregisterAckPublisher.class), - mock(AutomationCompositionProvider.class)); + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var handler = + new SupervisionParticipantHandler(participantProvider, mock(ParticipantRegisterAckPublisher.class), + mock(ParticipantDeregisterAckPublisher.class), automationCompositionProvider, + mock(AcDefinitionProvider.class), mock(ParticipantRestartPublisher.class)); var participant = CommonTestData.createParticipant(CommonTestData.getParticipantId()); when(participantProvider.findParticipant(CommonTestData.getParticipantId())) .thenReturn(Optional.of(participant)); handler.handleParticipantMessage(participantStatusMessage); - verify(participantProvider).updateParticipant(any()); + verify(automationCompositionProvider).upgradeStates(any()); } } 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 8de5ccabe..06684d863 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 @@ -222,6 +222,31 @@ class SupervisionMessagesTest { } @Test + void testParticipantRestartPublisher() { + var publisher = new ParticipantRestartPublisher(); + var topicSink = mock(TopicSink.class); + publisher.active(List.of(topicSink)); + + var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + // serviceTemplate.setName("Name"); + // serviceTemplate.setVersion("1.0.0"); + var acmDefinition = new AutomationCompositionDefinition(); + acmDefinition.setCompositionId(UUID.randomUUID()); + acmDefinition.setServiceTemplate(serviceTemplate); + var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate); + acmDefinition.setElementStateMap(AcmUtils.createElementStateMap(acElements, AcTypeState.PRIMED)); + + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); + + var participantId = automationComposition.getElements().values().iterator().next().getParticipantId(); + acmDefinition.getElementStateMap().values().iterator().next().setParticipantId(participantId); + + publisher.send(participantId, acmDefinition, List.of(automationComposition)); + verify(topicSink).send(anyString()); + } + + @Test void testParticipantRegisterListener() { final var participantRegister = new ParticipantRegister(); var supervisionHandler = mock(SupervisionParticipantHandler.class); |