Update compositions and instances monitoring 92/137492/1
authorFrancescoFioraEst <francesco.fiora@est.tech>
Thu, 14 Dec 2023 17:33:57 +0000 (17:33 +0000)
committerFrancesco Fiora <francesco.fiora@est.tech>
Fri, 8 Mar 2024 16:14:43 +0000 (16:14 +0000)
Improved performance scanning only compositions and instances
that are in transition.

Issue-ID: POLICY-4906
Change-Id: I7a849e921f1d97509f67ff624c715c893a1432ab
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
15 files changed:
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProvider.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionDefinitionRepository.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionRepository.java
models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProviderTest.java
models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandler.java
participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandlerTest.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/TimeoutHandler.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java

index a9b9a0c..9eb5e7a 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2023 Nordix Foundation.
+ *  Copyright (C) 2021-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.
@@ -28,10 +28,14 @@ import java.util.UUID;
 import lombok.RequiredArgsConstructor;
 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.NodeTemplateState;
+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.persistence.concepts.JpaAutomationCompositionDefinition;
+import org.onap.policy.clamp.models.acm.persistence.concepts.JpaNodeTemplateState;
 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.common.parameters.BeanValidationResult;
 import org.onap.policy.models.base.PfModelRuntimeException;
@@ -47,6 +51,7 @@ import org.springframework.transaction.annotation.Transactional;
 public class AcDefinitionProvider {
 
     private final AutomationCompositionDefinitionRepository acmDefinitionRepository;
+    private final NodeTemplateStateRepository nodeTemplateStateRepository;
 
     /**
      * Create Automation Composition Definition.
@@ -124,6 +129,43 @@ public class AcDefinitionProvider {
         acmDefinitionRepository.flush();
     }
 
+    /**
+     * Update Ac Definition AcTypeState, StateChangeResult and restarting.
+     *
+     * @param compositionId The UUID of the automation composition definition to update
+     * @param state the AcTypeState
+     * @param stateChangeResult the StateChangeResult
+     * @param restarting restarting process
+     */
+    public void updateAcDefinitionState(UUID compositionId, AcTypeState state, StateChangeResult stateChangeResult,
+                                      Boolean restarting) {
+        var jpaUpdate = acmDefinitionRepository.findById(compositionId.toString());
+        if (jpaUpdate.isEmpty()) {
+            String errorMessage = "update of Automation Composition Definition \"" + compositionId
+                + "\" failed, Automation Composition Definition does not exist";
+            throw new PfModelRuntimeException(Response.Status.NOT_FOUND, errorMessage);
+        }
+        var acDefinition = jpaUpdate.get();
+        acDefinition.setState(state);
+        acDefinition.setStateChangeResult(stateChangeResult);
+        acDefinition.setRestarting(restarting);
+        acmDefinitionRepository.save(acDefinition);
+        acmDefinitionRepository.flush();
+    }
+
+    /**
+     * Update Ac DefinitionElement.
+     *
+     * @param nodeTemplateState the NodeTemplateState
+     * @param compositionId The UUID of the automation composition definition
+     */
+    public void updateAcDefinitionElement(NodeTemplateState nodeTemplateState, UUID compositionId) {
+        var jpaNodeTemplateState = new JpaNodeTemplateState(
+            nodeTemplateState.getNodeTemplateStateId().toString(), compositionId.toString());
+        jpaNodeTemplateState.fromAuthorative(nodeTemplateState);
+        nodeTemplateStateRepository.save(jpaNodeTemplateState);
+    }
+
     /**
      * Delete Automation Composition Definition.
      *
@@ -173,13 +215,13 @@ public class AcDefinitionProvider {
     }
 
     /**
-     * Get Automation Composition Definitions.
+     * Get Automation Composition Definitions in transition.
      *
      * @return the Automation Composition Definitions found
      */
     @Transactional(readOnly = true)
-    public List<AutomationCompositionDefinition> getAllAcDefinitions() {
-        var jpaList = acmDefinitionRepository.findAll();
+    public List<AutomationCompositionDefinition> getAllAcDefinitionsInTransition() {
+        var jpaList = acmDefinitionRepository.findByStateIn(List.of(AcTypeState.PRIMING, AcTypeState.DEPRIMING));
         return ProviderUtils.asEntityList(jpaList);
     }
 
index 1ffcc1b..8be1296 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation.
+ * Copyright (C) 2021-2024 Nordix Foundation.
  * ================================================================================
  * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
@@ -127,7 +127,7 @@ public class AutomationCompositionProvider {
             @NonNull final AutomationComposition automationComposition) {
         var result = automationCompositionRepository.save(ProviderUtils.getJpaAndValidate(automationComposition,
                 JpaAutomationComposition::new, "automation composition"));
-
+        automationCompositionRepository.flush();
         // Return the saved automation composition
         return result.toAuthorative();
     }
@@ -144,6 +144,20 @@ public class AutomationCompositionProvider {
                 .asEntityList(automationCompositionRepository.findByCompositionId(compositionId.toString()));
     }
 
+    /**
+     * Get all automation compositions in transition..
+     *
+     * @return all automation compositions found
+     */
+    @Transactional(readOnly = true)
+    public List<AutomationComposition> getAcInstancesInTransition() {
+        var jpaList = automationCompositionRepository.findByDeployStateIn(List.of(DeployState.DEPLOYING,
+            DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING));
+        jpaList.addAll(automationCompositionRepository.findByLockStateIn(
+            List.of(LockState.LOCKING, LockState.UNLOCKING)));
+        return ProviderUtils.asEntityList(jpaList);
+    }
+
     /**
      * Get automation compositions.
      *
index df4d7df..86de60b 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2022 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.
 
 package org.onap.policy.clamp.models.acm.persistence.repository;
 
+import java.util.Collection;
+import java.util.List;
+import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionDefinition;
 import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.repository.query.QueryByExampleExecutor;
 import org.springframework.stereotype.Repository;
 
 @Repository
 public interface AutomationCompositionDefinitionRepository
-        extends JpaRepository<JpaAutomationCompositionDefinition, String>,
-        QueryByExampleExecutor<JpaAutomationCompositionDefinition> {
+        extends JpaRepository<JpaAutomationCompositionDefinition, String> {
+
+    List<JpaAutomationCompositionDefinition> findByStateIn(Collection<AcTypeState> states);
 }
index bb8b3e6..d61dfb4 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation.
+ *  Copyright (C) 2021-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.
 
 package org.onap.policy.clamp.models.acm.persistence.repository;
 
+import java.util.Collection;
 import java.util.List;
+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.persistence.concepts.JpaAutomationComposition;
 import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.repository.query.QueryByExampleExecutor;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public interface AutomationCompositionRepository
-        extends JpaRepository<JpaAutomationComposition, String>, QueryByExampleExecutor<JpaAutomationComposition> {
+public interface AutomationCompositionRepository extends JpaRepository<JpaAutomationComposition, String> {
 
     List<JpaAutomationComposition> findByCompositionId(String compositionId);
+
+    List<JpaAutomationComposition> findByDeployStateIn(Collection<DeployState> deployStates);
+
+    List<JpaAutomationComposition> findByLockStateIn(Collection<LockState> lockStates);
 }
index 78095c9..1e067c8 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2023 Nordix Foundation.
+ *  Copyright (C) 2021-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.
@@ -38,9 +38,12 @@ import org.mockito.Mockito;
 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.NodeTemplateState;
+import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
 import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionDefinition;
+import org.onap.policy.clamp.models.acm.persistence.concepts.JpaNodeTemplateState;
 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.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
@@ -91,7 +94,7 @@ class AcDefinitionProviderTest {
         when(acmDefinitionRepository.save(any(JpaAutomationCompositionDefinition.class)))
                 .thenReturn(new JpaAutomationCompositionDefinition(acmDefinition));
 
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
         var result = acDefinitionProvider
                 .createAutomationCompositionDefinition(inputServiceTemplate, ELEMENT_NAME, NODE_TYPE);
 
@@ -101,11 +104,9 @@ class AcDefinitionProviderTest {
 
     @Test
     void testToscaWithInvalidElement() {
-        var docServiceTemplate = new DocToscaServiceTemplate(inputServiceTemplate);
-        var acmDefinition = getAcDefinition(docServiceTemplate);
         var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
 
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
 
         assertThatThrownBy(() -> acDefinitionProvider
                 .createAutomationCompositionDefinition(inputServiceTemplate, INVALID_ELEMENT_NAME, NODE_TYPE))
@@ -114,11 +115,9 @@ class AcDefinitionProviderTest {
 
     @Test
     void testToscaWithInvalidNodeType() {
-        var docServiceTemplate = new DocToscaServiceTemplate(inputServiceTemplate);
-        var acmDefinition = getAcDefinition(docServiceTemplate);
         var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
 
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
 
         assertThatThrownBy(() -> acDefinitionProvider
                 .createAutomationCompositionDefinition(inputServiceTemplate, ELEMENT_NAME, INVALID_NODE_TYPE))
@@ -135,7 +134,7 @@ class AcDefinitionProviderTest {
         when(acmDefinitionRepository.save(any(JpaAutomationCompositionDefinition.class)))
             .thenReturn(new JpaAutomationCompositionDefinition(acmDefinition));
 
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
         inputServiceTemplate.setMetadata(new HashMap<>());
         var result = acDefinitionProvider
                 .createAutomationCompositionDefinition(inputServiceTemplate, ELEMENT_NAME, NODE_TYPE);
@@ -147,7 +146,7 @@ class AcDefinitionProviderTest {
     @Test
     void testUpdateServiceTemplate() {
         var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
         acDefinitionProvider.updateServiceTemplate(UUID.randomUUID(), inputServiceTemplate, ELEMENT_NAME, NODE_TYPE);
         verify(acmDefinitionRepository).save(any(JpaAutomationCompositionDefinition.class));
     }
@@ -155,19 +154,45 @@ class AcDefinitionProviderTest {
     @Test
     void testUpdateAcDefinition() {
         var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
         var acmDefinition = getAcDefinition(new DocToscaServiceTemplate(inputServiceTemplate));
         acDefinitionProvider.updateAcDefinition(acmDefinition, NODE_TYPE);
         verify(acmDefinitionRepository).save(any(JpaAutomationCompositionDefinition.class));
     }
 
+    @Test
+    void testUpdateAcDefinitionState() {
+        var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
+        var acmDefinition = getAcDefinition(new DocToscaServiceTemplate(inputServiceTemplate));
+        acmDefinition.setState(AcTypeState.PRIMING);
+        var jpa = new JpaAutomationCompositionDefinition(acmDefinition);
+        when(acmDefinitionRepository.findById(acmDefinition.getCompositionId().toString()))
+            .thenReturn(Optional.of(jpa));
+        acDefinitionProvider.updateAcDefinitionState(acmDefinition.getCompositionId(), AcTypeState.PRIMED,
+            StateChangeResult.NO_ERROR, false);
+        verify(acmDefinitionRepository).save(jpa);
+    }
+
+    @Test
+    void testUpdateAcDefinitionElement() {
+        var nodeTemplateState = new NodeTemplateState();
+        nodeTemplateState.setNodeTemplateId(new ToscaConceptIdentifier("name", "1.0.0"));
+        nodeTemplateState.setNodeTemplateStateId(UUID.randomUUID());
+        nodeTemplateState.setState(AcTypeState.PRIMED);
+        var nodeTemplateStateRepository = mock(NodeTemplateStateRepository.class);
+        var acDefinitionProvider = new AcDefinitionProvider(null, nodeTemplateStateRepository);
+        acDefinitionProvider.updateAcDefinitionElement(nodeTemplateState, UUID.randomUUID());
+        verify(nodeTemplateStateRepository).save(any(JpaNodeTemplateState.class));
+    }
+
     @Test
     void testGetAcDefinition() {
         var jpa = new JpaAutomationCompositionDefinition();
         jpa.fromAuthorative(getAcDefinition(new DocToscaServiceTemplate(inputServiceTemplate)));
         var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
         when(acmDefinitionRepository.findById(jpa.getCompositionId())).thenReturn(Optional.of(jpa));
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
         var result = acDefinitionProvider.getAcDefinition(UUID.fromString(jpa.getCompositionId()));
         assertThat(result).isNotNull();
     }
@@ -175,7 +200,7 @@ class AcDefinitionProviderTest {
     @Test
     void testGetAcDefinitionNotFound() {
         var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
         var compositionId = UUID.randomUUID();
         assertThatThrownBy(() -> acDefinitionProvider.getAcDefinition(compositionId))
                 .hasMessage("Get serviceTemplate \"" + compositionId + "\" failed, serviceTemplate does not exist");
@@ -187,20 +212,24 @@ class AcDefinitionProviderTest {
         jpa.fromAuthorative(getAcDefinition(new DocToscaServiceTemplate(inputServiceTemplate)));
         var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
         when(acmDefinitionRepository.findById(jpa.getCompositionId())).thenReturn(Optional.of(jpa));
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
-        var result = acDefinitionProvider.findAcDefinition(UUID.fromString(jpa.getCompositionId()));
-        assertThat(result).isNotNull();
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
+        var compositionId = UUID.fromString(jpa.getCompositionId());
+        var result = acDefinitionProvider.findAcDefinition(compositionId);
+        assertThat(result).isNotEmpty();
     }
 
     @Test
-    void testGetAllAcDefinitions() {
+    void getAllAcDefinitionsInTransition() {
+        var acDefinition = getAcDefinition(new DocToscaServiceTemplate(inputServiceTemplate));
+        acDefinition.setState(AcTypeState.PRIMING);
         var jpa = new JpaAutomationCompositionDefinition();
-        jpa.fromAuthorative(getAcDefinition(new DocToscaServiceTemplate(inputServiceTemplate)));
+        jpa.fromAuthorative(acDefinition);
         var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
-        when(acmDefinitionRepository.findAll()).thenReturn(List.of(jpa));
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
-        var result = acDefinitionProvider.getAllAcDefinitions();
-        assertThat(result).hasSize(1);
+        when(acmDefinitionRepository.findByStateIn(List.of(AcTypeState.PRIMING, AcTypeState.DEPRIMING)))
+            .thenReturn(List.of(jpa));
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
+        var result = acDefinitionProvider.getAllAcDefinitionsInTransition();
+        assertThat(result).isNotEmpty();
     }
 
     @Test
@@ -212,7 +241,7 @@ class AcDefinitionProviderTest {
         when(acmDefinitionRepository.findById(acmDefinition.getCompositionId().toString()))
                 .thenReturn(Optional.of(new JpaAutomationCompositionDefinition(acmDefinition)));
 
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
         var result = acDefinitionProvider.deleteAcDefintion(acmDefinition.getCompositionId());
 
         assertThat(result).isEqualTo(docServiceTemplate.toAuthorative());
@@ -222,7 +251,7 @@ class AcDefinitionProviderTest {
     void testDeleteServiceTemplateEmpty() {
         var compositionId = UUID.randomUUID();
         var acmDefinitionRepository = mock(AutomationCompositionDefinitionRepository.class);
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
         assertThatThrownBy(() -> acDefinitionProvider.deleteAcDefintion(compositionId))
                 .hasMessage("delete of Automation Composition Definition \"" + compositionId
                         + "\" failed, Automation Composition Definition does not exist");
@@ -236,7 +265,7 @@ class AcDefinitionProviderTest {
         when(acmDefinitionRepository.findAll(Mockito.<Example<JpaAutomationCompositionDefinition>>any()))
                 .thenReturn(List.of(new JpaAutomationCompositionDefinition(acmDefinition)));
 
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
         var result = acDefinitionProvider.getServiceTemplateList(inputServiceTemplate.getName(),
                 inputServiceTemplate.getVersion());
 
@@ -252,7 +281,7 @@ class AcDefinitionProviderTest {
         when(acmDefinitionRepository.findAll(Mockito.<Example<JpaAutomationCompositionDefinition>>any()))
             .thenReturn(List.of(new JpaAutomationCompositionDefinition(acmDefinition)));
 
-        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository);
+        var acDefinitionProvider = new AcDefinitionProvider(acmDefinitionRepository, null);
         var result = acDefinitionProvider.getServiceTemplateList(null,
             inputServiceTemplate.getVersion());
 
index b09ddda..463e958 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation.
+ * Copyright (C) 2021-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.
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import java.util.UUID;
@@ -40,6 +41,8 @@ import org.mockito.Mockito;
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementInfo;
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionInfo;
 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
+import org.onap.policy.clamp.models.acm.concepts.DeployState;
+import org.onap.policy.clamp.models.acm.concepts.LockState;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationComposition;
 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionElement;
 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionElementRepository;
@@ -176,6 +179,27 @@ class AutomationCompositionProviderTest {
         assertEquals(inputAutomationCompositions.getAutomationCompositionList(), acList);
     }
 
+    @Test
+    void testGetAcInstancesInTransition() {
+        inputAutomationCompositions.getAutomationCompositionList().get(0).setDeployState(DeployState.DEPLOYING);
+        inputAutomationCompositions.getAutomationCompositionList().get(1).setLockState(LockState.LOCKING);
+        inputAutomationCompositionsJpa.get(0).setDeployState(DeployState.DEPLOYING);
+        inputAutomationCompositionsJpa.get(1).setLockState(LockState.LOCKING);
+
+        List<JpaAutomationComposition> res1 = new ArrayList<>();
+        res1.add(inputAutomationCompositionsJpa.get(0));
+        var automationCompositionRepository = mock(AutomationCompositionRepository.class);
+        var automationCompositionProvider = new AutomationCompositionProvider(automationCompositionRepository,
+            mock(AutomationCompositionElementRepository.class));
+        when(automationCompositionRepository.findByDeployStateIn(List.of(DeployState.DEPLOYING,
+            DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING)))
+            .thenReturn(res1);
+        when(automationCompositionRepository.findByLockStateIn(List.of(LockState.LOCKING, LockState.UNLOCKING)))
+            .thenReturn(List.of(inputAutomationCompositionsJpa.get(1)));
+        var acList = automationCompositionProvider.getAcInstancesInTransition();
+        assertEquals(inputAutomationCompositions.getAutomationCompositionList(), acList);
+    }
+
     @Test
     void testDeleteAutomationComposition() {
         var automationCompositionRepository = mock(AutomationCompositionRepository.class);
index fd82c37..fefa637 100644 (file)
@@ -40,6 +40,7 @@ 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.ParticipantDeploy;
 import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc;
+import org.onap.policy.clamp.models.acm.concepts.ParticipantState;
 import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils;
 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeploy;
@@ -47,6 +48,7 @@ import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCom
 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration;
 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionStateChange;
 import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantMessageType;
+import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrimeAck;
 import org.onap.policy.clamp.models.acm.messages.kafka.participant.PropertiesUpdate;
 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
@@ -428,6 +430,16 @@ public class AutomationCompositionHandler {
         var acElementsDefinitions = cacheProvider.getAcElementsDefinitions().get(compositionId);
         if (acElementsDefinitions == null) {
             // this participant does not handle this composition
+            var participantPrimeAck = new ParticipantPrimeAck();
+            participantPrimeAck.setCompositionId(compositionId);
+            participantPrimeAck.setMessage("Already deprimed or never primed");
+            participantPrimeAck.setResult(true);
+            participantPrimeAck.setResponseTo(messageId);
+            participantPrimeAck.setCompositionState(AcTypeState.COMMISSIONED);
+            participantPrimeAck.setStateChangeResult(StateChangeResult.NO_ERROR);
+            participantPrimeAck.setParticipantId(cacheProvider.getParticipantId());
+            participantPrimeAck.setState(ParticipantState.ON_LINE);
+            publisher.sendParticipantPrimeAck(participantPrimeAck);
             return;
         }
         var list = new ArrayList<>(acElementsDefinitions.values());
index 661c009..b8fd3b4 100644 (file)
@@ -47,6 +47,7 @@ import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCom
 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck;
 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration;
 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionStateChange;
+import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrimeAck;
 import org.onap.policy.clamp.models.acm.messages.kafka.participant.PropertiesUpdate;
 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
@@ -273,7 +274,7 @@ class AutomationCompositionHandlerTest {
     }
 
     @Test
-    void handleComposiotDeprimeTest() {
+    void handleCompositionDeprimeTest() {
         var acElementDefinition = new AutomationCompositionElementDefinition();
         acElementDefinition.setAcElementDefinitionId(new ToscaConceptIdentifier("key", "1.0.0"));
         var toscaNodeTemplate = new ToscaNodeTemplate();
@@ -291,6 +292,17 @@ class AutomationCompositionHandlerTest {
         verify(listener).deprime(any(UUID.class), any(CompositionDto.class));
     }
 
+    @Test
+    void handleCompositionAlreadyDeprimedTest() {
+        var messageId = UUID.randomUUID();
+        var compositionId = UUID.randomUUID();
+        var participantMessagePublisher =  mock(ParticipantMessagePublisher.class);
+        var ach = new AutomationCompositionHandler(mock(CacheProvider.class), participantMessagePublisher,
+            mock(ThreadHandler.class));
+        ach.deprime(messageId, compositionId);
+        verify(participantMessagePublisher).sendParticipantPrimeAck(any(ParticipantPrimeAck.class));
+    }
+
     @Test
     void restartedTest() {
         var acElementDefinition = new AutomationCompositionElementDefinition();
index a5dc0e7..d6fa5d8 100644 (file)
@@ -204,7 +204,6 @@ public class SupervisionAcHandler {
             description = "AUTOMATION_COMPOSITION_DEPLOY_ACK messages received")
     public void handleAutomationCompositionUpdateAckMessage(
             AutomationCompositionDeployAck automationCompositionAckMessage) {
-        LOGGER.debug("AutomationComposition Update Ack message received {}", automationCompositionAckMessage);
         setAcElementStateInDb(automationCompositionAckMessage);
     }
 
@@ -219,7 +218,6 @@ public class SupervisionAcHandler {
             description = "AUTOMATION_COMPOSITION_STATECHANGE_ACK messages received")
     public void handleAutomationCompositionStateChangeAckMessage(
             AutomationCompositionDeployAck automationCompositionAckMessage) {
-        LOGGER.debug("AutomationComposition StateChange Ack message received {}", automationCompositionAckMessage);
         setAcElementStateInDb(automationCompositionAckMessage);
     }
 
index 660cb28..963e483 100644 (file)
@@ -52,7 +52,6 @@ public class SupervisionHandler {
      */
     @Timed(value = "listener.participant_prime_ack", description = "PARTICIPANT_PRIME_ACK messages received")
     public void handleParticipantMessage(ParticipantPrimeAck participantPrimeAckMessage) {
-        LOGGER.debug("Participant Prime Ack message received {}", participantPrimeAckMessage);
         var acDefinitionOpt = acDefinitionProvider.findAcDefinition(participantPrimeAckMessage.getCompositionId());
         if (acDefinitionOpt.isEmpty()) {
             LOGGER.warn("AC Definition not found in database {}", participantPrimeAckMessage.getCompositionId());
@@ -74,8 +73,10 @@ public class SupervisionHandler {
                 || AcTypeState.PRIMED.equals(acDefinition.getState()) ? AcTypeState.PRIMED : AcTypeState.COMMISSIONED;
         var msgInErrors = StateChangeResult.FAILED.equals(participantPrimeAckMessage.getStateChangeResult());
         boolean inProgress = !StateChangeResult.FAILED.equals(acDefinition.getStateChangeResult());
+        boolean toUpdate = false;
         if (inProgress && msgInErrors) {
             acDefinition.setStateChangeResult(StateChangeResult.FAILED);
+            toUpdate = true;
         }
 
         boolean completed = true;
@@ -85,6 +86,7 @@ public class SupervisionHandler {
                 element.setMessage(participantPrimeAckMessage.getMessage());
                 element.setState(participantPrimeAckMessage.getCompositionState());
                 element.setRestarting(null);
+                acDefinitionProvider.updateAcDefinitionElement(element, acDefinition.getCompositionId());
             }
             if (!finalState.equals(element.getState())) {
                 completed = false;
@@ -95,16 +97,19 @@ public class SupervisionHandler {
         }
 
         if (inProgress && !msgInErrors && completed) {
+            toUpdate = true;
             acDefinition.setState(finalState);
             if (StateChangeResult.TIMEOUT.equals(acDefinition.getStateChangeResult())) {
                 acDefinition.setStateChangeResult(StateChangeResult.NO_ERROR);
             }
         }
-        if (!restarting) {
+        if (!restarting && acDefinition.getRestarting() != null) {
+            toUpdate = true;
             acDefinition.setRestarting(null);
         }
-        acDefinitionProvider.updateAcDefinition(acDefinition,
-                acRuntimeParameterGroup.getAcmParameters().getToscaCompositionName());
+        if (toUpdate) {
+            acDefinitionProvider.updateAcDefinitionState(acDefinition.getCompositionId(), acDefinition.getState(),
+                acDefinition.getStateChangeResult(), acDefinition.getRestarting());
+        }
     }
-
 }
index 7a2c58d..24c256f 100644 (file)
@@ -74,7 +74,6 @@ public class SupervisionParticipantHandler {
     @MessageIntercept
     @Timed(value = "listener.participant_register", description = "PARTICIPANT_REGISTER messages received")
     public void handleParticipantMessage(ParticipantRegister participantRegisterMsg) {
-        LOGGER.debug("Participant Register received {}", participantRegisterMsg);
         var participantOpt = participantProvider.findParticipant(participantRegisterMsg.getParticipantId());
 
         if (participantOpt.isPresent()) {
@@ -100,7 +99,6 @@ public class SupervisionParticipantHandler {
     @MessageIntercept
     @Timed(value = "listener.participant_deregister", description = "PARTICIPANT_DEREGISTER messages received")
     public void handleParticipantMessage(ParticipantDeregister participantDeregisterMsg) {
-        LOGGER.debug("Participant Deregister received {}", participantDeregisterMsg);
         var participantOpt = participantProvider.findParticipant(participantDeregisterMsg.getParticipantId());
 
         if (participantOpt.isPresent()) {
@@ -120,7 +118,6 @@ public class SupervisionParticipantHandler {
     @MessageIntercept
     @Timed(value = "listener.participant_status", description = "PARTICIPANT_STATUS messages received")
     public void handleParticipantMessage(ParticipantStatus participantStatusMsg) {
-        LOGGER.debug("Participant Status received {}", participantStatusMsg);
 
         var participantOpt = participantProvider.findParticipant(participantStatusMsg.getParticipantId());
         if (participantOpt.isEmpty()) {
index 33118fa..881969a 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation.
+ * Copyright (C) 2021-2024 Nordix Foundation.
  * ================================================================================
  * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
 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.acm.runtime.supervision.comm.AutomationCompositionDeployPublisher;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionStateChangePublisher;
@@ -56,7 +59,6 @@ public class SupervisionScanner {
     private final AcDefinitionProvider acDefinitionProvider;
     private final AutomationCompositionStateChangePublisher automationCompositionStateChangePublisher;
     private final AutomationCompositionDeployPublisher automationCompositionDeployPublisher;
-    private final AcRuntimeParameterGroup acRuntimeParameterGroup;
 
     /**
      * Constructor for instantiating SupervisionScanner.
@@ -76,7 +78,6 @@ public class SupervisionScanner {
         this.acDefinitionProvider = acDefinitionProvider;
         this.automationCompositionStateChangePublisher = automationCompositionStateChangePublisher;
         this.automationCompositionDeployPublisher = automationCompositionDeployPublisher;
-        this.acRuntimeParameterGroup = acRuntimeParameterGroup;
 
         acTimeout.setMaxWaitMs(acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs());
     }
@@ -87,20 +88,27 @@ public class SupervisionScanner {
     public void run() {
         LOGGER.debug("Scanning automation compositions in the database . . .");
 
-        var list = acDefinitionProvider.getAllAcDefinitions();
-        for (var acDefinition : list) {
-            if (AcTypeState.PRIMING.equals(acDefinition.getState())
-                    || AcTypeState.DEPRIMING.equals(acDefinition.getState())) {
-                scanAutomationCompositionDefinition(acDefinition);
-            } else {
-                acTimeout.clear(acDefinition.getCompositionId());
-                var acList =
-                        automationCompositionProvider.getAcInstancesByCompositionId(acDefinition.getCompositionId());
-                for (var automationComposition : acList) {
-                    scanAutomationComposition(automationComposition, acDefinition.getServiceTemplate());
-                }
+        var acDefinitionList = acDefinitionProvider.getAllAcDefinitionsInTransition();
+        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<>();
+        for (var automationComposition : acList) {
+            var acDefinition = acDefinitionMap.get(automationComposition.getCompositionId());
+            if (acDefinition == null) {
+                acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId());
+                acDefinitionMap.put(acDefinition.getCompositionId(), acDefinition);
             }
+            scanAutomationComposition(automationComposition, acDefinition.getServiceTemplate());
         }
+        set.addAll(
+            acList.stream().map(AutomationComposition::getInstanceId).collect(Collectors.toSet()));
+        acTimeout.removeIfNotPresent(set);
 
         LOGGER.debug("Automation composition scan complete . . .");
     }
@@ -110,7 +118,7 @@ public class SupervisionScanner {
             LOGGER.debug("automation definition {} scanned, OK", acDefinition.getCompositionId());
 
             // Clear Timeout on ac Definition
-            acTimeout.clear(acDefinition.getCompositionId());
+            acTimeout.remove(acDefinition.getCompositionId());
             return;
         }
 
@@ -121,7 +129,21 @@ public class SupervisionScanner {
             acTimeout.clear(acDefinition.getCompositionId());
         }
 
-        handleTimeout(acDefinition);
+        boolean completed = true;
+        var finalState = AcTypeState.PRIMING.equals(acDefinition.getState())
+            || AcTypeState.PRIMED.equals(acDefinition.getState()) ? AcTypeState.PRIMED : AcTypeState.COMMISSIONED;
+        for (var element : acDefinition.getElementStateMap().values()) {
+            if (!finalState.equals(element.getState())) {
+                completed = false;
+            }
+        }
+        if (completed) {
+            acDefinitionProvider.updateAcDefinitionState(acDefinition.getCompositionId(), finalState,
+                StateChangeResult.NO_ERROR, null);
+            acTimeout.remove(acDefinition.getCompositionId());
+        } else {
+            handleTimeout(acDefinition);
+        }
     }
 
     private void scanAutomationComposition(final AutomationComposition automationComposition,
@@ -134,7 +156,7 @@ public class SupervisionScanner {
             LOGGER.debug("automation composition {} scanned, OK", automationComposition.getInstanceId());
 
             // Clear Timeout on automation composition
-            clearTimeout(automationComposition, true);
+            removeTimeout(automationComposition);
             return;
         }
 
@@ -214,7 +236,7 @@ public class SupervisionScanner {
         }
 
         // Clear timeout on automation composition
-        clearTimeout(automationComposition, true);
+        removeTimeout(automationComposition);
     }
 
     private void clearTimeout(AutomationComposition automationComposition, boolean cleanPhase) {
@@ -224,6 +246,11 @@ public class SupervisionScanner {
         }
     }
 
+    private void removeTimeout(AutomationComposition automationComposition) {
+        acTimeout.remove(automationComposition.getInstanceId());
+        phaseMap.remove(automationComposition.getInstanceId());
+    }
+
     private void handleTimeout(AutomationCompositionDefinition acDefinition) {
         var compositionId = acDefinition.getCompositionId();
         if (acTimeout.isTimeout(compositionId)) {
@@ -235,8 +262,8 @@ public class SupervisionScanner {
             LOGGER.debug("Report timeout for the ac definition {}", acDefinition.getCompositionId());
             acTimeout.setTimeout(compositionId);
             acDefinition.setStateChangeResult(StateChangeResult.TIMEOUT);
-            acDefinitionProvider.updateAcDefinition(acDefinition,
-                    acRuntimeParameterGroup.getAcmParameters().getToscaCompositionName());
+            acDefinitionProvider.updateAcDefinitionState(acDefinition.getCompositionId(),
+                acDefinition.getState(), acDefinition.getStateChangeResult(), acDefinition.getRestarting());
         }
     }
 
index 976c914..3b34252 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2023 Nordix Foundation.
+ *  Copyright (C) 2023-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.
@@ -33,8 +33,8 @@ public class TimeoutHandler<K> {
     @Setter
     private long maxWaitMs;
 
-    private Set<K> mapTimeout = new HashSet<>();
-    private Map<K, Long> mapTimer = new HashMap<>();
+    private final Set<K> mapTimeout = new HashSet<>();
+    private final Map<K, Long> mapTimer = new HashMap<>();
 
     public long getDuration(K id) {
         mapTimer.putIfAbsent(id, getEpochMilli());
@@ -61,6 +61,18 @@ public class TimeoutHandler<K> {
         mapTimer.remove(id);
     }
 
+    /**
+     * Remove elements that are not present in set.
+     *
+     * @param set the elements that should be present
+     */
+    public void removeIfNotPresent(final Set<K> set) {
+        var res = mapTimeout.stream().filter(el -> !set.contains(el)).toList();
+        if (!res.isEmpty()) {
+            res.forEach(this::remove);
+        }
+    }
+
     public void setTimeout(K id) {
         mapTimeout.add(id);
     }
index 4028f57..448666f 100644 (file)
@@ -22,6 +22,7 @@ package org.onap.policy.clamp.acm.runtime.supervision;
 
 import static org.mockito.ArgumentMatchers.any;
 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.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML;
@@ -77,13 +78,16 @@ class SupervisionHandlerTest {
     void testParticipantPrimeAck() {
         var participantPrimeAckMessage = new ParticipantPrimeAck();
         participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId());
+        participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED);
         participantPrimeAckMessage.setState(ParticipantState.ON_LINE);
 
         var acDefinition = CommonTestData.createAcDefinition(
                 InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMING);
+        acDefinition.setStateChangeResult(StateChangeResult.NO_ERROR);
         participantPrimeAckMessage.setCompositionId(acDefinition.getCompositionId());
-        acDefinition.getElementStateMap().values().iterator().next()
-                .setParticipantId(CommonTestData.getParticipantId());
+        for (var element : acDefinition.getElementStateMap().values()) {
+            element.setParticipantId(CommonTestData.getParticipantId());
+        }
 
         var acDefinitionProvider = mock(AcDefinitionProvider.class);
         when(acDefinitionProvider.findAcDefinition(acDefinition.getCompositionId()))
@@ -93,7 +97,10 @@ class SupervisionHandlerTest {
 
         handler.handleParticipantMessage(participantPrimeAckMessage);
         verify(acDefinitionProvider).findAcDefinition(any());
-        verify(acDefinitionProvider).updateAcDefinition(any(), any());
+        verify(acDefinitionProvider, times(acDefinition.getElementStateMap().size()))
+            .updateAcDefinitionElement(any(), any());
+        verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), AcTypeState.PRIMED,
+            StateChangeResult.NO_ERROR, null);
     }
 
     @Test
@@ -117,6 +124,39 @@ class SupervisionHandlerTest {
 
         handler.handleParticipantMessage(participantPrimeAckMessage);
         verify(acDefinitionProvider).findAcDefinition(any());
-        verify(acDefinitionProvider).updateAcDefinition(any(), any());
+        verify(acDefinitionProvider).updateAcDefinitionElement(any(), any());
+        verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), AcTypeState.PRIMING,
+            StateChangeResult.FAILED, null);
+    }
+
+    @Test
+    void testParticipantPrimeAckRestarted() {
+        var participantPrimeAckMessage = new ParticipantPrimeAck();
+        participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId());
+        participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED);
+        participantPrimeAckMessage.setState(ParticipantState.ON_LINE);
+
+        var acDefinition = CommonTestData.createAcDefinition(
+            InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMED);
+        acDefinition.setStateChangeResult(StateChangeResult.TIMEOUT);
+        acDefinition.setRestarting(true);
+        participantPrimeAckMessage.setCompositionId(acDefinition.getCompositionId());
+        for (var element : acDefinition.getElementStateMap().values()) {
+            element.setParticipantId(CommonTestData.getParticipantId());
+            element.setRestarting(true);
+        }
+
+        var acDefinitionProvider = mock(AcDefinitionProvider.class);
+        when(acDefinitionProvider.findAcDefinition(acDefinition.getCompositionId()))
+            .thenReturn(Optional.of(acDefinition));
+
+        var handler = new SupervisionHandler(acDefinitionProvider, CommonTestData.getTestParamaterGroup());
+
+        handler.handleParticipantMessage(participantPrimeAckMessage);
+        verify(acDefinitionProvider).findAcDefinition(any());
+        verify(acDefinitionProvider, times(acDefinition.getElementStateMap().size()))
+            .updateAcDefinitionElement(any(), any());
+        verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), AcTypeState.PRIMED,
+            StateChangeResult.NO_ERROR, null);
     }
 }
index a1fad46..7d0b425 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2023 Nordix Foundation.
+ *  Copyright (C) 2021-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.
@@ -25,6 +25,7 @@ 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 static org.mockito.Mockito.verify;
@@ -46,6 +47,7 @@ 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.NodeTemplateState;
 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;
@@ -57,82 +59,131 @@ class SupervisionScannerTest {
 
     private static final UUID compositionId = UUID.randomUUID();
 
-    private AcDefinitionProvider createAcDefinitionProvider(AcTypeState acTypeState,
-            StateChangeResult stateChangeResult) {
+    private AutomationCompositionDefinition createAutomationCompositionDefinition(AcTypeState acTypeState,
+                                                                                  StateChangeResult stateChangeResult) {
         var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
         var acDefinition = new AutomationCompositionDefinition();
         acDefinition.setState(acTypeState);
         acDefinition.setStateChangeResult(stateChangeResult);
         acDefinition.setCompositionId(compositionId);
         acDefinition.setServiceTemplate(serviceTemplate);
+        var node = new NodeTemplateState();
+        node.setState(AcTypeState.PRIMING);
+        node.setNodeTemplateStateId(UUID.randomUUID());
+        acDefinition.setElementStateMap(Map.of(node.getNodeTemplateStateId().toString(), node));
+        return acDefinition;
+    }
+
+    private AcDefinitionProvider createAcDefinitionProvider(AutomationCompositionDefinition acDefinition) {
         var acDefinitionProvider = mock(AcDefinitionProvider.class);
-        when(acDefinitionProvider.getAllAcDefinitions()).thenReturn(List.of(Objects.requireNonNull(acDefinition)));
+        var acTypeState = acDefinition.getState();
+        if (AcTypeState.PRIMING.equals(acTypeState) || AcTypeState.DEPRIMING.equals(acTypeState)) {
+            when(acDefinitionProvider.getAllAcDefinitionsInTransition())
+                .thenReturn(List.of(Objects.requireNonNull(acDefinition)));
+        }
+        when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acDefinition);
         return acDefinitionProvider;
     }
 
+    private AcDefinitionProvider createAcDefinitionProvider(AcTypeState acTypeState,
+        StateChangeResult stateChangeResult) {
+        return createAcDefinitionProvider(createAutomationCompositionDefinition(acTypeState, stateChangeResult));
+    }
+
     private AcDefinitionProvider createAcDefinitionProvider() {
         return createAcDefinitionProvider(AcTypeState.PRIMED, StateChangeResult.NO_ERROR);
     }
 
     @Test
-    void testScannerOrderedFailed() {
+    void testAcDefinitionPrimeFailed() {
         var acDefinitionProvider = createAcDefinitionProvider(AcTypeState.PRIMING, StateChangeResult.FAILED);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
         var supervisionScanner = new SupervisionScanner(mock(AutomationCompositionProvider.class), acDefinitionProvider,
                 mock(AutomationCompositionStateChangePublisher.class), mock(AutomationCompositionDeployPublisher.class),
                 acRuntimeParameterGroup);
         supervisionScanner.run();
-        verify(acDefinitionProvider, times(0)).updateAcDefinition(any(AutomationCompositionDefinition.class),
-                eq(CommonTestData.TOSCA_COMP_NAME));
+        verify(acDefinitionProvider, times(0)).updateAcDefinitionState(any(), any(), any(), any());
     }
 
     @Test
-    void testScannerOrderedPriming() {
-        var acDefinitionProvider = createAcDefinitionProvider(AcTypeState.PRIMING, StateChangeResult.NO_ERROR);
+    void testAcDefinitionPrimeTimeout() {
+        var acDefinition = createAutomationCompositionDefinition(AcTypeState.PRIMING, StateChangeResult.NO_ERROR);
+        var acDefinitionProvider = createAcDefinitionProvider(acDefinition);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
         var supervisionScanner = new SupervisionScanner(mock(AutomationCompositionProvider.class), acDefinitionProvider,
                 mock(AutomationCompositionStateChangePublisher.class), mock(AutomationCompositionDeployPublisher.class),
                 acRuntimeParameterGroup);
         supervisionScanner.run();
-        verify(acDefinitionProvider, times(0)).updateAcDefinition(any(AutomationCompositionDefinition.class),
-                eq(CommonTestData.TOSCA_COMP_NAME));
+        // Ac Definition in Priming state
+        verify(acDefinitionProvider, times(0)).updateAcDefinitionState(any(), any(), any(), any());
 
         acRuntimeParameterGroup.getParticipantParameters().setMaxStatusWaitMs(-1);
         supervisionScanner = new SupervisionScanner(mock(AutomationCompositionProvider.class), acDefinitionProvider,
                 mock(AutomationCompositionStateChangePublisher.class), mock(AutomationCompositionDeployPublisher.class),
                 acRuntimeParameterGroup);
         supervisionScanner.run();
-        verify(acDefinitionProvider).updateAcDefinition(any(AutomationCompositionDefinition.class),
-                eq(CommonTestData.TOSCA_COMP_NAME));
+        // set Timeout
+        verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), acDefinition.getState(),
+            StateChangeResult.TIMEOUT, null);
+
+        clearInvocations(acDefinitionProvider);
+        acDefinition.setStateChangeResult(StateChangeResult.TIMEOUT);
+        supervisionScanner.run();
+        // already in Timeout
+        verify(acDefinitionProvider, times(0)).updateAcDefinitionState(any(), any(), any(), any());
+
+        clearInvocations(acDefinitionProvider);
+        // retry by the user
+        acDefinition.setStateChangeResult(StateChangeResult.NO_ERROR);
+        supervisionScanner.run();
+        // set Timeout
+        verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), acDefinition.getState(),
+            StateChangeResult.TIMEOUT, null);
+
+        clearInvocations(acDefinitionProvider);
+        for (var element : acDefinition.getElementStateMap().values()) {
+            element.setState(AcTypeState.PRIMED);
+        }
+        supervisionScanner.run();
+        // completed
+        verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), AcTypeState.PRIMED,
+            StateChangeResult.NO_ERROR, null);
     }
 
     @Test
-    void testScannerOrderedStateEqualsToState() {
+    void testAcNotInTransitionOrFailed() {
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
         var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
         var automationCompositionDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
 
         var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
-        when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+        automationComposition.setCompositionId(compositionId);
+        when(automationCompositionProvider.getAcInstancesInTransition()).thenReturn(List.of(automationComposition));
 
         var supervisionScanner = new SupervisionScanner(automationCompositionProvider, createAcDefinitionProvider(),
                 automationCompositionStateChangePublisher, automationCompositionDeployPublisher,
                 acRuntimeParameterGroup);
+
+        // not in transition
         supervisionScanner.run();
+        verify(automationCompositionProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class));
 
+        automationComposition.setDeployState(DeployState.DEPLOYING);
+        automationComposition.setStateChangeResult(StateChangeResult.FAILED);
+        supervisionScanner.run();
+        // failed
         verify(automationCompositionProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class));
     }
 
     @Test
-    void testScannerOrderedStateDifferentToState() {
+    void testAcUndeployCompleted() {
         var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
         automationComposition.setDeployState(DeployState.UNDEPLOYING);
         automationComposition.setLockState(LockState.NONE);
+        automationComposition.setCompositionId(compositionId);
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
-        when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+        when(automationCompositionProvider.getAcInstancesInTransition()).thenReturn(List.of(automationComposition));
 
         var automationCompositionDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
@@ -147,13 +198,13 @@ class SupervisionScannerTest {
     }
 
     @Test
-    void testScannerDelete() {
+    void testAcDeleted() {
         var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
         automationComposition.setDeployState(DeployState.DELETING);
         automationComposition.setLockState(LockState.NONE);
+        automationComposition.setCompositionId(compositionId);
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
-        when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+        when(automationCompositionProvider.getAcInstancesInTransition()).thenReturn(List.of(automationComposition));
 
         var automationCompositionDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
@@ -171,8 +222,8 @@ class SupervisionScannerTest {
     void testScanner() {
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
         var automationComposition = new AutomationComposition();
-        when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+        automationComposition.setCompositionId(compositionId);
+        when(automationCompositionProvider.getAcInstancesInTransition()).thenReturn(List.of(automationComposition));
 
         var automationCompositionDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
@@ -191,12 +242,12 @@ class SupervisionScannerTest {
         var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
         automationComposition.setDeployState(DeployState.DEPLOYING);
         automationComposition.setLockState(LockState.NONE);
+        automationComposition.setCompositionId(compositionId);
         for (Map.Entry<UUID, AutomationCompositionElement> entry : automationComposition.getElements().entrySet()) {
             entry.getValue().setDeployState(DeployState.DEPLOYING);
         }
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
-        when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+        when(automationCompositionProvider.getAcInstancesInTransition()).thenReturn(List.of(automationComposition));
 
         var automationCompositionDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
@@ -225,6 +276,7 @@ class SupervisionScannerTest {
         var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
         automationComposition.setDeployState(DeployState.DEPLOYING);
         automationComposition.setLockState(LockState.NONE);
+        automationComposition.setCompositionId(compositionId);
         for (var element : automationComposition.getElements().values()) {
             if ("org.onap.domain.database.Http_PMSHMicroserviceAutomationCompositionElement"
                     .equals(element.getDefinition().getName())) {
@@ -237,8 +289,7 @@ class SupervisionScannerTest {
         }
 
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
-        when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+        when(automationCompositionProvider.getAcInstancesInTransition()).thenReturn(List.of(automationComposition));
 
         var automationCompositionDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
@@ -258,6 +309,7 @@ class SupervisionScannerTest {
     void testSendAutomationCompositionMigrate() {
         var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
         automationComposition.setDeployState(DeployState.MIGRATING);
+        automationComposition.setCompositionId(compositionId);
         var compositionTargetId = UUID.randomUUID();
         automationComposition.setCompositionTargetId(compositionTargetId);
         automationComposition.setLockState(LockState.LOCKED);
@@ -267,8 +319,7 @@ class SupervisionScannerTest {
         }
 
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
-        when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+        when(automationCompositionProvider.getAcInstancesInTransition()).thenReturn(List.of(automationComposition));
 
         var automationCompositionDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
@@ -289,6 +340,7 @@ class SupervisionScannerTest {
         var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
         automationComposition.setDeployState(DeployState.DEPLOYED);
         automationComposition.setLockState(LockState.UNLOCKING);
+        automationComposition.setCompositionId(compositionId);
         for (var element : automationComposition.getElements().values()) {
             if ("org.onap.domain.database.Http_PMSHMicroserviceAutomationCompositionElement"
                     .equals(element.getDefinition().getName())) {
@@ -301,8 +353,7 @@ class SupervisionScannerTest {
         }
 
         var automationCompositionProvider = mock(AutomationCompositionProvider.class);
-        when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId))
-                .thenReturn(List.of(automationComposition));
+        when(automationCompositionProvider.getAcInstancesInTransition()).thenReturn(List.of(automationComposition));
 
         var automationCompositionDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);