/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2023 Nordix Foundation.
+ * Copyright (C) 2022-2024 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
private StateChangeResult stateChangeResult;
+ @NonNull
+ private String lastMsg;
+
@NonNull
// Map used to store prime state with key as NodeTemplate Name and value as NodeTemplateState
private Map<String, NodeTemplateState> elementStateMap = new HashMap<>();
this.serviceTemplate = new ToscaServiceTemplate(otherAcmDefinition.serviceTemplate);
this.restarting = otherAcmDefinition.restarting;
this.state = otherAcmDefinition.state;
+ this.lastMsg = otherAcmDefinition.lastMsg;
this.elementStateMap = PfUtils.mapMap(otherAcmDefinition.elementStateMap, NodeTemplateState::new);
this.stateChangeResult = otherAcmDefinition.stateChangeResult;
}
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2023 Nordix Foundation.
+ * Copyright (C) 2022-2024 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import jakarta.persistence.Lob;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
+import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
-import org.onap.policy.clamp.models.acm.document.base.ToscaServiceTemplateValidation;
import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
import org.onap.policy.common.parameters.BeanValidationResult;
import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.common.parameters.annotations.Pattern;
@Column
private StateChangeResult stateChangeResult;
+ @Column
+ @NotNull
+ private Timestamp lastMsg;
+
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "compositionId", foreignKey = @ForeignKey(name = "dt_element_fk"))
private Set<JpaNodeTemplateState> elements = new HashSet<>();
acmDefinition.setRestarting(this.restarting);
acmDefinition.setState(this.state);
acmDefinition.setStateChangeResult(this.stateChangeResult);
+ acmDefinition.setLastMsg(this.lastMsg.toString());
acmDefinition.setServiceTemplate(this.serviceTemplate.toAuthorative());
for (var element : this.elements) {
var key = element.getNodeTemplateId().getName();
this.restarting = copyConcept.getRestarting();
this.state = copyConcept.getState();
this.stateChangeResult = copyConcept.getStateChangeResult();
+ this.lastMsg = TimestampHelper.toTimestamp(copyConcept.getLastMsg());
this.serviceTemplate = new DocToscaServiceTemplate(copyConcept.getServiceTemplate());
setName(this.serviceTemplate.getName());
setVersion(this.serviceTemplate.getVersion());
import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionDefinitionRepository;
import org.onap.policy.clamp.models.acm.persistence.repository.NodeTemplateStateRepository;
import org.onap.policy.clamp.models.acm.utils.AcmUtils;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
import org.onap.policy.common.parameters.BeanValidationResult;
import org.onap.policy.models.base.PfModelRuntimeException;
import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
if (serviceTemplate.getMetadata() == null) {
serviceTemplate.setMetadata(new HashMap<>());
}
+ acmDefinition.setLastMsg(TimestampHelper.now());
serviceTemplate.getMetadata().put("compositionId", compositionId);
acmDefinition.setServiceTemplate(serviceTemplate);
var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate, toscaElementName);
var acmDefinition = new AutomationCompositionDefinition();
acmDefinition.setCompositionId(compositionId);
acmDefinition.setState(AcTypeState.COMMISSIONED);
+ acmDefinition.setLastMsg(TimestampHelper.now());
acmDefinition.setServiceTemplate(serviceTemplate);
var acElements =
AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate, toscaElementName);
import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionDefinitionRepository;
import org.onap.policy.clamp.models.acm.persistence.repository.NodeTemplateStateRepository;
import org.onap.policy.clamp.models.acm.utils.CommonTestData;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate;
import org.springframework.data.domain.Example;
class AcDefinitionProviderTest {
private static ToscaServiceTemplate inputServiceTemplate;
+ @Test
+ void testBadRequest() {
+ var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
+ var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
+
+ var compositionId = UUID.randomUUID();
+ var serviceTemplate = new ToscaServiceTemplate();
+ serviceTemplate.setToscaTopologyTemplate(new ToscaTopologyTemplate());
+ serviceTemplate.getToscaTopologyTemplate().setNodeTemplates(new HashMap<>());
+ assertThatThrownBy(() -> acDefinitionProvider.updateServiceTemplate(compositionId, serviceTemplate,
+ "ElementName", "CompositionName"))
+ .hasMessageMatching("NodeTemplate with element type ElementName must exist!");
+
+ var docServiceTemplate = new DocToscaServiceTemplate(inputServiceTemplate);
+ var acmDefinition = getAcDefinition(docServiceTemplate);
+ assertThatThrownBy(() -> acDefinitionProvider.updateAcDefinition(acmDefinition, "CompositionName"))
+ .hasMessageStartingWith("\"AutomationCompositionDefinition\" INVALID, item has status INVALID");
+
+ assertThatThrownBy(() -> acDefinitionProvider.updateAcDefinitionState(compositionId, AcTypeState.PRIMED,
+ StateChangeResult.NO_ERROR, false))
+ .hasMessageStartingWith("update of Automation Composition Definition");
+ }
+
@BeforeAll
static void loadServiceTemplate() {
inputServiceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
var acmDefinition = new AutomationCompositionDefinition();
acmDefinition.setCompositionId(UUID.randomUUID());
acmDefinition.setState(AcTypeState.COMMISSIONED);
+ acmDefinition.setLastMsg(TimestampHelper.now());
acmDefinition.setServiceTemplate(docServiceTemplate.toAuthorative());
var nodeTemplateState = new NodeTemplateState();
nodeTemplateState.setNodeTemplateStateId(UUID.randomUUID());
import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
import org.onap.policy.clamp.models.acm.persistence.provider.AcTypeStateResolver;
import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
import org.onap.policy.models.base.PfModelRuntimeException;
import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplates;
}
private void prime(AutomationCompositionDefinition acmDefinition) {
- acmDefinition.setStateChangeResult(StateChangeResult.NO_ERROR);
var preparation = participantPrimePublisher.prepareParticipantPriming(acmDefinition);
acDefinitionProvider.updateAcDefinition(acmDefinition,
acRuntimeParameterGroup.getAcmParameters().getToscaCompositionName());
acmParticipantProvider.verifyParticipantState(participantIds);
}
acmDefinition.setState(AcTypeState.DEPRIMING);
+ acmDefinition.setLastMsg(TimestampHelper.now());
acDefinitionProvider.updateAcDefinition(acmDefinition,
acRuntimeParameterGroup.getAcmParameters().getToscaCompositionName());
package org.onap.policy.clamp.acm.runtime.supervision;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
-import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
import org.onap.policy.clamp.models.acm.utils.AcmUtils;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final TimeoutHandler<UUID> acTimeout = new TimeoutHandler<>();
private final Map<UUID, Integer> phaseMap = new HashMap<>();
+ private final long maxStatusWaitMs;
+
private final AutomationCompositionProvider automationCompositionProvider;
private final AcDefinitionProvider acDefinitionProvider;
private final AutomationCompositionStateChangePublisher automationCompositionStateChangePublisher;
this.automationCompositionDeployPublisher = automationCompositionDeployPublisher;
acTimeout.setMaxWaitMs(acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs());
+ this.maxStatusWaitMs = acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs();
}
/**
for (var acDefinition : acDefinitionList) {
scanAutomationCompositionDefinition(acDefinition);
}
- Set<UUID> set = new HashSet<>();
- set.addAll(acDefinitionList
- .stream().map(AutomationCompositionDefinition::getCompositionId).collect(Collectors.toSet()));
var acList = automationCompositionProvider.getAcInstancesInTransition();
HashMap<UUID, AutomationCompositionDefinition> acDefinitionMap = new HashMap<>();
}
scanAutomationComposition(automationComposition, acDefinition.getServiceTemplate());
}
- set.addAll(
- acList.stream().map(AutomationComposition::getInstanceId).collect(Collectors.toSet()));
+ var set = acList.stream().map(AutomationComposition::getInstanceId).collect(Collectors.toSet());
acTimeout.removeIfNotPresent(set);
LOGGER.debug("Automation composition scan complete . . .");
private void scanAutomationCompositionDefinition(AutomationCompositionDefinition acDefinition) {
if (StateChangeResult.FAILED.equals(acDefinition.getStateChangeResult())) {
LOGGER.debug("automation definition {} scanned, OK", acDefinition.getCompositionId());
-
- // Clear Timeout on ac Definition
- acTimeout.remove(acDefinition.getCompositionId());
return;
}
- if (acTimeout.isTimeout(acDefinition.getCompositionId())
- && StateChangeResult.NO_ERROR.equals(acDefinition.getStateChangeResult())) {
- // retry by the user
- LOGGER.debug("clearing Timeout for the ac definition");
- acTimeout.clear(acDefinition.getCompositionId());
- }
-
boolean completed = true;
var finalState = AcTypeState.PRIMING.equals(acDefinition.getState())
|| AcTypeState.PRIMED.equals(acDefinition.getState()) ? AcTypeState.PRIMED : AcTypeState.COMMISSIONED;
if (completed) {
acDefinitionProvider.updateAcDefinitionState(acDefinition.getCompositionId(), finalState,
StateChangeResult.NO_ERROR, null);
- acTimeout.remove(acDefinition.getCompositionId());
} else {
handleTimeout(acDefinition);
}
}
private void handleTimeout(AutomationCompositionDefinition acDefinition) {
- var compositionId = acDefinition.getCompositionId();
- if (acTimeout.isTimeout(compositionId)) {
+ if (StateChangeResult.TIMEOUT.equals(acDefinition.getStateChangeResult())) {
LOGGER.debug("The ac definition is in timeout {}", acDefinition.getCompositionId());
return;
}
-
- if (acTimeout.getDuration(compositionId) > acTimeout.getMaxWaitMs()) {
+ var now = TimestampHelper.nowEpochMilli();
+ var lastMsg = TimestampHelper.toEpochMilli(acDefinition.getLastMsg());
+ if ((now - lastMsg) > maxStatusWaitMs) {
LOGGER.debug("Report timeout for the ac definition {}", acDefinition.getCompositionId());
- acTimeout.setTimeout(compositionId);
acDefinition.setStateChangeResult(StateChangeResult.TIMEOUT);
acDefinitionProvider.updateAcDefinitionState(acDefinition.getCompositionId(),
acDefinition.getState(), acDefinition.getStateChangeResult(), acDefinition.getRestarting());
import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition;
+import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrime;
import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
import org.onap.policy.clamp.models.acm.utils.AcmUtils;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @return list of ParticipantDefinition
*/
public List<ParticipantDefinition> prepareParticipantPriming(AutomationCompositionDefinition acmDefinition) {
+ acmDefinition.setStateChangeResult(StateChangeResult.NO_ERROR);
acmDefinition.setState(AcTypeState.PRIMING);
+ acmDefinition.setLastMsg(TimestampHelper.now());
var acElements = AcmUtils.extractAcElementsFromServiceTemplate(acmDefinition.getServiceTemplate(),
acRuntimeParameterGroup.getAcmParameters().getToscaElementName());
Map<ToscaConceptIdentifier, UUID> supportedElementMap = new HashMap<>();
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
+import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
class SupervisionScannerTest {
acDefinition.setState(acTypeState);
acDefinition.setStateChangeResult(stateChangeResult);
acDefinition.setCompositionId(compositionId);
+ acDefinition.setLastMsg(TimestampHelper.now());
acDefinition.setServiceTemplate(serviceTemplate);
var node = new NodeTemplateState();
node.setState(AcTypeState.PRIMING);
var acDefinition = new AutomationCompositionDefinition();
acDefinition.setCompositionId(UUID.randomUUID());
acDefinition.setState(state);
+ acDefinition.setLastMsg(TimestampHelper.now());
acDefinition.setServiceTemplate(serviceTemplate);
var acElements = AcmUtils
.extractAcElementsFromServiceTemplate(serviceTemplate, TOSCA_ELEMENT_NAME);