Add support startPhase in all state transitions 64/125364/1
authorFrancescoFioraEst <francesco.fiora@est.tech>
Fri, 22 Oct 2021 12:52:24 +0000 (13:52 +0100)
committerFrancesco Fiora <francesco.fiora@est.tech>
Fri, 22 Oct 2021 13:44:03 +0000 (13:44 +0000)
Issue-ID: POLICY-3785
Change-Id: I1b5821cc42cdbb63e3172596431dc561ced09c55
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
12 files changed:
models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ParticipantUtils.java
models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ParticipantUtilsTest.java [new file with mode: 0644]
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ControlLoopHandler.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ParticipantHandler.java
runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java
runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScanner.java
runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ControlLoopStateChangePublisher.java
runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProviderTest.java
runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandlerTest.java
runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScannerTest.java
runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/SupervisionMessagesTest.java
runtime-controlloop/src/test/resources/rest/controlloops/ControlLoopsSmoke.json [new file with mode: 0644]

index 4c3dd4b..c053118 100644 (file)
@@ -56,6 +56,30 @@ public final class ParticipantUtils {
         return null;
     }
 
+    /**
+     * Get the First StartPhase
+     * it depend of the state of the Control Loop
+     * and also from the all startPhase defined into the ToscaServiceTemplate.
+     * @param controlLoop the ControlLoop
+     * @param toscaServiceTemplate the ToscaServiceTemplate
+     * @return the First StartPhase
+     */
+    public static int getFirstStartPhase(ControlLoop controlLoop, ToscaServiceTemplate toscaServiceTemplate) {
+        var minStartPhase = 1000;
+        var maxStartPhase = 0;
+        for (var element : controlLoop.getElements().values()) {
+            ToscaNodeTemplate toscaNodeTemplate = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates()
+                    .get(element.getDefinition().getName());
+            int startPhase = ParticipantUtils.findStartPhase(toscaNodeTemplate.getProperties());
+            minStartPhase = Math.min(minStartPhase, startPhase);
+            maxStartPhase = Math.max(maxStartPhase, startPhase);
+        }
+
+        return ControlLoopState.UNINITIALISED2PASSIVE.equals(controlLoop.getState())
+                || ControlLoopState.PASSIVE2RUNNING.equals(controlLoop.getState()) ? minStartPhase
+                        : maxStartPhase;
+    }
+
     /**
      * Finds startPhase from a map of properties.
      *
diff --git a/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ParticipantUtilsTest.java b/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ParticipantUtilsTest.java
new file mode 100644 (file)
index 0000000..3fb8b6d
--- /dev/null
@@ -0,0 +1,84 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 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.controlloop.models.controlloop.concepts;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.coder.StandardYamlCoder;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+
+class ParticipantUtilsTest {
+
+    private static final Coder CODER = new StandardCoder();
+    private static final String TOSCA_TEMPLATE_YAML = "examples/controlloop/PMSubscriptionHandling.yaml";
+    private static final String CONTROL_LOOP_JSON = "src/test/resources/providers/TestControlLoops.json";
+    private static final String CONTROL_LOOP_ELEMENT = "org.onap.policy.clamp.controlloop.ControlLoopElement";
+    private static final String POLICY_CONTROL_LOOP_ELEMENT =
+            "org.onap.policy.clamp.controlloop.PolicyControlLoopElement";
+    private static final String PARTICIPANT_CONTROL_LOOP_ELEMENT = "org.onap.policy.clamp.controlloop.Participant";
+    private static final StandardYamlCoder YAML_TRANSLATOR = new StandardYamlCoder();
+
+    @Test
+    void testFindParticipantType() throws CoderException {
+        var identifier = new ToscaConceptIdentifier("Identifier", "1.0.1");
+        var result = ParticipantUtils.findParticipantType(Map.of("participantType", CODER.encode(identifier)));
+        assertThat(result).isEqualTo(identifier);
+    }
+
+    @Test
+    void testFindStartPhase() {
+        var identifier = 13;
+        var result = ParticipantUtils.findStartPhase(Map.of("startPhase", identifier));
+        assertThat(result).isEqualTo(identifier);
+    }
+
+    @Test
+    void testGetFirstStartPhase() throws CoderException {
+        var serviceTemplate = YAML_TRANSLATOR.decode(ResourceUtils.getResourceAsStream(TOSCA_TEMPLATE_YAML),
+                ToscaServiceTemplate.class);
+        var controlLoops = CODER.decode(ResourceUtils.getResourceAsString(CONTROL_LOOP_JSON), ControlLoops.class);
+        var result = ParticipantUtils.getFirstStartPhase(controlLoops.getControlLoopList().get(0), serviceTemplate);
+        assertThat(result).isZero();
+    }
+
+    @Test
+    void testCheckIfNodeTemplateIsControlLoopElement() throws CoderException {
+        var serviceTemplate = YAML_TRANSLATOR.decode(ResourceUtils.getResourceAsStream(TOSCA_TEMPLATE_YAML),
+                ToscaServiceTemplate.class);
+        var nodeTemplate = new ToscaNodeTemplate();
+        nodeTemplate.setType(CONTROL_LOOP_ELEMENT);
+        assertThat(ParticipantUtils.checkIfNodeTemplateIsControlLoopElement(nodeTemplate, serviceTemplate)).isTrue();
+
+        nodeTemplate.setType(POLICY_CONTROL_LOOP_ELEMENT);
+        assertThat(ParticipantUtils.checkIfNodeTemplateIsControlLoopElement(nodeTemplate, serviceTemplate)).isTrue();
+
+        nodeTemplate.setType(PARTICIPANT_CONTROL_LOOP_ELEMENT);
+        assertThat(ParticipantUtils.checkIfNodeTemplateIsControlLoopElement(nodeTemplate, serviceTemplate)).isFalse();
+    }
+}
index ac135b0..5a0f498 100644 (file)
@@ -93,7 +93,8 @@ public class ControlLoopHandler {
     /**
      * Handle a control loop element state change message.
      *
-     * @param id controlloop element id
+     * @param controlLoopId the controlLoop Id
+     * @param id the controlLoop UUID
      * @param orderedState the current state
      * @param newState the ordered state
      * @return controlLoopElement the updated controlloop element
@@ -160,8 +161,10 @@ public class ControlLoopHandler {
      * Handle a control loop state change message.
      *
      * @param stateChangeMsg the state change message
+     * @param clElementDefinitions the list of ControlLoopElementDefinition
      */
-    public void handleControlLoopStateChange(ControlLoopStateChange stateChangeMsg) {
+    public void handleControlLoopStateChange(ControlLoopStateChange stateChangeMsg,
+            List<ControlLoopElementDefinition> clElementDefinitions) {
         if (stateChangeMsg.getControlLoopId() == null) {
             return;
         }
@@ -182,7 +185,8 @@ public class ControlLoopHandler {
             return;
         }
 
-        handleState(controlLoop, stateChangeMsg.getOrderedState());
+        handleState(controlLoop, stateChangeMsg.getOrderedState(), stateChangeMsg.getStartPhase(),
+                clElementDefinitions);
     }
 
     /**
@@ -190,17 +194,20 @@ public class ControlLoopHandler {
      *
      * @param controlLoop participant response
      * @param orderedState controlloop ordered state
+     * @param startPhaseMsg startPhase from message
+     * @param clElementDefinitions the list of ControlLoopElementDefinition
      */
-    private void handleState(final ControlLoop controlLoop, ControlLoopOrderedState orderedState) {
+    private void handleState(final ControlLoop controlLoop, ControlLoopOrderedState orderedState, Integer startPhaseMsg,
+            List<ControlLoopElementDefinition> clElementDefinitions) {
         switch (orderedState) {
             case UNINITIALISED:
-                handleUninitialisedState(controlLoop, orderedState);
+                handleUninitialisedState(controlLoop, orderedState, startPhaseMsg, clElementDefinitions);
                 break;
             case PASSIVE:
-                handlePassiveState(controlLoop, orderedState);
+                handlePassiveState(controlLoop, orderedState, startPhaseMsg, clElementDefinitions);
                 break;
             case RUNNING:
-                handleRunningState(controlLoop, orderedState);
+                handleRunningState(controlLoop, orderedState, startPhaseMsg, clElementDefinitions);
                 break;
             default:
                 LOGGER.debug("StateChange message has no state, state is null {}", controlLoop.getDefinition());
@@ -212,6 +219,7 @@ public class ControlLoopHandler {
      * Handle a control loop update message.
      *
      * @param updateMsg the update message
+     * @param clElementDefinitions the list of ControlLoopElementDefinition
      */
     public void handleControlLoopUpdate(ControlLoopUpdate updateMsg,
             List<ControlLoopElementDefinition> clElementDefinitions) {
@@ -300,8 +308,7 @@ public class ControlLoopHandler {
             ToscaConceptIdentifier clElementDefId) {
 
         for (var clElementDefinition : clElementDefinitions) {
-            if (clElementDefId.getName().contains(
-                clElementDefinition.getClElementDefinitionId().getName())) {
+            if (clElementDefId.getName().contains(clElementDefinition.getClElementDefinitionId().getName())) {
                 return clElementDefinition.getControlLoopElementToscaNodeTemplate();
             }
         }
@@ -332,11 +339,18 @@ public class ControlLoopHandler {
      *
      * @param controlLoop participant response
      * @param orderedState orderedState
+     * @param startPhaseMsg startPhase from message
+     * @param clElementDefinitions the list of ControlLoopElementDefinition
      */
-    private void handleUninitialisedState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState) {
-        handleStateChange(controlLoop, orderedState);
-        controlLoopMap.remove(controlLoop.getDefinition());
-        controlLoop.getElements().values().forEach(element -> elementsOnThisParticipant.remove(element.getId()));
+    private void handleUninitialisedState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
+            Integer startPhaseMsg, List<ControlLoopElementDefinition> clElementDefinitions) {
+        handleStateChange(controlLoop, orderedState, startPhaseMsg, clElementDefinitions);
+        boolean isAllUninitialised = controlLoop.getElements().values().stream()
+                .filter(element -> !ControlLoopState.UNINITIALISED.equals(element.getState())).findAny().isEmpty();
+        if (isAllUninitialised) {
+            controlLoopMap.remove(controlLoop.getDefinition());
+            controlLoop.getElements().values().forEach(element -> elementsOnThisParticipant.remove(element.getId()));
+        }
     }
 
     /**
@@ -344,9 +358,12 @@ public class ControlLoopHandler {
      *
      * @param controlLoop participant response
      * @param orderedState orderedState
+     * @param startPhaseMsg startPhase from message
+     * @param clElementDefinitions the list of ControlLoopElementDefinition
      */
-    private void handlePassiveState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState) {
-        handleStateChange(controlLoop, orderedState);
+    private void handlePassiveState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
+            Integer startPhaseMsg, List<ControlLoopElementDefinition> clElementDefinitions) {
+        handleStateChange(controlLoop, orderedState, startPhaseMsg, clElementDefinitions);
     }
 
     /**
@@ -354,9 +371,12 @@ public class ControlLoopHandler {
      *
      * @param controlLoop participant response
      * @param orderedState orderedState
+     * @param startPhaseMsg startPhase from message
+     * @param clElementDefinitions the list of ControlLoopElementDefinition
      */
-    private void handleRunningState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState) {
-        handleStateChange(controlLoop, orderedState);
+    private void handleRunningState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
+            Integer startPhaseMsg, List<ControlLoopElementDefinition> clElementDefinitions) {
+        handleStateChange(controlLoop, orderedState, startPhaseMsg, clElementDefinitions);
     }
 
     /**
@@ -364,8 +384,11 @@ public class ControlLoopHandler {
      *
      * @param controlLoop participant status in memory
      * @param orderedState orderedState the new ordered state the participant should have
+     * @param startPhaseMsg startPhase from message
+     * @param clElementDefinitions the list of ControlLoopElementDefinition
      */
-    private void handleStateChange(ControlLoop controlLoop, final ControlLoopOrderedState orderedState) {
+    private void handleStateChange(ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
+            Integer startPhaseMsg, List<ControlLoopElementDefinition> clElementDefinitions) {
 
         if (orderedState.equals(controlLoop.getOrderedState())) {
             var controlLoopAck = new ControlLoopAck(ParticipantMessageType.CONTROLLOOP_STATECHANGE_ACK);
@@ -378,16 +401,27 @@ public class ControlLoopHandler {
             return;
         }
 
-        controlLoop.getElements().values().stream().forEach(clElement -> {
-            for (var clElementListener : listeners) {
-                try {
-                    clElementListener.controlLoopElementStateChange(controlLoop.getDefinition(), clElement.getId(),
-                            clElement.getState(), orderedState);
-                } catch (PfModelException e) {
-                    LOGGER.debug("Control loop element update failed {}", controlLoop.getDefinition());
+        controlLoop.getElements().values().stream().forEach(clElement -> controlLoopElementStateChange(controlLoop,
+                orderedState, clElement, startPhaseMsg, clElementDefinitions));
+    }
+
+    private void controlLoopElementStateChange(ControlLoop controlLoop, ControlLoopOrderedState orderedState,
+            ControlLoopElement clElement, Integer startPhaseMsg,
+            List<ControlLoopElementDefinition> clElementDefinitions) {
+        var clElementNodeTemplate = getClElementNodeTemplate(clElementDefinitions, clElement.getDefinition());
+        if (clElementNodeTemplate != null) {
+            int startPhase = ParticipantUtils.findStartPhase(clElementNodeTemplate.getProperties());
+            if (startPhaseMsg.equals(startPhase)) {
+                for (var clElementListener : listeners) {
+                    try {
+                        clElementListener.controlLoopElementStateChange(controlLoop.getDefinition(), clElement.getId(),
+                                clElement.getState(), orderedState);
+                    } catch (PfModelException e) {
+                        LOGGER.debug("Control loop element update failed {}", controlLoop.getDefinition());
+                    }
                 }
             }
-        });
+        }
     }
 
     /**
index 0734cb9..d7537e3 100644 (file)
@@ -156,7 +156,7 @@ public class ParticipantHandler {
      * @param stateChangeMsg the state change message
      */
     public void handleControlLoopStateChange(ControlLoopStateChange stateChangeMsg) {
-        controlLoopHandler.handleControlLoopStateChange(stateChangeMsg);
+        controlLoopHandler.handleControlLoopStateChange(stateChangeMsg, clElementDefsOnThisParticipant);
     }
 
     private void handleStateChange(ParticipantState newParticipantState, ParticipantUpdateAck response) {
index 960cb43..2a1f908 100644 (file)
@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
 import lombok.AllArgsConstructor;
 import org.apache.commons.collections4.CollectionUtils;
 import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException;
@@ -36,6 +37,7 @@ import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantHealthStatus;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantState;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantUtils;
 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider;
 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopAck;
@@ -51,7 +53,10 @@ import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantDer
 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantRegisterAckPublisher;
 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantUpdatePublisher;
 import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.base.PfModelRuntimeException;
+import org.onap.policy.models.provider.PolicyModelsProvider;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
@@ -75,6 +80,7 @@ public class SupervisionHandler {
     private final ControlLoopProvider controlLoopProvider;
     private final ParticipantProvider participantProvider;
     private final MonitoringProvider monitoringProvider;
+    private final PolicyModelsProvider modelsProvider;
 
     // Publishers for participant communication
     private final ControlLoopUpdatePublisher controlLoopUpdatePublisher;
@@ -350,7 +356,7 @@ public class SupervisionHandler {
             case UNINITIALISED2PASSIVE:
             case PASSIVE:
                 controlLoop.setState(ControlLoopState.PASSIVE2UNINITIALISED);
-                controlLoopStateChangePublisher.send(controlLoop);
+                controlLoopStateChangePublisher.send(controlLoop, getFirstStartPhase(controlLoop));
                 break;
 
             case PASSIVE2UNINITIALISED:
@@ -384,7 +390,7 @@ public class SupervisionHandler {
 
             case RUNNING:
                 controlLoop.setState(ControlLoopState.RUNNING2PASSIVE);
-                controlLoopStateChangePublisher.send(controlLoop);
+                controlLoopStateChangePublisher.send(controlLoop, getFirstStartPhase(controlLoop));
                 break;
 
             default:
@@ -408,7 +414,7 @@ public class SupervisionHandler {
 
             case PASSIVE:
                 controlLoop.setState(ControlLoopState.PASSIVE2RUNNING);
-                controlLoopStateChangePublisher.send(controlLoop);
+                controlLoopStateChangePublisher.send(controlLoop, getFirstStartPhase(controlLoop));
                 break;
 
             default:
@@ -418,6 +424,16 @@ public class SupervisionHandler {
         }
     }
 
+    private int getFirstStartPhase(ControlLoop controlLoop) {
+        ToscaServiceTemplate toscaServiceTemplate = null;
+        try {
+            toscaServiceTemplate = modelsProvider.getServiceTemplateList(null, null).get(0);
+        } catch (PfModelException e) {
+            throw new PfModelRuntimeException(Status.BAD_REQUEST, "Canont load ToscaServiceTemplate from DB", e);
+        }
+        return ParticipantUtils.getFirstStartPhase(controlLoop, toscaServiceTemplate);
+    }
+
     private void checkParticipant(ParticipantMessage participantMessage, ParticipantState participantState,
             ParticipantHealthStatus healthStatus) throws ControlLoopException, PfModelException {
         if (participantMessage.getParticipantId() == null) {
index 5147aa2..48e0601 100644 (file)
@@ -220,13 +220,19 @@ public class SupervisionScanner {
 
         var completed = true;
         var minSpNotCompleted = 1000; // min startPhase not completed
+        var maxSpNotCompleted = 0; // max startPhase not completed
+        var defaultMin = 1000; // min startPhase
+        var defaultMax = 0; // max startPhase
         for (ControlLoopElement element : controlLoop.getElements().values()) {
+            ToscaNodeTemplate toscaNodeTemplate = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates()
+                    .get(element.getDefinition().getName());
+            int startPhase = ParticipantUtils.findStartPhase(toscaNodeTemplate.getProperties());
+            defaultMin = Math.min(defaultMin, startPhase);
+            defaultMax = Math.max(defaultMax, startPhase);
             if (!element.getState().equals(element.getOrderedState().asState())) {
                 completed = false;
-                ToscaNodeTemplate toscaNodeTemplate = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates()
-                        .get(element.getDefinition().getName());
-                int startPhase = ParticipantUtils.findStartPhase(toscaNodeTemplate.getProperties());
                 minSpNotCompleted = Math.min(minSpNotCompleted, startPhase);
+                maxSpNotCompleted = Math.max(maxSpNotCompleted, startPhase);
             }
         }
 
@@ -243,12 +249,20 @@ public class SupervisionScanner {
             LOGGER.debug("control loop scan: transition from state {} to {} not completed", controlLoop.getState(),
                     controlLoop.getOrderedState());
 
-            if (minSpNotCompleted != phaseMap.getOrDefault(controlLoop.getKey().asIdentifier(), 0)
-                    && ControlLoopState.UNINITIALISED2PASSIVE.equals(controlLoop.getState())) {
-                phaseMap.put(controlLoop.getKey().asIdentifier(), minSpNotCompleted);
-                sendControlLoopMsg(controlLoop, minSpNotCompleted);
+            var nextSpNotCompleted = ControlLoopState.UNINITIALISED2PASSIVE.equals(controlLoop.getState())
+                    || ControlLoopState.PASSIVE2RUNNING.equals(controlLoop.getState()) ? minSpNotCompleted
+                            : maxSpNotCompleted;
+
+            var firstStartPhase = ControlLoopState.UNINITIALISED2PASSIVE.equals(controlLoop.getState())
+                    || ControlLoopState.PASSIVE2RUNNING.equals(controlLoop.getState()) ? defaultMin
+                            : defaultMax;
+
+            if (nextSpNotCompleted != phaseMap.getOrDefault(controlLoop.getKey().asIdentifier(), firstStartPhase)) {
+                phaseMap.put(controlLoop.getKey().asIdentifier(), nextSpNotCompleted);
+                sendControlLoopMsg(controlLoop, nextSpNotCompleted);
             } else if (counterCheck) {
-                handleCounter(controlLoop, minSpNotCompleted);
+                phaseMap.put(controlLoop.getKey().asIdentifier(), nextSpNotCompleted);
+                handleCounter(controlLoop, nextSpNotCompleted);
             }
         }
     }
@@ -282,7 +296,7 @@ public class SupervisionScanner {
             controlLoopUpdatePublisher.send(controlLoop, startPhase);
         } else {
             LOGGER.debug("retry message ControlLoopStateChange");
-            controlLoopStateChangePublisher.send(controlLoop);
+            controlLoopStateChangePublisher.send(controlLoop, startPhase);
         }
     }
 }
index 79d113c..69d7b73 100644 (file)
@@ -36,12 +36,14 @@ public class ControlLoopStateChangePublisher
      * Send ControlLoopStateChange to Participant.
      *
      * @param controlLoop the ControlLoop
+     * @param startPhase the startPhase
      */
-    public void send(ControlLoop controlLoop) {
+    public void send(ControlLoop controlLoop, int startPhase) {
         var clsc = new ControlLoopStateChange();
         clsc.setControlLoopId(controlLoop.getKey().asIdentifier());
         clsc.setMessageId(UUID.randomUUID());
         clsc.setOrderedState(controlLoop.getOrderedState());
+        clsc.setStartPhase(startPhase);
 
         super.send(clsc);
     }
index 82f7e66..d8892c8 100644 (file)
@@ -133,7 +133,9 @@ class ControlLoopInstantiationProviderTest {
         var participantRegisterAckPublisher = Mockito.mock(ParticipantRegisterAckPublisher.class);
         var participantDeregisterAckPublisher = Mockito.mock(ParticipantDeregisterAckPublisher.class);
         var participantUpdatePublisher = Mockito.mock(ParticipantUpdatePublisher.class);
-        supervisionHandler = new SupervisionHandler(clProvider, participantProvider, monitoringProvider,
+        var modelsProvider = Mockito.mock(PolicyModelsProvider.class);
+
+        supervisionHandler = new SupervisionHandler(clProvider, participantProvider, monitoringProvider, modelsProvider,
                 controlLoopUpdatePublisher, controlLoopStateChangePublisher, participantRegisterAckPublisher,
                 participantDeregisterAckPublisher, participantUpdatePublisher);
     }
index 0ad8aad..0fcf52a 100644 (file)
@@ -32,6 +32,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
 import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState;
@@ -56,9 +57,12 @@ import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantReg
 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantUpdatePublisher;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.provider.PolicyModelsProvider;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 
 class SupervisionHandlerTest {
+    private static final String TOSCA_TEMPLATE_YAML =
+            "src/test/resources/rest/servicetemplates/tosca-for-smoke-testing.yaml";
     private static final String CL_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/controlloops/ControlLoops.json";
     private static final ToscaConceptIdentifier identifier = new ToscaConceptIdentifier("PMSHInstance0Crud", "1.0.1");
     private static final ToscaConceptIdentifier participantId = new ToscaConceptIdentifier("ParticipantId", "1.0.0");
@@ -262,7 +266,11 @@ class SupervisionHandlerTest {
 
         when(controlLoopProvider.getControlLoop(eq(identifier))).thenReturn(controlLoop);
 
-        return new SupervisionHandler(controlLoopProvider, participantProvider, monitoringProvider,
+        var modelsProvider = Mockito.mock(PolicyModelsProvider.class);
+        when(modelsProvider.getServiceTemplateList(any(), any()))
+                .thenReturn(List.of(InstantiationUtils.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML)));
+
+        return new SupervisionHandler(controlLoopProvider, participantProvider, monitoringProvider, modelsProvider,
                 controlLoopUpdatePublisher, controlLoopStateChangePublisher, participantRegisterAckPublisher,
                 participantDeregisterAckPublisher, participantUpdatePublisher);
 
index 47cc6f1..f884e01 100644 (file)
@@ -29,11 +29,9 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.util.List;
-import java.util.Map;
-import java.util.UUID;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
-import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant;
@@ -47,6 +45,7 @@ import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopUpd
 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantStatusReqPublisher;
 import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantUpdatePublisher;
 import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData;
+import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.models.base.PfModelException;
 import org.onap.policy.models.provider.PolicyModelsProvider;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
@@ -56,11 +55,19 @@ class SupervisionScannerTest {
 
     private static final String TOSCA_SERVICE_TEMPLATE_YAML =
             "src/test/resources/rest/servicetemplates/tosca-for-smoke-testing.yaml";
+    private static final String CONTROLLOOP_JSON = "src/test/resources/rest/controlloops/ControlLoopsSmoke.json";
+
+    private static PolicyModelsProvider modelsProvider = mock(PolicyModelsProvider.class);
+
+    @BeforeAll
+    public static void setUpBeforeAll() throws Exception {
+        ToscaServiceTemplate serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
+        when(modelsProvider.getServiceTemplateList(null, null)).thenReturn(List.of(serviceTemplate));
+    }
 
     @Test
-    void testScannerOrderedStateEqualsToState() throws PfModelException {
+    void testScannerOrderedStateEqualsToState() throws PfModelException, CoderException {
         var controlLoopProvider = mock(ControlLoopProvider.class);
-        var modelsProvider = mock(PolicyModelsProvider.class);
         var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class);
         var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class);
         var participantProvider = mock(ParticipantProvider.class);
@@ -68,8 +75,9 @@ class SupervisionScannerTest {
         var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class);
         var clRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
 
-        var controlLoop = new ControlLoop();
-        when(controlLoopProvider.getControlLoops(null, null)).thenReturn(List.of(controlLoop));
+        var controlLoops =
+                InstantiationUtils.getControlLoopsFromResource(CONTROLLOOP_JSON, "Crud").getControlLoopList();
+        when(controlLoopProvider.getControlLoops(null, null)).thenReturn(controlLoops);
 
         var supervisionScanner = new SupervisionScanner(controlLoopProvider, modelsProvider,
                 controlLoopStateChangePublisher, controlLoopUpdatePublisher, participantProvider,
@@ -80,13 +88,13 @@ class SupervisionScannerTest {
     }
 
     @Test
-    void testScannerOrderedStateDifferentToState() throws PfModelException {
-        var controlLoop = new ControlLoop();
-        controlLoop.setState(ControlLoopState.UNINITIALISED2PASSIVE);
-        controlLoop.setOrderedState(ControlLoopOrderedState.UNINITIALISED);
-        controlLoop.setElements(Map.of(UUID.randomUUID(), new ControlLoopElement()));
+    void testScannerOrderedStateDifferentToState() throws PfModelException, CoderException {
+        var controlLoops =
+                InstantiationUtils.getControlLoopsFromResource(CONTROLLOOP_JSON, "Crud").getControlLoopList();
+        controlLoops.get(0).setState(ControlLoopState.UNINITIALISED2PASSIVE);
+        controlLoops.get(0).setOrderedState(ControlLoopOrderedState.UNINITIALISED);
         var controlLoopProvider = mock(ControlLoopProvider.class);
-        when(controlLoopProvider.getControlLoops(null, null)).thenReturn(List.of(controlLoop));
+        when(controlLoopProvider.getControlLoops(null, null)).thenReturn(controlLoops);
 
         var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class);
         var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class);
@@ -95,9 +103,6 @@ class SupervisionScannerTest {
         var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class);
         var clRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
 
-        var modelsProvider = mock(PolicyModelsProvider.class);
-        when(modelsProvider.getServiceTemplateList(null, null)).thenReturn(List.of(new ToscaServiceTemplate()));
-
         var supervisionScanner = new SupervisionScanner(controlLoopProvider, modelsProvider,
                 controlLoopStateChangePublisher, controlLoopUpdatePublisher, participantProvider,
                 participantStatusReqPublisher, participantUpdatePublisher, clRuntimeParameterGroup);
@@ -118,7 +123,6 @@ class SupervisionScannerTest {
         participant.setVersion("1.0.0");
         when(participantProvider.getParticipants(null, null)).thenReturn(List.of(participant));
 
-        var modelsProvider = mock(PolicyModelsProvider.class);
         var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class);
         var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class);
         var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class);
@@ -136,19 +140,24 @@ class SupervisionScannerTest {
     }
 
     @Test
-    void testSendControlLoopMsgUpdate() throws PfModelException {
-        var controlLoop = new ControlLoop();
-        controlLoop.setState(ControlLoopState.UNINITIALISED2PASSIVE);
-        controlLoop.setOrderedState(ControlLoopOrderedState.PASSIVE);
-        controlLoop.setElements(Map.of(UUID.randomUUID(),
-                createHttpElement(ControlLoopState.UNINITIALISED, ControlLoopOrderedState.PASSIVE)));
+    void testSendControlLoopMsgUpdate() throws PfModelException, CoderException {
+        var controlLoops =
+                InstantiationUtils.getControlLoopsFromResource(CONTROLLOOP_JSON, "Crud").getControlLoopList();
+        controlLoops.get(0).setState(ControlLoopState.UNINITIALISED2PASSIVE);
+        controlLoops.get(0).setOrderedState(ControlLoopOrderedState.PASSIVE);
+        for (var element : controlLoops.get(0).getElements().values()) {
+            if ("org.onap.domain.database.Http_PMSHMicroserviceControlLoopElement"
+                    .equals(element.getDefinition().getName())) {
+                element.setOrderedState(ControlLoopOrderedState.PASSIVE);
+                element.setState(ControlLoopState.UNINITIALISED);
+            } else {
+                element.setOrderedState(ControlLoopOrderedState.PASSIVE);
+                element.setState(ControlLoopState.PASSIVE);
+            }
+        }
 
         var controlLoopProvider = mock(ControlLoopProvider.class);
-        when(controlLoopProvider.getControlLoops(null, null)).thenReturn(List.of(controlLoop));
-
-        ToscaServiceTemplate serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
-        var modelsProvider = mock(PolicyModelsProvider.class);
-        when(modelsProvider.getServiceTemplateList(null, null)).thenReturn(List.of(serviceTemplate));
+        when(controlLoopProvider.getControlLoops(null, null)).thenReturn(controlLoops);
 
         var participantProvider = mock(ParticipantProvider.class);
         var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class);
@@ -166,19 +175,6 @@ class SupervisionScannerTest {
         verify(controlLoopUpdatePublisher).send(any(ControlLoop.class), anyInt());
     }
 
-    private ControlLoopElement createHttpElement(ControlLoopState state, ControlLoopOrderedState orderedState) {
-        var element = new ControlLoopElement();
-        element.setDefinition(new ToscaConceptIdentifier(
-                "org.onap.domain.database.Http_PMSHMicroserviceControlLoopElement", "1.2.3"));
-        element.setState(state);
-        element.setOrderedState(orderedState);
-        element.setParticipantId(new ToscaConceptIdentifier("HttpParticipant0", "1.0.0"));
-        element.setParticipantType(
-                new ToscaConceptIdentifier("org.onap.k8s.controlloop.HttpControlLoopParticipant", "2.3.4"));
-
-        return element;
-    }
-
     @Test
     void testScanParticipant() throws PfModelException {
         var controlLoopProvider = mock(ControlLoopProvider.class);
@@ -199,7 +195,6 @@ class SupervisionScannerTest {
         var participantProvider = new ParticipantProvider(clRuntimeParameterGroup.getDatabaseProviderParameters());
         participantProvider.updateParticipants(List.of(participant));
 
-        var modelsProvider = mock(PolicyModelsProvider.class);
         var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class);
         var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class);
         var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class);
index 70d115e..4dfb8a9 100644 (file)
 package org.onap.policy.clamp.controlloop.runtime.supervision.comm;
 
 import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 
 import java.time.Instant;
 import java.util.Collections;
+import java.util.List;
 import java.util.UUID;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ClElementStatisticsProvider;
 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
 import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider;
@@ -51,6 +58,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 
 class SupervisionMessagesTest extends CommonRestController {
 
+    private static final String NOT_ACTIVE = "Not Active!";
     private static final Object lockit = new Object();
     private static final CommInfrastructure INFRA = CommInfrastructure.NOOP;
     private static final String TOPIC = "my-topic";
@@ -77,12 +85,13 @@ class SupervisionMessagesTest extends CommonRestController {
         var monitoringProvider =
                 new MonitoringProvider(participantStatisticsProvider, clElementStatisticsProvider, clProvider);
         var participantProvider = new ParticipantProvider(controlLoopParameters.getDatabaseProviderParameters());
+        var modelsProvider = Mockito.mock(PolicyModelsProvider.class);
         var controlLoopUpdatePublisher = Mockito.mock(ControlLoopUpdatePublisher.class);
         var controlLoopStateChangePublisher = Mockito.mock(ControlLoopStateChangePublisher.class);
         var participantRegisterAckPublisher = Mockito.mock(ParticipantRegisterAckPublisher.class);
         var participantDeregisterAckPublisher = Mockito.mock(ParticipantDeregisterAckPublisher.class);
         var participantUpdatePublisher = Mockito.mock(ParticipantUpdatePublisher.class);
-        supervisionHandler = new SupervisionHandler(clProvider, participantProvider, monitoringProvider,
+        supervisionHandler = new SupervisionHandler(clProvider, participantProvider, monitoringProvider, modelsProvider,
                 controlLoopUpdatePublisher, controlLoopStateChangePublisher, participantRegisterAckPublisher,
                 participantDeregisterAckPublisher, participantUpdatePublisher);
     }
@@ -154,6 +163,29 @@ class SupervisionMessagesTest extends CommonRestController {
         }
     }
 
+    @Test
+    void testSendControlLoopStateChangePublisherNotActive() {
+        var publisher = new ControlLoopStateChangePublisher();
+        assertThatThrownBy(() -> publisher.send(getControlLoop(), 0)).hasMessage(NOT_ACTIVE);
+    }
+
+    @Test
+    void testSendControlLoopStateChangePublisher() {
+        var publisher = new ControlLoopStateChangePublisher();
+        var topicSink = mock(TopicSink.class);
+        publisher.active(List.of(topicSink));
+        publisher.send(getControlLoop(), 0);
+        verify(topicSink).send(anyString());
+    }
+
+    private ControlLoop getControlLoop() {
+        var controlLoop = new ControlLoop();
+        controlLoop.setName("NAME");
+        controlLoop.setVersion("0.0.1");
+        controlLoop.setState(ControlLoopState.UNINITIALISED);
+        return controlLoop;
+    }
+
     private ToscaConceptIdentifier getParticipantId() {
         return new ToscaConceptIdentifier("org.onap.PM_Policy", "1.0.0");
     }
diff --git a/runtime-controlloop/src/test/resources/rest/controlloops/ControlLoopsSmoke.json b/runtime-controlloop/src/test/resources/rest/controlloops/ControlLoopsSmoke.json
new file mode 100644 (file)
index 0000000..47f379b
--- /dev/null
@@ -0,0 +1,174 @@
+{
+    "controlLoopList": [
+        {
+            "name": "PMSHInstance0",
+            "version": "1.0.1",
+            "definition": {
+                "name": "org.onap.domain.pmsh.PMSHControlLoopDefinition",
+                "version": "1.2.3"
+            },
+            "state": "UNINITIALISED",
+            "orderedState": "UNINITIALISED",
+            "description": "PMSH control loop instance 0",
+            "elements": {
+                "709c62b3-8918-41b9-a747-d21eb79c6c20": {
+                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c20",
+                    "definition": {
+                        "name": "org.onap.domain.database.Http_PMSHMicroserviceControlLoopElement",
+                        "version": "1.2.3"
+                    },
+                    "participantId": {
+                        "name": "org.onap.dcae.controlloop.DCAEMicroserviceControlLoopParticipant",
+                        "version": "2.3.4"
+                    },
+                    "participantType": {
+                        "name": "org.onap.dcae.controlloop.DCAEMicroserviceControlLoopParticipant",
+                        "version": "2.3.4"
+                    },
+                    "state": "UNINITIALISED",
+                    "orderedState": "UNINITIALISED",
+                    "description": "DCAE Control Loop Element for the PMSH instance 0 control loop"
+                },
+                "709c62b3-8918-41b9-a747-d21eb79c6c21": {
+                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c21",
+                    "definition": {
+                        "name": "org.onap.domain.pmsh.PMSH_MonitoringPolicyControlLoopElement",
+                        "version": "1.2.3"
+                    },
+                    "participantId": {
+                        "name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
+                        "version": "2.3.1"
+                    },
+                    "participantType": {
+                        "name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
+                        "version": "2.3.1"
+                    },
+                    "state": "UNINITIALISED",
+                    "orderedState": "UNINITIALISED",
+                    "description": "Monitoring Policy Control Loop Element for the PMSH instance 0 control loop"
+                },
+                "709c62b3-8918-41b9-a747-d21eb79c6c22": {
+                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c22",
+                    "definition": {
+                        "name": "org.onap.domain.pmsh.PMSH_OperationalPolicyControlLoopElement",
+                        "version": "1.2.3"
+                    },
+                    "participantId": {
+                        "name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
+                        "version": "2.3.1"
+                    },
+                    "participantType": {
+                        "name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
+                        "version": "2.3.1"
+                    },
+                    "state": "UNINITIALISED",
+                    "orderedState": "UNINITIALISED",
+                    "description": "Operational Policy Control Loop Element for the PMSH instance 0 control loop"
+                },
+                "709c62b3-8918-41b9-a747-d21eb79c6c23": {
+                    "id": "709c62b3-8918-41b9-a747-d21eb79c6c23",
+                    "definition": {
+                        "name": "org.onap.domain.database.PMSH_K8SMicroserviceControlLoopElement",
+                        "version": "1.2.3"
+                    },
+                    "participantId": {
+                        "name": "org.onap.ccsdk.cds.controlloop.CdsControlLoopParticipant",
+                        "version": "2.2.1"
+                    },
+                    "participantType": {
+                        "name": "org.onap.ccsdk.cds.controlloop.CdsControlLoopParticipant",
+                        "version": "2.2.1"
+                    },
+                    "state": "UNINITIALISED",
+                    "orderedState": "UNINITIALISED",
+                    "description": "CDS Control Loop Element for the PMSH instance 0 control loop"
+                }
+            }
+        },
+        {
+            "name": "PMSHInstance1",
+            "version": "1.0.1",
+            "definition": {
+                "name": "org.onap.domain.pmsh.PMSHControlLoopDefinition",
+                "version": "1.2.3"
+            },
+            "state": "UNINITIALISED",
+            "orderedState": "UNINITIALISED",
+            "description": "PMSH control loop instance 1",
+            "elements": {
+                "709c62b3-8918-41b9-a747-d21eb79c6c24": {
+                    "id": "709c62b3-8918-41b9-a747-e21eb79c6c24",
+                    "definition": {
+                        "name": "org.onap.domain.pmsh.PMSH_DCAEMicroservice",
+                        "version": "1.2.3"
+                    },
+                    "participantId": {
+                        "name": "org.onap.dcae.controlloop.DCAEMicroserviceControlLoopParticipant",
+                        "version": "2.3.4"
+                    },
+                    "participantType": {
+                        "name": "org.onap.dcae.controlloop.DCAEMicroserviceControlLoopParticipant",
+                        "version": "2.3.4"
+                    },
+                    "state": "UNINITIALISED",
+                    "orderedState": "UNINITIALISED",
+                    "description": "DCAE Control Loop Element for the PMSH instance 1 control loop"
+                },
+                "709c62b3-8918-41b9-a747-d21eb79c6c25": {
+                    "id": "709c62b3-8918-41b9-a747-e21eb79c6c25",
+                    "definition": {
+                        "name": "org.onap.domain.pmsh.PMSH_MonitoringPolicyControlLoopElement",
+                        "version": "1.2.3"
+                    },
+                    "participantId": {
+                        "name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
+                        "version": "2.3.1"
+                    },
+                    "participantType": {
+                        "name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
+                        "version": "2.3.1"
+                    },
+                    "state": "UNINITIALISED",
+                    "orderedState": "UNINITIALISED",
+                    "description": "Monitoring Policy Control Loop Element for the PMSH instance 1 control loop"
+                },
+                "709c62b3-8918-41b9-a747-d21eb79c6c26": {
+                    "id": "709c62b3-8918-41b9-a747-e21eb79c6c26",
+                    "definition": {
+                        "name": "org.onap.domain.pmsh.PMSH_OperationalPolicyControlLoopElement",
+                        "version": "1.2.3"
+                    },
+                    "participantId": {
+                        "name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
+                        "version": "2.3.1"
+                    },
+                    "participantType": {
+                        "name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
+                        "version": "2.3.1"
+                    },
+                    "state": "UNINITIALISED",
+                    "orderedState": "UNINITIALISED",
+                    "description": "Operational Policy Control Loop Element for the PMSH instance 1 control loop"
+                },
+                "709c62b3-8918-41b9-a747-d21eb79c6c27": {
+                    "id": "709c62b3-8918-41b9-a747-e21eb79c6c27",
+                    "definition": {
+                        "name": "org.onap.domain.pmsh.PMSH_CDS_ControlLoopElement",
+                        "version": "1.2.3"
+                    },
+                    "participantId": {
+                        "name": "org.onap.ccsdk.cds.controlloop.CdsControlLoopParticipant",
+                        "version": "2.2.1"
+                    },
+                    "participantType": {
+                        "name": "org.onap.ccsdk.cds.controlloop.CdsControlLoopParticipant",
+                        "version": "2.2.1"
+                    },
+                    "state": "UNINITIALISED",
+                    "orderedState": "UNINITIALISED",
+                    "description": "CDS Control Loop Element for the PMSH instance 1 control loop"
+                }
+            }
+        }
+    ]
+}