Fix parsing of type heirarchy for nodetypes 97/123897/2
authorSirisha_Manchikanti <sirisha.manchikanti@est.tech>
Mon, 6 Sep 2021 08:15:07 +0000 (09:15 +0100)
committerSirisha_Manchikanti <sirisha.manchikanti@est.tech>
Tue, 7 Sep 2021 16:47:12 +0000 (17:47 +0100)
Fixed an issue where a ControlLoopElement with type defined in
node-types is not parsed. This commit also includes changes to save
the state of a controlLoopElement coming from ControlLoopAck message
into runtime database.

Issue-ID: POLICY-3575
Signed-off-by: Sirisha_Manchikanti <sirisha.manchikanti@est.tech>
Change-Id: I1249cf2cabd4a499d80b401f94f7f42f08b350e3

24 files changed:
models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ControlLoopElementAck.java
models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantAckMessage.java
models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ControlLoopAckTest.java
participant/participant-impl/participant-impl-dcae/src/main/java/org/onap/policy/clamp/controlloop/participant/dcae/main/handler/ControlLoopElementHandler.java
participant/participant-impl/participant-impl-dcae/src/test/java/org/onap/policy/clamp/controlloop/participant/dcae/main/handler/ControlLoopElementHandlerTest.java
participant/participant-impl/participant-impl-dcae/src/test/java/org/onap/policy/clamp/controlloop/participant/dcae/main/rest/TestListenerUtils.java
participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/handler/ControlLoopElementHandler.java
participant/participant-impl/participant-impl-http/src/test/java/handler/ClElementHandlerTest.java
participant/participant-impl/participant-impl-http/src/test/java/utils/CommonTestData.java
participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/controlloop/participant/kubernetes/handler/ControlLoopElementHandler.java
participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/controlloop/participant/kubernetes/handler/ControlLoopElementHandlerTest.java
participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/controlloop/participant/kubernetes/parameters/CommonTestData.java
participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/controlloop/participant/policy/main/handler/ControlLoopElementHandler.java
participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/utils/TestListenerUtils.java
participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/controlloop/participant/simulator/simulation/SimulationProvider.java
participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/controlloop/participant/simulator/main/rest/TestListenerUtils.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/api/ControlLoopElementListener.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/api/ParticipantIntermediaryApi.java
participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java
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/comm/ParticipantUpdatePublisher.java
runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/SupervisionMessagesTest.java

index a5918fe..61b90c9 100644 (file)
@@ -31,10 +31,12 @@ import lombok.ToString;
 @ToString
 public class ControlLoopElementAck {
 
+    // State of the controlLoopElement
+    private ControlLoopState state;
+
     // Result: Success/Fail.
     private Boolean result;
 
     // Message indicating reason for failure
     private String message;
-
 }
index c6f5c61..8a1be69 100644 (file)
@@ -25,6 +25,7 @@ import lombok.Getter;
 import lombok.NonNull;
 import lombok.Setter;
 import lombok.ToString;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantState;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 
 /**
@@ -56,6 +57,11 @@ public class ParticipantAckMessage {
      */
     private ToscaConceptIdentifier participantId;
 
+    /**
+     * Participant State, or {@code null} for messages from participants.
+     */
+    private ParticipantState state;
+
     /**
      * Constructor for instantiating a participant ack message class.
      *
@@ -77,6 +83,7 @@ public class ParticipantAckMessage {
         this.messageType = source.messageType;
         this.participantType = source.participantType;
         this.participantId = source.participantId;
+        this.state = source.state;
     }
 
     /**
index 5fded73..f312c48 100644 (file)
@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.UUID;
 import org.junit.jupiter.api.Test;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElementAck;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 
@@ -50,7 +51,8 @@ class ControlLoopAckTest {
         orig.setControlLoopId(id);
         orig.setParticipantId(id);
         orig.setParticipantType(id);
-        var clElementResult = new ControlLoopElementAck(true, "ControlLoopElement result");
+        var clElementResult = new ControlLoopElementAck(ControlLoopState.UNINITIALISED,
+            true, "ControlLoopElement result");
         final var controlLoopResultMap = Map.of(UUID.randomUUID(), clElementResult);
         orig.setControlLoopResultMap(controlLoopResultMap);
 
index 221635d..ca763f1 100644 (file)
@@ -39,6 +39,7 @@ import org.onap.policy.clamp.controlloop.participant.intermediary.api.ControlLoo
 import org.onap.policy.clamp.controlloop.participant.intermediary.api.ParticipantIntermediaryApi;
 import org.onap.policy.common.utils.resources.ResourceUtils;
 import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -92,23 +93,27 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
      * @param newState the state to which the control loop element is changing to
      */
     @Override
-    public void controlLoopElementStateChange(UUID controlLoopElementId, ControlLoopState currentState,
+    public void controlLoopElementStateChange(ToscaConceptIdentifier controlLoopId,
+            UUID controlLoopElementId, ControlLoopState currentState,
             ControlLoopOrderedState newState) {
         switch (newState) {
             case UNINITIALISED:
                 var loop = clampClient.getstatus(LOOP);
                 if (loop != null) {
                     clampClient.undeploy(LOOP);
-                    intermediaryApi.updateControlLoopElementState(controlLoopElementId, newState,
+                    intermediaryApi.updateControlLoopElementState(controlLoopId,
+                            controlLoopElementId, newState,
                             ControlLoopState.UNINITIALISED, ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE);
                 }
                 break;
             case PASSIVE:
-                intermediaryApi.updateControlLoopElementState(controlLoopElementId, newState, ControlLoopState.PASSIVE,
+                intermediaryApi.updateControlLoopElementState(controlLoopId,
+                    controlLoopElementId, newState, ControlLoopState.PASSIVE,
                     ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE);
                 break;
             case RUNNING:
-                intermediaryApi.updateControlLoopElementState(controlLoopElementId, newState, ControlLoopState.RUNNING,
+                intermediaryApi.updateControlLoopElementState(controlLoopId,
+                    controlLoopElementId, newState, ControlLoopState.RUNNING,
                     ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE);
                 break;
             default:
@@ -145,8 +150,9 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
      * @throws PfModelException in case of an exception
      */
     @Override
-    public void controlLoopElementUpdate(ControlLoopElement element, ToscaNodeTemplate nodeTemplate)
-            throws PfModelException {
+    public void controlLoopElementUpdate(ToscaConceptIdentifier controlLoopId,
+            ControlLoopElement element, ToscaNodeTemplate nodeTemplate)
+             throws PfModelException {
         try {
             var loop = getStatus();
 
@@ -159,16 +165,18 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
                     loop = getStatus();
                     String status = ClampHttpClient.getStatusCode(loop);
                     if (MICROSERVICE_INSTALLED_SUCCESSFULLY.equals(status)) {
-                        intermediaryApi.updateControlLoopElementState(element.getId(), element.getOrderedState(),
-                                ControlLoopState.PASSIVE, ParticipantMessageType.CONTROL_LOOP_UPDATE);
+                        intermediaryApi.updateControlLoopElementState(controlLoopId, element.getId(),
+                            element.getOrderedState(), ControlLoopState.PASSIVE,
+                            ParticipantMessageType.CONTROL_LOOP_UPDATE);
                         deployedFlag = true;
                         break;
                     }
                 }
                 if (!deployedFlag) {
                     LOGGER.warn("DCAE is not deployed properly, ClElement state will be UNINITIALISED2PASSIVE");
-                    intermediaryApi.updateControlLoopElementState(element.getId(), element.getOrderedState(),
-                            ControlLoopState.UNINITIALISED2PASSIVE, ParticipantMessageType.CONTROL_LOOP_UPDATE);
+                    intermediaryApi.updateControlLoopElementState(controlLoopId, element.getId(),
+                        element.getOrderedState(), ControlLoopState.UNINITIALISED2PASSIVE,
+                        ParticipantMessageType.CONTROL_LOOP_UPDATE);
                 }
             }
         } catch (PfModelException e) {
index 74728a9..2d8e0ac 100644 (file)
@@ -104,7 +104,8 @@ class ControlLoopElementHandlerTest {
         controlLoopElementHandler.setIntermediaryApi(intermediaryApi);
 
         UUID controlLoopElementId = UUID.randomUUID();
-        controlLoopElementHandler.controlLoopElementStateChange(controlLoopElementId, ControlLoopState.PASSIVE,
+        controlLoopElementHandler.controlLoopElementStateChange(TestListenerUtils.getControlLoopId(),
+                controlLoopElementId, ControlLoopState.PASSIVE,
                 ControlLoopOrderedState.UNINITIALISED);
 
         verify(clampClient).undeploy(LOOP);
@@ -137,7 +138,7 @@ class ControlLoopElementHandlerTest {
         element.setOrderedState(ControlLoopOrderedState.PASSIVE);
 
         final ToscaServiceTemplate controlLoopDefinition = new ToscaServiceTemplate();
-        controlLoopElementHandler.controlLoopElementUpdate(element,
+        controlLoopElementHandler.controlLoopElementUpdate(TestListenerUtils.getControlLoopId(), element,
             controlLoopDefinition.getToscaTopologyTemplate().getNodeTemplates()
             .get("org.onap.domain.pmsh.PMSH_DCAEMicroservice"));
 
@@ -169,7 +170,7 @@ class ControlLoopElementHandlerTest {
         element.setOrderedState(ControlLoopOrderedState.PASSIVE);
 
         ToscaServiceTemplate controlLoopDefinition = new ToscaServiceTemplate();
-        controlLoopElementHandler.controlLoopElementUpdate(element,
+        controlLoopElementHandler.controlLoopElementUpdate(TestListenerUtils.getControlLoopId(), element,
                 controlLoopDefinition.getToscaTopologyTemplate().getNodeTemplates()
                 .get("org.onap.domain.pmsh.PMSH_DCAEMicroservice"));
 
index 26f9cd4..df49f7c 100644 (file)
@@ -140,7 +140,7 @@ public class TestListenerUtils {
         Map<String, ToscaNodeTemplate> nodeTemplatesMap =
                 toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates();
         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry : nodeTemplatesMap.entrySet()) {
-            if (toscaInputEntry.getValue().getType().contains(CONTROL_LOOP_ELEMENT)) {
+            if (checkIfNodeTemplateIsControlLoopElement(toscaInputEntry.getValue(), toscaServiceTemplate)) {
                 ControlLoopElement clElement = new ControlLoopElement();
                 clElement.setId(UUID.randomUUID());
                 ToscaConceptIdentifier clParticipantType;
@@ -172,6 +172,22 @@ public class TestListenerUtils {
         return clUpdateMsg;
     }
 
+    private static boolean checkIfNodeTemplateIsControlLoopElement(ToscaNodeTemplate nodeTemplate,
+            ToscaServiceTemplate toscaServiceTemplate) {
+        if (nodeTemplate.getType().contains(CONTROL_LOOP_ELEMENT)) {
+            return true;
+        } else {
+            var nodeType = toscaServiceTemplate.getNodeTypes().get(nodeTemplate.getType());
+            if (nodeType != null) {
+                var derivedFrom = nodeType.getDerivedFrom();
+                if (derivedFrom != null) {
+                    return derivedFrom.contains(CONTROL_LOOP_ELEMENT) ? true : false;
+                }
+            }
+        }
+        return false;
+    }
+
     private static void prepareParticipantUpdateForControlLoop(ControlLoopElement clElement,
         List<ParticipantUpdates> participantUpdates) {
         if (participantUpdates.isEmpty()) {
@@ -221,7 +237,7 @@ public class TestListenerUtils {
         List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>();
         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry :
             toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().entrySet()) {
-            if (toscaInputEntry.getValue().getType().contains(CONTROL_LOOP_ELEMENT)) {
+            if (checkIfNodeTemplateIsControlLoopElement(toscaInputEntry.getValue(), toscaServiceTemplate)) {
                 ToscaConceptIdentifier clParticipantType;
                 try {
                     clParticipantType = CODER.decode(
@@ -276,6 +292,10 @@ public class TestListenerUtils {
         return participantDefinition;
     }
 
+    public static ToscaConceptIdentifier getControlLoopId() {
+        return new ToscaConceptIdentifier("PMSHInstance0", "1.0.0");
+    }
+
     /**
      * Method to create a deep copy of ControlLoopUpdateMsg.
      *
index f18885f..cfe7868 100644 (file)
@@ -88,8 +88,8 @@ public class ControlLoopElementHandler implements ControlLoopElementListener, Cl
      * @throws PfModelException in case of a model exception
      */
     @Override
-    public void controlLoopElementStateChange(UUID controlLoopElementId, ControlLoopState currentState,
-                                              ControlLoopOrderedState newState) throws PfModelException {
+    public void controlLoopElementStateChange(ToscaConceptIdentifier controlLoopId, UUID controlLoopElementId,
+            ControlLoopState currentState, ControlLoopOrderedState newState) throws PfModelException {
         // Implementation not needed for http participant
     }
 
@@ -100,7 +100,8 @@ public class ControlLoopElementHandler implements ControlLoopElementListener, Cl
      * @param nodeTemplate toscaNodeTemplate
      */
     @Override
-    public void controlLoopElementUpdate(ControlLoopElement element, ToscaNodeTemplate nodeTemplate) {
+    public void controlLoopElementUpdate(ToscaConceptIdentifier controlLoopId, ControlLoopElement element,
+            ToscaNodeTemplate nodeTemplate) {
         try {
             var configRequest = CODER.convert(nodeTemplate.getProperties(), ConfigRequest.class);
             Set<ConstraintViolation<ConfigRequest>> violations = Validation.buildDefaultValidatorFactory()
index 46ed355..0de2507 100644 (file)
@@ -66,6 +66,7 @@ class ClElementHandlerTest {
             serviceTemplate.getToscaTopologyTemplate().getNodeTemplates();
 
         assertDoesNotThrow(() -> controlLoopElementHandler
-            .controlLoopElementUpdate(element, nodeTemplatesMap.get(HTTP_CONTROL_LOOP_ELEMENT)));
+            .controlLoopElementUpdate(commonTestData.getControlLoopId(), element,
+                nodeTemplatesMap.get(HTTP_CONTROL_LOOP_ELEMENT)));
     }
 }
index 84957ed..aa4f562 100644 (file)
@@ -135,6 +135,14 @@ public class CommonTestData {
         );
     }
 
+    /**
+     * Get controlloop id.
+     * @return ToscaConceptIdentifier controlLoopId
+     */
+    public ToscaConceptIdentifier getControlLoopId() {
+        return new ToscaConceptIdentifier("PMSHInstance0", "1.0.0");
+    }
+
     /**
      * Get headers for config request.
      * @return Map of headers
index 24a0755..d7991d1 100644 (file)
@@ -44,6 +44,7 @@ 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.models.base.PfModelException;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -87,8 +88,8 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
      * @param newState the state to which the control loop element is changing to
      */
     @Override
-    public synchronized void controlLoopElementStateChange(UUID controlLoopElementId, ControlLoopState currentState,
-                                                           ControlLoopOrderedState newState) {
+    public synchronized void controlLoopElementStateChange(ToscaConceptIdentifier controlLoopId,
+            UUID controlLoopElementId, ControlLoopState currentState, ControlLoopOrderedState newState) {
         switch (newState) {
             case UNINITIALISED:
                 ChartInfo chart = chartMap.get(controlLoopElementId);
@@ -96,8 +97,9 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
                     LOGGER.info("Helm deployment to be deleted {} ", chart.getReleaseName());
                     try {
                         chartService.uninstallChart(chart);
-                        intermediaryApi.updateControlLoopElementState(controlLoopElementId, newState,
-                            ControlLoopState.UNINITIALISED, ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE);
+                        intermediaryApi.updateControlLoopElementState(controlLoopId,
+                            controlLoopElementId, newState, ControlLoopState.UNINITIALISED,
+                            ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE);
                         chartMap.remove(controlLoopElementId);
                         podStatusMap.remove(chart.getReleaseName());
                     } catch (ServiceException se) {
@@ -106,11 +108,13 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
                 }
                 break;
             case PASSIVE:
-                intermediaryApi.updateControlLoopElementState(controlLoopElementId, newState, ControlLoopState.PASSIVE,
+                intermediaryApi.updateControlLoopElementState(controlLoopId,
+                    controlLoopElementId, newState, ControlLoopState.PASSIVE,
                     ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE);
                 break;
             case RUNNING:
-                intermediaryApi.updateControlLoopElementState(controlLoopElementId, newState, ControlLoopState.RUNNING,
+                intermediaryApi.updateControlLoopElementState(controlLoopId,
+                    controlLoopElementId, newState, ControlLoopState.RUNNING,
                     ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE);
                 break;
             default:
@@ -128,8 +132,8 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
      * @throws PfModelException in case of an exception
      */
     @Override
-    public synchronized void controlLoopElementUpdate(ControlLoopElement element,
-            ToscaNodeTemplate nodeTemplate) throws PfModelException {
+    public synchronized void controlLoopElementUpdate(ToscaConceptIdentifier controlLoopId,
+            ControlLoopElement element, ToscaNodeTemplate nodeTemplate) throws PfModelException {
         @SuppressWarnings("unchecked")
         Map<String, Object> chartData =
             (Map<String, Object>) nodeTemplate.getProperties().get("chart");
index 2d4439a..1f8e769 100644 (file)
@@ -47,6 +47,7 @@ import org.onap.policy.clamp.controlloop.participant.intermediary.api.Participan
 import org.onap.policy.clamp.controlloop.participant.kubernetes.exception.ServiceException;
 import org.onap.policy.clamp.controlloop.participant.kubernetes.models.ChartInfo;
 import org.onap.policy.clamp.controlloop.participant.kubernetes.models.ChartList;
+import org.onap.policy.clamp.controlloop.participant.kubernetes.parameters.CommonTestData;
 import org.onap.policy.clamp.controlloop.participant.kubernetes.service.ChartService;
 import org.onap.policy.clamp.controlloop.participant.kubernetes.utils.TestUtils;
 import org.onap.policy.common.utils.coder.Coder;
@@ -69,7 +70,7 @@ class ControlLoopElementHandlerTest {
     private static ToscaServiceTemplate toscaServiceTemplate;
     private static final String K8S_CONTROL_LOOP_ELEMENT =
         "org.onap.domain.database.PMSH_K8SMicroserviceControlLoopElement";
-
+    private CommonTestData commonTestData = new CommonTestData();
 
     @InjectMocks
     @Spy
@@ -98,19 +99,19 @@ class ControlLoopElementHandlerTest {
 
         doNothing().when(chartService).uninstallChart(charts.get(0));
 
-        controlLoopElementHandler.controlLoopElementStateChange(controlLoopElementId1, ControlLoopState.PASSIVE,
-            ControlLoopOrderedState.UNINITIALISED);
+        controlLoopElementHandler.controlLoopElementStateChange(commonTestData.getControlLoopId(),
+            controlLoopElementId1, ControlLoopState.PASSIVE, ControlLoopOrderedState.UNINITIALISED);
 
         doThrow(new ServiceException("Error uninstalling the chart")).when(chartService)
             .uninstallChart(charts.get(0));
 
         assertDoesNotThrow(() -> controlLoopElementHandler
-            .controlLoopElementStateChange(controlLoopElementId1, ControlLoopState.PASSIVE,
-                ControlLoopOrderedState.UNINITIALISED));
+            .controlLoopElementStateChange(commonTestData.getControlLoopId(), controlLoopElementId1,
+                ControlLoopState.PASSIVE, ControlLoopOrderedState.UNINITIALISED));
 
         assertDoesNotThrow(() -> controlLoopElementHandler
-            .controlLoopElementStateChange(controlLoopElementId1, ControlLoopState.PASSIVE,
-                ControlLoopOrderedState.RUNNING));
+            .controlLoopElementStateChange(commonTestData.getControlLoopId(), controlLoopElementId1,
+                ControlLoopState.PASSIVE, ControlLoopOrderedState.RUNNING));
 
     }
 
@@ -125,7 +126,8 @@ class ControlLoopElementHandlerTest {
 
         Map<String, ToscaNodeTemplate> nodeTemplatesMap =
                 toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates();
-        controlLoopElementHandler.controlLoopElementUpdate(element, nodeTemplatesMap.get(K8S_CONTROL_LOOP_ELEMENT));
+        controlLoopElementHandler.controlLoopElementUpdate(commonTestData.getControlLoopId(), element,
+            nodeTemplatesMap.get(K8S_CONTROL_LOOP_ELEMENT));
 
         assertThat(controlLoopElementHandler.getChartMap()).hasSize(1).containsKey(elementId1);
 
@@ -134,7 +136,8 @@ class ControlLoopElementHandlerTest {
 
         UUID elementId2 = UUID.randomUUID();
         element.setId(elementId2);
-        controlLoopElementHandler.controlLoopElementUpdate(element, nodeTemplatesMap.get(K8S_CONTROL_LOOP_ELEMENT));
+        controlLoopElementHandler.controlLoopElementUpdate(commonTestData.getControlLoopId(), element,
+            nodeTemplatesMap.get(K8S_CONTROL_LOOP_ELEMENT));
 
         assertThat(controlLoopElementHandler.getChartMap().containsKey(elementId2)).isFalse();
     }
index 98c0862..f6ec401 100644 (file)
@@ -150,4 +150,12 @@ public class CommonTestData {
         topicParams.setServers(Arrays.asList("localhost"));
         return topicParams;
     }
+
+    /**
+     * Get controlloop id.
+     * @return ToscaConceptIdentifier controlLoopId
+     */
+    public ToscaConceptIdentifier getControlLoopId() {
+        return new ToscaConceptIdentifier("PMSHInstance0", "1.0.0");
+    }
 }
index 4f8dcf1..9054788 100644 (file)
@@ -38,6 +38,7 @@ import org.onap.policy.clamp.controlloop.participant.intermediary.api.Participan
 import org.onap.policy.clamp.controlloop.participant.policy.client.PolicyApiHttpClient;
 import org.onap.policy.models.base.PfModelException;
 import org.onap.policy.models.base.PfModelRuntimeException;
+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.ToscaPolicy;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
@@ -79,22 +80,25 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
      * @throws PfModelException in case of an exception
      */
     @Override
-    public void controlLoopElementStateChange(UUID controlLoopElementId, ControlLoopState currentState,
+    public void controlLoopElementStateChange(ToscaConceptIdentifier controlLoopId,
+                UUID controlLoopElementId, ControlLoopState currentState,
             ControlLoopOrderedState newState) throws PfModelException {
         switch (newState) {
             case UNINITIALISED:
                 try {
-                    deletePolicyData(controlLoopElementId, newState);
+                    deletePolicyData(controlLoopId, controlLoopElementId, newState);
                 } catch (PfModelRuntimeException e) {
                     LOGGER.debug("Deleting policy data failed", e);
                 }
                 break;
             case PASSIVE:
-                intermediaryApi.updateControlLoopElementState(controlLoopElementId, newState, ControlLoopState.PASSIVE,
+                intermediaryApi.updateControlLoopElementState(controlLoopId,
+                    controlLoopElementId, newState, ControlLoopState.PASSIVE,
                     ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE);
                 break;
             case RUNNING:
-                intermediaryApi.updateControlLoopElementState(controlLoopElementId, newState, ControlLoopState.RUNNING,
+                intermediaryApi.updateControlLoopElementState(controlLoopId,
+                    controlLoopElementId, newState, ControlLoopState.RUNNING,
                     ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE);
                 break;
             default:
@@ -103,7 +107,8 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
         }
     }
 
-    private void deletePolicyData(UUID controlLoopElementId, ControlLoopOrderedState newState) {
+    private void deletePolicyData(ToscaConceptIdentifier controlLoopId,
+            UUID controlLoopElementId, ControlLoopOrderedState newState) {
         // Delete all policies of this controlLoop from policy framework
         for (Entry<String, String> policy : policyMap.entrySet()) {
             apiHttpClient.deletePolicy(policy.getKey(), policy.getValue());
@@ -114,7 +119,8 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
             apiHttpClient.deletePolicyType(policyType.getKey(), policyType.getValue());
         }
         policyTypeMap.clear();
-        intermediaryApi.updateControlLoopElementState(controlLoopElementId, newState, ControlLoopState.UNINITIALISED,
+        intermediaryApi.updateControlLoopElementState(controlLoopId,
+            controlLoopElementId, newState, ControlLoopState.UNINITIALISED,
             ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE);
     }
 
@@ -126,9 +132,10 @@ public class ControlLoopElementHandler implements ControlLoopElementListener {
      * @throws PfModelException in case of an exception
      */
     @Override
-    public void controlLoopElementUpdate(ControlLoopElement element, ToscaNodeTemplate clElementDefinition)
+    public void controlLoopElementUpdate(ToscaConceptIdentifier controlLoopId, ControlLoopElement element,
+                ToscaNodeTemplate clElementDefinition)
             throws PfModelException {
-        intermediaryApi.updateControlLoopElementState(element.getId(), element.getOrderedState(),
+        intermediaryApi.updateControlLoopElementState(controlLoopId, element.getId(), element.getOrderedState(),
                 ControlLoopState.PASSIVE, ParticipantMessageType.CONTROL_LOOP_UPDATE);
         ToscaServiceTemplate controlLoopDefinition = element.getToscaServiceTemplateFragment();
         if (controlLoopDefinition.getToscaTopologyTemplate() != null) {
index a33fa0a..fe7cb3c 100644 (file)
@@ -154,7 +154,7 @@ public class TestListenerUtils {
         Map<String, ToscaNodeTemplate> nodeTemplatesMap =
                 toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates();
         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry : nodeTemplatesMap.entrySet()) {
-            if (toscaInputEntry.getValue().getType().contains(CONTROL_LOOP_ELEMENT)) {
+            if (checkIfNodeTemplateIsControlLoopElement(toscaInputEntry.getValue(), toscaServiceTemplate)) {
                 ControlLoopElement clElement = new ControlLoopElement();
                 clElement.setId(UUID.randomUUID());
                 ToscaConceptIdentifier clParticipantType;
@@ -187,6 +187,22 @@ public class TestListenerUtils {
         return clUpdateMsg;
     }
 
+    private static boolean checkIfNodeTemplateIsControlLoopElement(ToscaNodeTemplate nodeTemplate,
+            ToscaServiceTemplate toscaServiceTemplate) {
+        if (nodeTemplate.getType().contains(CONTROL_LOOP_ELEMENT)) {
+            return true;
+        } else {
+            var nodeType = toscaServiceTemplate.getNodeTypes().get(nodeTemplate.getType());
+            if (nodeType != null) {
+                var derivedFrom = nodeType.getDerivedFrom();
+                if (derivedFrom != null) {
+                    return derivedFrom.contains(CONTROL_LOOP_ELEMENT) ? true : false;
+                }
+            }
+        }
+        return false;
+    }
+
     private static void populateToscaNodeTemplateFragment(ControlLoopElement clElement,
             ToscaServiceTemplate toscaServiceTemplate) {
         ToscaNodeTemplate toscaNodeTemplate = toscaServiceTemplate
@@ -263,7 +279,7 @@ public class TestListenerUtils {
         List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>();
         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry :
             toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().entrySet()) {
-            if (toscaInputEntry.getValue().getType().contains(CONTROL_LOOP_ELEMENT)) {
+            if (checkIfNodeTemplateIsControlLoopElement(toscaInputEntry.getValue(), toscaServiceTemplate)) {
                 ToscaConceptIdentifier clParticipantType;
                 try {
                     clParticipantType = CODER.decode(
index a7d2116..688f7df 100644 (file)
@@ -79,8 +79,8 @@ public class SimulationProvider {
      */
     public TypedSimpleResponse<ControlLoopElement> updateControlLoopElement(ControlLoopElement element) {
         TypedSimpleResponse<ControlLoopElement> response = new TypedSimpleResponse<>();
-        response.setResponse(intermediaryApi.updateControlLoopElementState(element.getId(), element.getOrderedState(),
-                element.getState(), ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE));
+        response.setResponse(intermediaryApi.updateControlLoopElementState(null, element.getId(),
+            element.getOrderedState(), element.getState(), ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE));
         return response;
     }
 
index 56be081..7439ccd 100644 (file)
@@ -146,7 +146,7 @@ public class TestListenerUtils {
         Map<String, ToscaNodeTemplate> nodeTemplatesMap =
                 toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates();
         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry : nodeTemplatesMap.entrySet()) {
-            if (toscaInputEntry.getValue().getType().contains(CONTROL_LOOP_ELEMENT)) {
+            if (checkIfNodeTemplateIsControlLoopElement(toscaInputEntry.getValue(), toscaServiceTemplate)) {
                 ControlLoopElement clElement = new ControlLoopElement();
                 clElement.setId(UUID.randomUUID());
                 ToscaConceptIdentifier clParticipantType;
@@ -178,6 +178,22 @@ public class TestListenerUtils {
         return clUpdateMsg;
     }
 
+    private static boolean checkIfNodeTemplateIsControlLoopElement(ToscaNodeTemplate nodeTemplate,
+            ToscaServiceTemplate toscaServiceTemplate) {
+        if (nodeTemplate.getType().contains(CONTROL_LOOP_ELEMENT)) {
+            return true;
+        } else {
+            var nodeType = toscaServiceTemplate.getNodeTypes().get(nodeTemplate.getType());
+            if (nodeType != null) {
+                var derivedFrom = nodeType.getDerivedFrom();
+                if (derivedFrom != null) {
+                    return derivedFrom.contains(CONTROL_LOOP_ELEMENT) ? true : false;
+                }
+            }
+        }
+        return false;
+    }
+
     private static void prepareParticipantUpdateForControlLoop(ControlLoopElement clElement,
         List<ParticipantUpdates> participantUpdates) {
         if (participantUpdates.isEmpty()) {
@@ -228,7 +244,7 @@ public class TestListenerUtils {
         List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>();
         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry :
             toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().entrySet()) {
-            if (toscaInputEntry.getValue().getType().contains(CONTROL_LOOP_ELEMENT)) {
+            if (checkIfNodeTemplateIsControlLoopElement(toscaInputEntry.getValue(), toscaServiceTemplate)) {
                 ToscaConceptIdentifier clParticipantType;
                 try {
                     clParticipantType = CODER.decode(
index 4dd978f..58378fa 100644 (file)
@@ -25,6 +25,7 @@ import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
 import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
 
 /**
@@ -39,8 +40,8 @@ public interface ControlLoopElementListener {
      * @param newState the state to which the control loop element is changing to
      * @throws PfModelException in case of a model exception
      */
-    public void controlLoopElementStateChange(UUID controlLoopElementId, ControlLoopState currentState,
-            ControlLoopOrderedState newState) throws PfModelException;
+    public void controlLoopElementStateChange(ToscaConceptIdentifier controlLoopId, UUID controlLoopElementId,
+        ControlLoopState currentState, ControlLoopOrderedState newState) throws PfModelException;
 
     /**
      * Handle an update on a control loop element.
@@ -49,7 +50,7 @@ public interface ControlLoopElementListener {
      * @param controlLoopElementDefinition toscaNodeTemplate
      * @throws PfModelException from Policy framework
      */
-    public void controlLoopElementUpdate(ControlLoopElement element,
+    public void controlLoopElementUpdate(ToscaConceptIdentifier controlLoopId, ControlLoopElement element,
             ToscaNodeTemplate controlLoopElementDefinition) throws PfModelException;
 
     /**
index 7292f8d..3859e0c 100644 (file)
@@ -116,7 +116,8 @@ public interface ParticipantIntermediaryApi {
      * @param newState the state of the control loop element
      * @return ControlLoopElement updated control loop element
      */
-    ControlLoopElement updateControlLoopElementState(UUID id, ControlLoopOrderedState currentState,
+    ControlLoopElement updateControlLoopElementState(ToscaConceptIdentifier controlLoopId,
+            UUID id, ControlLoopOrderedState currentState,
             ControlLoopState newState, ParticipantMessageType messageType);
 
     /**
index f8ef8d5..1f79d71 100644 (file)
@@ -122,9 +122,11 @@ public class ParticipantIntermediaryApiImpl implements ParticipantIntermediaryAp
     }
 
     @Override
-    public ControlLoopElement updateControlLoopElementState(UUID id, ControlLoopOrderedState currentState,
+    public ControlLoopElement updateControlLoopElementState(ToscaConceptIdentifier controlLoopId,
+            UUID id, ControlLoopOrderedState currentState,
             ControlLoopState newState, ParticipantMessageType messageType) {
-        return participantHandler.getControlLoopHandler().updateControlLoopElementState(id, currentState, newState);
+        return participantHandler.getControlLoopHandler().updateControlLoopElementState(controlLoopId,
+            id, currentState, newState);
     }
 
     @Override
index 9cd032a..6e1b31c 100644 (file)
@@ -45,6 +45,7 @@ import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.Parti
 import org.onap.policy.clamp.controlloop.participant.intermediary.api.ControlLoopElementListener;
 import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ParticipantMessagePublisher;
 import org.onap.policy.clamp.controlloop.participant.intermediary.parameters.ParticipantParameters;
+import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.models.base.PfModelException;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
@@ -96,7 +97,8 @@ public class ControlLoopHandler {
      * @param newState the ordered state
      * @return controlLoopElement the updated controlloop element
      */
-    public ControlLoopElement updateControlLoopElementState(UUID id, ControlLoopOrderedState orderedState,
+    public ControlLoopElement updateControlLoopElementState(ToscaConceptIdentifier controlLoopId,
+            UUID id, ControlLoopOrderedState orderedState,
             ControlLoopState newState) {
 
         if (id == null) {
@@ -104,15 +106,24 @@ public class ControlLoopHandler {
         }
 
         ControlLoopElement clElement = elementsOnThisParticipant.get(id);
+        for (var controlLoop : controlLoopMap.values()) {
+            var element = controlLoop.getElements().get(id);
+            if (element != null) {
+                element.setState(newState);
+            }
+        }
+
         if (clElement != null) {
             var controlLoopStateChangeAck =
                     new ControlLoopAck(ParticipantMessageType.CONTROLLOOP_STATECHANGE_ACK);
             controlLoopStateChangeAck.setParticipantId(participantId);
             controlLoopStateChangeAck.setParticipantType(participantType);
+            controlLoopStateChangeAck.setControlLoopId(controlLoopId);
             clElement.setOrderedState(orderedState);
             clElement.setState(newState);
             controlLoopStateChangeAck.getControlLoopResultMap().put(clElement.getId(),
-                new  ControlLoopElementAck(true, "Control loop element {} state changed to {}\", id, newState)"));
+                new  ControlLoopElementAck(newState, true,
+                    "Control loop element {} state changed to {}\", id, newState)"));
             LOGGER.debug("Control loop element {} state changed to {}", id, newState);
             controlLoopStateChangeAck.setMessage("ControlLoopElement state changed to {} " + newState);
             controlLoopStateChangeAck.setResult(true);
@@ -219,6 +230,11 @@ public class ControlLoopHandler {
             return;
         }
 
+        if (updateMsg.getParticipantUpdatesList().isEmpty()) {
+            LOGGER.warn("No ControlLoopElement updates in message {}", updateMsg.getControlLoopId());
+            return;
+        }
+
         List<ControlLoopElement> clElements = storeElementsOnThisParticipant(updateMsg.getParticipantUpdatesList());
 
         try {
@@ -226,7 +242,8 @@ public class ControlLoopHandler {
                 ToscaNodeTemplate clElementNodeTemplate = getClElementNodeTemplate(
                         clElementDefinitions, element.getDefinition());
                 for (ControlLoopElementListener clElementListener : listeners) {
-                    clElementListener.controlLoopElementUpdate(element, clElementNodeTemplate);
+                    clElementListener.controlLoopElementUpdate(updateMsg.getControlLoopId(),
+                        element, clElementNodeTemplate);
                 }
             }
         } catch (PfModelException e) {
@@ -284,7 +301,8 @@ public class ControlLoopHandler {
         for (ControlLoopElementListener clElementListener : listeners) {
             try {
                 for (ControlLoopElement element : controlLoop.getElements().values()) {
-                    clElementListener.controlLoopElementStateChange(element.getId(), element.getState(), orderedState);
+                    clElementListener.controlLoopElementStateChange(controlLoop.getDefinition(),
+                        element.getId(), element.getState(), orderedState);
                 }
             } catch (PfModelException e) {
                 LOGGER.debug("Control loop element update failed {}", controlLoop.getDefinition());
index 072a2eb..19641b0 100644 (file)
@@ -301,6 +301,7 @@ public class ParticipantHandler {
         } else {
             // This message is to decommision the controlloop
             clElementDefsOnThisParticipant.clear();
+            this.state = ParticipantState.TERMINATED;
         }
         sendParticipantUpdateAck(participantUpdateMsg.getMessageId());
     }
@@ -315,7 +316,7 @@ public class ParticipantHandler {
         participantUpdateAck.setResult(true);
         participantUpdateAck.setParticipantId(participantId);
         participantUpdateAck.setParticipantType(participantType);
-
+        participantUpdateAck.setState(state);
         publisher.sendParticipantUpdateAck(participantUpdateAck);
     }
 
index 789e4fa..a426cac 100644 (file)
 package org.onap.policy.clamp.controlloop.runtime.supervision;
 
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
 import javax.ws.rs.core.Response;
 import lombok.AllArgsConstructor;
 import org.apache.commons.collections4.CollectionUtils;
 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.ControlLoopElementAck;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopInfo;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant;
@@ -166,6 +170,22 @@ public class SupervisionHandler {
     @MessageIntercept
     public void handleParticipantMessage(ParticipantUpdateAck participantUpdateAckMessage) {
         LOGGER.debug("Participant Update Ack received {}", participantUpdateAckMessage);
+        try {
+            var participantList =
+                participantProvider.getParticipants(participantUpdateAckMessage.getParticipantId().getName(),
+                    participantUpdateAckMessage.getParticipantId().getVersion());
+
+            if (participantList != null) {
+                for (Participant participant : participantList) {
+                    participant.setParticipantState(participantUpdateAckMessage.getState());
+                }
+                participantProvider.updateParticipants(participantList);
+            } else {
+                LOGGER.warn("Participant not found in database {}", participantUpdateAckMessage.getParticipantId());
+            }
+        } catch (PfModelException pfme) {
+            LOGGER.warn("Model exception occured {}", participantUpdateAckMessage.getParticipantId());
+        }
     }
 
     /**
@@ -200,6 +220,7 @@ public class SupervisionHandler {
     @MessageIntercept
     public void handleControlLoopUpdateAckMessage(ControlLoopAck controlLoopAckMessage) {
         LOGGER.debug("ControlLoop Update Ack message received {}", controlLoopAckMessage);
+        setClElementStateInDb(controlLoopAckMessage);
     }
 
     /**
@@ -210,6 +231,39 @@ public class SupervisionHandler {
     @MessageIntercept
     public void handleControlLoopStateChangeAckMessage(ControlLoopAck controlLoopAckMessage) {
         LOGGER.debug("ControlLoop StateChange Ack message received {}", controlLoopAckMessage);
+        setClElementStateInDb(controlLoopAckMessage);
+    }
+
+    private void setClElementStateInDb(ControlLoopAck controlLoopAckMessage) {
+        if (controlLoopAckMessage.getControlLoopResultMap() != null) {
+            try {
+                var controlLoop = controlLoopProvider.getControlLoop(controlLoopAckMessage.getControlLoopId());
+                if (controlLoop != null) {
+                    var updated = updateState(controlLoop, controlLoopAckMessage
+                            .getControlLoopResultMap().entrySet());
+                    if (updated) {
+                        controlLoopProvider.updateControlLoop(controlLoop);
+                    }
+                } else {
+                    LOGGER.warn("ControlLoop not found in database {}", controlLoopAckMessage.getControlLoopId());
+                }
+            } catch (PfModelException pfme) {
+                LOGGER.warn("Model exception occured {}", controlLoopAckMessage.getControlLoopId());
+            }
+        }
+    }
+
+    private boolean updateState(ControlLoop controlLoop, Set<Map.Entry<UUID, ControlLoopElementAck>>
+            controlLoopResultSet) {
+        var updated = false;
+        for (var clElementAck : controlLoopResultSet) {
+            var element = controlLoop.getElements().get(clElementAck.getKey());
+            if (element != null) {
+                element.setState(clElementAck.getValue().getState());
+                updated = true;
+            }
+        }
+        return updated;
     }
 
     /**
index c820bf3..d15a424 100644 (file)
@@ -78,7 +78,7 @@ public class ParticipantUpdatePublisher extends AbstractParticipantPublisher<Par
         List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>();
         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry : toscaServiceTemplate.getToscaTopologyTemplate()
                 .getNodeTemplates().entrySet()) {
-            if (toscaInputEntry.getValue().getType().contains(CONTROL_LOOP_ELEMENT)) {
+            if (checkIfNodeTemplateIsControlLoopElement(toscaInputEntry.getValue(), toscaServiceTemplate)) {
                 ToscaConceptIdentifier clParticipantType;
                 try {
                     clParticipantType =
@@ -138,4 +138,20 @@ public class ParticipantUpdatePublisher extends AbstractParticipantPublisher<Par
         participantDefinition.setControlLoopElementDefinitionList(controlLoopElementDefinitionList);
         return participantDefinition;
     }
+
+    private static boolean checkIfNodeTemplateIsControlLoopElement(ToscaNodeTemplate nodeTemplate,
+            ToscaServiceTemplate toscaServiceTemplate) {
+        if (nodeTemplate.getType().contains(CONTROL_LOOP_ELEMENT)) {
+            return true;
+        } else {
+            var nodeType = toscaServiceTemplate.getNodeTypes().get(nodeTemplate.getType());
+            if (nodeType != null) {
+                var derivedFrom = nodeType.getDerivedFrom();
+                if (derivedFrom != null) {
+                    return derivedFrom.contains(CONTROL_LOOP_ELEMENT) ? true : false;
+                }
+            }
+        }
+        return false;
+    }
 }
index 260ccfb..14de34d 100644 (file)
@@ -193,7 +193,7 @@ class SupervisionMessagesTest extends CommonRestController {
         List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>();
         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry :
             toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().entrySet()) {
-            if (toscaInputEntry.getValue().getType().contains(CONTROL_LOOP_ELEMENT)) {
+            if (checkIfNodeTemplateIsControlLoopElement(toscaInputEntry.getValue(), toscaServiceTemplate)) {
                 ToscaConceptIdentifier clParticipantType;
                 try {
                     clParticipantType = CODER.decode(
@@ -216,6 +216,22 @@ class SupervisionMessagesTest extends CommonRestController {
         }
     }
 
+    private static boolean checkIfNodeTemplateIsControlLoopElement(ToscaNodeTemplate nodeTemplate,
+            ToscaServiceTemplate toscaServiceTemplate) {
+        if (nodeTemplate.getType().contains(CONTROL_LOOP_ELEMENT)) {
+            return true;
+        } else {
+            var nodeType = toscaServiceTemplate.getNodeTypes().get(nodeTemplate.getType());
+            if (nodeType != null) {
+                var derivedFrom = nodeType.getDerivedFrom();
+                if (derivedFrom != null) {
+                    return derivedFrom.contains(CONTROL_LOOP_ELEMENT) ? true : false;
+                }
+            }
+        }
+        return false;
+    }
+
     private void prepareParticipantDefinitionUpdate(ToscaConceptIdentifier clParticipantType, String entryKey,
         ToscaNodeTemplate entryValue, List<ParticipantDefinition> participantDefinitionUpdates) {
 
@@ -259,6 +275,8 @@ class SupervisionMessagesTest extends CommonRestController {
         participantUpdateAckMsg.setMessage("ParticipantUpdateAck message");
         participantUpdateAckMsg.setResponseTo(UUID.randomUUID());
         participantUpdateAckMsg.setResult(true);
+        participantUpdateAckMsg.setParticipantId(getParticipantId());
+        participantUpdateAckMsg.setParticipantType(getParticipantType());
 
         synchronized (lockit) {
             ParticipantUpdateAckListener participantUpdateAckListener =