summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ControlLoopInfo.java (renamed from models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantHealthCheck.java)40
-rw-r--r--models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ControlLoopStatistics.java50
-rw-r--r--models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ParticipantHealthStatus.java7
-rw-r--r--models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ControlLoopAck.java6
-rw-r--r--models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantAckMessage.java13
-rw-r--r--models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantRegister.java4
-rw-r--r--models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantResponseDetails.java64
-rw-r--r--models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantStatus.java30
-rw-r--r--models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ControlLoopAckTest.java5
-rw-r--r--models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantHealthCheckTest.java61
-rw-r--r--models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantStatusTest.java66
-rw-r--r--participant/participant-impl/participant-impl-dcae/src/test/java/org/onap/policy/clamp/controlloop/participant/dcae/main/rest/TestListenerUtils.java24
-rw-r--r--participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/endtoend/ParticipantMessagesTest.java65
-rw-r--r--participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/utils/TestListenerUtils.java25
-rw-r--r--participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/MessageSender.java61
-rw-r--r--participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantMessagePublisher.java11
-rw-r--r--participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantStatusReqListener.java (renamed from participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantHealthCheckListener.java)10
-rw-r--r--participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ControlLoopHandler.java71
-rw-r--r--participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/IntermediaryActivator.java6
-rw-r--r--participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ParticipantHandler.java40
-rw-r--r--runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounter.java91
-rw-r--r--runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspect.java7
-rw-r--r--runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java40
-rw-r--r--runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScanner.java123
-rw-r--r--runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusReqPublisher.java48
-rw-r--r--runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounterTest.java84
-rw-r--r--runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspectTest.java66
-rw-r--r--runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScannerTest.java160
28 files changed, 875 insertions, 403 deletions
diff --git a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantHealthCheck.java b/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ControlLoopInfo.java
index e472e15fe..bdf894125 100644
--- a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantHealthCheck.java
+++ b/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ControlLoopInfo.java
@@ -18,39 +18,31 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.policy.clamp.controlloop.models.messages.dmaap.participant;
+package org.onap.policy.clamp.controlloop.models.controlloop.concepts;
-import lombok.Getter;
-import lombok.Setter;
+import lombok.Data;
+import lombok.NoArgsConstructor;
import lombok.ToString;
-import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantState;
/**
- * Class to represent the PARTICIPANT_HEALTHCHECK message that the control loop runtime will send to
- * participants to change the state of a control loop they are running.
+ * Class to represent a control loop info instance.
*/
-@Getter
-@Setter
-@ToString(callSuper = true)
-public class ParticipantHealthCheck extends ParticipantMessage {
- private ParticipantState state;
+@NoArgsConstructor
+@Data
+@ToString
+public class ControlLoopInfo {
- /**
- * Constructor for instantiating ParticipantHealthCheck class with message name.
- *
- */
- public ParticipantHealthCheck() {
- super(ParticipantMessageType.PARTICIPANT_HEALTH_CHECK);
- }
+ private ControlLoopState state = ControlLoopState.UNINITIALISED;
+
+ private ControlLoopStatistics controlLoopStatistics;
/**
- * Constructs the object, making a deep copy.
+ * Copy constructor, does a deep copy but as all fields here are immutable, it's just a regular copy.
*
- * @param source source from which to copy
+ * @param otherElement the other element to copy from
*/
- public ParticipantHealthCheck(ParticipantHealthCheck source) {
- super(source);
-
- this.state = source.state;
+ public ControlLoopInfo(final ControlLoopInfo otherElement) {
+ this.state = otherElement.state;
+ this.controlLoopStatistics = otherElement.controlLoopStatistics;
}
}
diff --git a/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ControlLoopStatistics.java b/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ControlLoopStatistics.java
new file mode 100644
index 000000000..685947b13
--- /dev/null
+++ b/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ControlLoopStatistics.java
@@ -0,0 +1,50 @@
+/*-
+ * ============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 java.time.Instant;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.ToString;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+@NoArgsConstructor
+@Data
+@ToString
+public class ControlLoopStatistics {
+
+ @NonNull
+ private ToscaConceptIdentifier controlLoopId;
+
+ @NonNull
+ private Instant timeStamp;
+
+ @NonNull
+ private ClElementStatisticsList clElementStatisticsList;
+
+ private long eventCount;
+ private long lastExecutionTime;
+ private double averageExecutionTime;
+ private long upTime;
+ private long lastEnterTime;
+ private long lastStart;
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ParticipantHealthStatus.java b/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ParticipantHealthStatus.java
index 0cf41c9cd..e7c5fecda 100644
--- a/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ParticipantHealthStatus.java
+++ b/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ParticipantHealthStatus.java
@@ -43,5 +43,10 @@ public enum ParticipantHealthStatus {
/**
* The health status of the Participant is unknown.
*/
- UNKNOWN
+ UNKNOWN,
+
+ /**
+ * The health status of the Participant is off line.
+ */
+ OFF_LINE
}
diff --git a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ControlLoopAck.java b/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ControlLoopAck.java
index 6a72ec1f2..3411a0369 100644
--- a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ControlLoopAck.java
+++ b/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ControlLoopAck.java
@@ -28,7 +28,6 @@ import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.commons.lang3.tuple.Pair;
-import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElementDefinition;
import org.onap.policy.models.base.PfUtils;
import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
@@ -59,7 +58,7 @@ public class ControlLoopAck extends ParticipantAckMessage {
// A map with ControlLoopElementID as its key, and a pair of result and message as value per
// ControlLoopElement.
- private Map<UUID, Map<UUID, Boolean>> controlLoopResultMap = new LinkedHashMap<>();
+ private Map<UUID, Pair<Boolean, String>> controlLoopResultMap = new LinkedHashMap<>();
/**
* Constructor for instantiating ParticipantRegisterAck class with message name.
@@ -79,7 +78,6 @@ public class ControlLoopAck extends ParticipantAckMessage {
this.participantId = source.participantId;
this.participantType = source.participantType;
this.controlLoopId = source.controlLoopId;
- this.controlLoopResultMap = PfUtils.mapMap(source.controlLoopResultMap,
- clElementResultMap -> PfUtils.mapMap(clElementResultMap, UnaryOperator.identity()));
+ this.controlLoopResultMap = PfUtils.mapMap(source.controlLoopResultMap, UnaryOperator.identity());
}
}
diff --git a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantAckMessage.java b/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantAckMessage.java
index 1e53921dd..8b59a1801 100644
--- a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantAckMessage.java
+++ b/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantAckMessage.java
@@ -24,6 +24,7 @@ import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
/**
* Class to represent participant Ack message.
@@ -45,6 +46,16 @@ public class ParticipantAckMessage {
private ParticipantMessageType messageType;
/**
+ * Participant Type, or {@code null} for messages from participants.
+ */
+ private ToscaConceptIdentifier participantType;
+
+ /**
+ * Participant ID, or {@code null} for messages from participants.
+ */
+ private ToscaConceptIdentifier participantId;
+
+ /**
* Constructor for instantiating a participant ack message class.
*
* @param messageType the message type
@@ -63,5 +74,7 @@ public class ParticipantAckMessage {
this.result = source.result;
this.message = source.message;
this.messageType = source.messageType;
+ this.participantType = source.participantType;
+ this.participantId = source.participantId;
}
}
diff --git a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantRegister.java b/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantRegister.java
index 7319d99db..af0149189 100644
--- a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantRegister.java
+++ b/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantRegister.java
@@ -23,10 +23,6 @@ package org.onap.policy.clamp.controlloop.models.messages.dmaap.participant;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
-import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops;
-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.ParticipantStatistics;
/**
* Class to represent the PARTICIPANT_REGISTER message that all the participants send to control loop runtime.
diff --git a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantResponseDetails.java b/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantResponseDetails.java
deleted file mode 100644
index 4c771b405..000000000
--- a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantResponseDetails.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*-
- * ============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.messages.dmaap.participant;
-
-import java.util.UUID;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
-
-/**
- * Class to represent participant response details.
- */
-@Getter
-@Setter
-@ToString
-@NoArgsConstructor
-public class ParticipantResponseDetails {
-
- // The responseTo field should match the original request id in the request.
- private UUID responseTo;
- private ParticipantResponseStatus responseStatus;
- private String responseMessage;
-
- /**
- * Constructs the object as a response to.
- *
- * @param triggerMessage the message to which this is a response
- */
- public ParticipantResponseDetails(ParticipantMessage triggerMessage) {
- this.responseMessage = null;
- this.responseStatus = ParticipantResponseStatus.FAIL;
- this.responseTo = triggerMessage.getMessageId();
- }
-
- /**
- * Constructs the object, making a deep copy.
- *
- * @param source source from which to copy
- */
- public ParticipantResponseDetails(ParticipantResponseDetails source) {
- this.responseMessage = source.responseMessage;
- this.responseStatus = source.responseStatus;
- this.responseTo = source.responseTo;
- }
-}
diff --git a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantStatus.java b/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantStatus.java
index 5b9284243..c3e630681 100644
--- a/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantStatus.java
+++ b/models/src/main/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantStatus.java
@@ -20,13 +20,19 @@
package org.onap.policy.clamp.controlloop.models.messages.dmaap.participant;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
-import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElementDefinition;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopInfo;
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.ParticipantStatistics;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
/**
* Class to represent the PARTICIPANT_STATUS message that all the participants send to the control loop runtime.
@@ -35,21 +41,21 @@ import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant
@Setter
@ToString(callSuper = true)
public class ParticipantStatus extends ParticipantMessage {
- // The response should be completed if this message is a response to a request from the Control Loop Runtime
- private ParticipantResponseDetails response;
// State and health status of the participant
private ParticipantState state;
private ParticipantHealthStatus healthStatus;
- // Control Loops on the participant
- private ControlLoops controlLoops;
-
// Participant statistics
private ParticipantStatistics participantStatistics;
- // Description. May be left {@code null}.
- private String message;
+ // A map with Participant ID as its key, and a map of ControlLoopElements as value.
+ // Returned in response to ParticipantStatusReq only
+ private Map<ToscaConceptIdentifier, Map<UUID, ControlLoopElementDefinition>>
+ participantDefinitionUpdateMap = new LinkedHashMap<>();
+
+ // Map of ControlLoopInfo types indexed by ControlLoopId, one entry for each control loop
+ private Map<ToscaConceptIdentifier, ControlLoopInfo> controlLoopInfoMap;
/**
* Constructor for instantiating ParticipantStatus class with message name.
@@ -69,8 +75,10 @@ public class ParticipantStatus extends ParticipantMessage {
this.state = source.state;
this.healthStatus = source.healthStatus;
- this.message = source.message;
- this.controlLoops = (source.controlLoops == null ? null : new ControlLoops(source.controlLoops));
- this.response = (source.response == null ? null : new ParticipantResponseDetails(source.response));
+ this.participantStatistics = (source.participantStatistics == null ? null : new ParticipantStatistics());
+ this.participantDefinitionUpdateMap = PfUtils.mapMap(source.participantDefinitionUpdateMap,
+ clElementDefinitionMap -> PfUtils.mapMap(clElementDefinitionMap,
+ ControlLoopElementDefinition::new));
+ this.controlLoopInfoMap = PfUtils.mapMap(source.controlLoopInfoMap, ControlLoopInfo::new);
}
}
diff --git a/models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ControlLoopAckTest.java b/models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ControlLoopAckTest.java
index 8734a435c..d7d7e4327 100644
--- a/models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ControlLoopAckTest.java
+++ b/models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ControlLoopAckTest.java
@@ -26,6 +26,7 @@ import static org.onap.policy.clamp.controlloop.models.messages.dmaap.participan
import java.util.Map;
import java.util.UUID;
+import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.Test;
import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
@@ -48,8 +49,8 @@ class ControlLoopAckTest {
orig.setParticipantId(id);
orig.setParticipantType(id);
- Map<UUID, Boolean> clElementResult = Map.of(UUID.randomUUID(), true);
- final Map<UUID, Map<UUID, Boolean>> controlLoopResultMap = Map.of(UUID.randomUUID(), clElementResult);
+ Pair<Boolean, String> clElementResult = Pair.of(true, "ControlLoopElement result");
+ final Map<UUID, Pair<Boolean, String>> controlLoopResultMap = Map.of(UUID.randomUUID(), clElementResult);
orig.setControlLoopResultMap(controlLoopResultMap);
orig.setResponseTo(UUID.randomUUID());
diff --git a/models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantHealthCheckTest.java b/models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantHealthCheckTest.java
deleted file mode 100644
index 52f1cc480..000000000
--- a/models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantHealthCheckTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*-
- * ============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.messages.dmaap.participant;
-
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.junit.Assert.assertEquals;
-import static org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessageUtils.removeVariableFields;
-
-import java.time.Instant;
-import java.util.UUID;
-import org.junit.jupiter.api.Test;
-import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantState;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
-
-/**
- * Test the copy constructor and other methods.
- */
-class ParticipantHealthCheckTest {
-
- @Test
- void testCopyConstructor() {
- assertThatThrownBy(() -> new ParticipantHealthCheck(null)).isInstanceOf(NullPointerException.class);
-
- ParticipantHealthCheck orig = new ParticipantHealthCheck();
-
- // verify with null values
- assertEquals(removeVariableFields(orig.toString()),
- removeVariableFields(new ParticipantHealthCheck(orig).toString()));
-
- // verify with all values
- ToscaConceptIdentifier id = new ToscaConceptIdentifier();
- id.setName("id");
- id.setVersion("1.2.3");
- orig.setControlLoopId(id);
- orig.setParticipantId(id);
- orig.setMessageId(UUID.randomUUID());
- orig.setState(ParticipantState.ACTIVE);
- orig.setTimestamp(Instant.ofEpochMilli(3000));
-
- assertEquals(removeVariableFields(orig.toString()),
- removeVariableFields(new ParticipantHealthCheck(orig).toString()));
- }
-}
diff --git a/models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantStatusTest.java b/models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantStatusTest.java
index 706e58b91..05cfdd78b 100644
--- a/models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantStatusTest.java
+++ b/models/src/test/java/org/onap/policy/clamp/controlloop/models/messages/dmaap/participant/ParticipantStatusTest.java
@@ -25,10 +25,20 @@ import static org.junit.Assert.assertEquals;
import static org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessageUtils.removeVariableFields;
import java.time.Instant;
+import java.util.List;
+import java.util.Map;
import java.util.UUID;
import org.junit.jupiter.api.Test;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatistics;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatisticsList;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElementDefinition;
+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.ControlLoopStatistics;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantHealthStatus;
import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantState;
import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
class ParticipantStatusTest {
@@ -43,20 +53,64 @@ class ParticipantStatusTest {
removeVariableFields(new ParticipantStatus(orig).toString()));
// verify with all values
- ToscaConceptIdentifier id = new ToscaConceptIdentifier();
- id.setName("id");
- id.setVersion("1.2.3");
+ ToscaConceptIdentifier id = new ToscaConceptIdentifier("id", "1.2.3");
orig.setControlLoopId(id);
orig.setParticipantId(id);
+ orig.setParticipantType(id);
orig.setMessageId(UUID.randomUUID());
orig.setState(ParticipantState.ACTIVE);
+ orig.setHealthStatus(ParticipantHealthStatus.HEALTHY);
orig.setTimestamp(Instant.ofEpochMilli(3000));
- final ParticipantResponseDetails resp = new ParticipantResponseDetails();
- resp.setResponseMessage("my-response");
- orig.setResponse(resp);
+ ControlLoopInfo clInfo = getControlLoopInfo(id);
+ orig.setControlLoopInfoMap(Map.of(id, clInfo));
+
+ ControlLoopElementDefinition clDefinition = getClElementDefinition();
+ Map<UUID, ControlLoopElementDefinition> clElementDefinitionMap = Map.of(UUID.randomUUID(), clDefinition);
+ Map<ToscaConceptIdentifier, Map<UUID, ControlLoopElementDefinition>>
+ participantDefinitionUpdateMap = Map.of(id, clElementDefinitionMap);
+ orig.setParticipantDefinitionUpdateMap(participantDefinitionUpdateMap);
assertEquals(removeVariableFields(orig.toString()),
removeVariableFields(new ParticipantStatus(orig).toString()));
}
+
+ private ControlLoopInfo getControlLoopInfo(ToscaConceptIdentifier id) {
+ ControlLoopInfo clInfo = new ControlLoopInfo();
+ clInfo.setState(ControlLoopState.PASSIVE2RUNNING);
+
+ ControlLoopStatistics clStatistics = new ControlLoopStatistics();
+ clStatistics.setControlLoopId(id);
+ clStatistics.setAverageExecutionTime(12345);
+ clStatistics.setEventCount(12345);
+ clStatistics.setLastEnterTime(12345);
+ clStatistics.setLastExecutionTime(12345);
+ clStatistics.setLastStart(12345);
+ clStatistics.setTimeStamp(Instant.ofEpochMilli(3000));
+ clStatistics.setUpTime(12345);
+ ClElementStatisticsList clElementStatisticsList = new ClElementStatisticsList();
+ ClElementStatistics clElementStatistics = new ClElementStatistics();
+ clElementStatistics.setParticipantId(new ToscaConceptIdentifier("defName", "0.0.1"));
+ clElementStatistics.setTimeStamp(Instant.now());
+ clElementStatisticsList.setClElementStatistics(List.of(clElementStatistics));
+ clStatistics.setClElementStatisticsList(clElementStatisticsList);
+
+ clInfo.setControlLoopStatistics(clStatistics);
+ return clInfo;
+ }
+
+ private ControlLoopElementDefinition getClElementDefinition() {
+ ToscaServiceTemplate toscaServiceTemplate = new ToscaServiceTemplate();
+ toscaServiceTemplate.setName("serviceTemplate");
+ toscaServiceTemplate.setDerivedFrom("parentServiceTemplate");
+ toscaServiceTemplate.setDescription("Description of serviceTemplate");
+ toscaServiceTemplate.setVersion("1.2.3");
+
+ ControlLoopElementDefinition clDefinition = new ControlLoopElementDefinition();
+ clDefinition.setId(UUID.randomUUID());
+ clDefinition.setControlLoopElementToscaServiceTemplate(toscaServiceTemplate);
+ Map<String, String> commonPropertiesMap = Map.of("Prop1", "PropValue");
+ clDefinition.setCommonPropertiesMap(commonPropertiesMap);
+ return clDefinition;
+ }
}
diff --git a/participant/participant-impl/participant-impl-dcae/src/test/java/org/onap/policy/clamp/controlloop/participant/dcae/main/rest/TestListenerUtils.java b/participant/participant-impl/participant-impl-dcae/src/test/java/org/onap/policy/clamp/controlloop/participant/dcae/main/rest/TestListenerUtils.java
index bb1021db6..136d0e500 100644
--- a/participant/participant-impl/participant-impl-dcae/src/test/java/org/onap/policy/clamp/controlloop/participant/dcae/main/rest/TestListenerUtils.java
+++ b/participant/participant-impl/participant-impl-dcae/src/test/java/org/onap/policy/clamp/controlloop/participant/dcae/main/rest/TestListenerUtils.java
@@ -32,7 +32,6 @@ import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop
import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantState;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopStateChange;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopUpdate;
-import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantHealthCheck;
import org.onap.policy.common.utils.coder.Coder;
import org.onap.policy.common.utils.coder.CoderException;
import org.onap.policy.common.utils.coder.StandardCoder;
@@ -170,29 +169,6 @@ public class TestListenerUtils {
}
/**
- * Method to create ParticipantHealthCheck message.
- *
- * @return ParticipantHealthCheck message
- */
- public static ParticipantHealthCheck createParticipantHealthCheckMsg() {
- ToscaConceptIdentifier participantId = new ToscaConceptIdentifier();
- participantId.setName("DCAEParticipant0");
- participantId.setVersion("1.0.0");
-
- ToscaConceptIdentifier controlLoopId = new ToscaConceptIdentifier();
- controlLoopId.setName("PMSHInstance0");
- controlLoopId.setVersion("1.0.0");
-
- final ParticipantHealthCheck participantHealthCheckMsg = new ParticipantHealthCheck();
- participantHealthCheckMsg.setParticipantId(participantId);
- participantHealthCheckMsg.setControlLoopId(controlLoopId);
- participantHealthCheckMsg.setTimestamp(Instant.now());
- participantHealthCheckMsg.setState(ParticipantState.PASSIVE);
-
- return participantHealthCheckMsg;
- }
-
- /**
* Method to create ControlLoopUpdate using the arguments passed.
*
* @param jsonFilePath the path of the controlloop content
diff --git a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/endtoend/ParticipantMessagesTest.java b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/endtoend/ParticipantMessagesTest.java
index 093ac190c..aed03556a 100644
--- a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/endtoend/ParticipantMessagesTest.java
+++ b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/endtoend/ParticipantMessagesTest.java
@@ -24,15 +24,22 @@ import static org.assertj.core.api.Assertions.assertThatCode;
import java.time.Instant;
import java.util.Collections;
+import java.util.List;
+import java.util.Map;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatistics;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatisticsList;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElementDefinition;
+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.ControlLoopStatistics;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregister;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregisterAck;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegister;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegisterAck;
-import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseDetails;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdate;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdateAck;
@@ -45,6 +52,7 @@ import org.onap.policy.clamp.controlloop.participant.policy.main.utils.TestListe
import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
import org.onap.policy.common.endpoints.event.comm.TopicSink;
import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
@@ -146,9 +154,16 @@ class ParticipantMessagesTest {
@Test
void testParticipantStatusHeartbeat() throws Exception {
final ParticipantStatus heartbeat = new ParticipantStatus();
- heartbeat.setMessage("ParticipantStatus message");
- heartbeat.setResponse(new ParticipantResponseDetails());
heartbeat.setParticipantId(getParticipantId());
+ ControlLoopInfo clInfo = getControlLoopInfo(getControlLoopId());
+ heartbeat.setControlLoopInfoMap(Map.of(getControlLoopId(), clInfo));
+
+ ControlLoopElementDefinition clDefinition = getClElementDefinition();
+ Map<UUID, ControlLoopElementDefinition> clElementDefinitionMap = Map.of(UUID.randomUUID(), clDefinition);
+ Map<ToscaConceptIdentifier, Map<UUID, ControlLoopElementDefinition>>
+ participantDefinitionUpdateMap = Map.of(getParticipantId(), clElementDefinitionMap);
+ heartbeat.setParticipantDefinitionUpdateMap(participantDefinitionUpdateMap);
+
synchronized (lockit) {
ParticipantMessagePublisher publisher =
new ParticipantMessagePublisher(Collections.singletonList(Mockito.mock(TopicSink.class)));
@@ -156,7 +171,6 @@ class ParticipantMessagesTest {
}
}
-
private ToscaConceptIdentifier getParticipantId() {
return new ToscaConceptIdentifier("org.onap.PM_Policy", "1.0.0");
}
@@ -164,4 +178,47 @@ class ParticipantMessagesTest {
private ToscaConceptIdentifier getParticipantType() {
return new ToscaConceptIdentifier("org.onap.policy.controlloop.PolicyControlLoopParticipant", "2.3.1");
}
+
+ private ToscaConceptIdentifier getControlLoopId() {
+ return new ToscaConceptIdentifier("PMSHInstance0", "1.0.0");
+ }
+
+ private ControlLoopInfo getControlLoopInfo(ToscaConceptIdentifier id) {
+ ControlLoopInfo clInfo = new ControlLoopInfo();
+ clInfo.setState(ControlLoopState.PASSIVE2RUNNING);
+
+ ControlLoopStatistics clStatistics = new ControlLoopStatistics();
+ clStatistics.setControlLoopId(id);
+ clStatistics.setAverageExecutionTime(12345);
+ clStatistics.setEventCount(12345);
+ clStatistics.setLastEnterTime(12345);
+ clStatistics.setLastExecutionTime(12345);
+ clStatistics.setLastStart(12345);
+ clStatistics.setTimeStamp(Instant.ofEpochMilli(3000));
+ clStatistics.setUpTime(12345);
+ ClElementStatisticsList clElementStatisticsList = new ClElementStatisticsList();
+ ClElementStatistics clElementStatistics = new ClElementStatistics();
+ clElementStatistics.setParticipantId(new ToscaConceptIdentifier("defName", "0.0.1"));
+ clElementStatistics.setTimeStamp(Instant.now());
+ clElementStatisticsList.setClElementStatistics(List.of(clElementStatistics));
+ clStatistics.setClElementStatisticsList(clElementStatisticsList);
+
+ clInfo.setControlLoopStatistics(clStatistics);
+ return clInfo;
+ }
+
+ private ControlLoopElementDefinition getClElementDefinition() {
+ ToscaServiceTemplate toscaServiceTemplate = new ToscaServiceTemplate();
+ toscaServiceTemplate.setName("serviceTemplate");
+ toscaServiceTemplate.setDerivedFrom("parentServiceTemplate");
+ toscaServiceTemplate.setDescription("Description of serviceTemplate");
+ toscaServiceTemplate.setVersion("1.2.3");
+
+ ControlLoopElementDefinition clDefinition = new ControlLoopElementDefinition();
+ clDefinition.setId(UUID.randomUUID());
+ clDefinition.setControlLoopElementToscaServiceTemplate(toscaServiceTemplate);
+ Map<String, String> commonPropertiesMap = Map.of("Prop1", "PropValue");
+ clDefinition.setCommonPropertiesMap(commonPropertiesMap);
+ return clDefinition;
+ }
}
diff --git a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/utils/TestListenerUtils.java b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/utils/TestListenerUtils.java
index fe7e17fd7..b91cff22c 100644
--- a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/utils/TestListenerUtils.java
+++ b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/controlloop/participant/policy/main/utils/TestListenerUtils.java
@@ -37,7 +37,6 @@ import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop
import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantState;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopStateChange;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopUpdate;
-import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantHealthCheck;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdate;
import org.onap.policy.clamp.controlloop.participant.policy.main.parameters.CommonTestData;
import org.onap.policy.common.utils.coder.Coder;
@@ -156,6 +155,7 @@ public class TestListenerUtils {
clElementParticipantId.setName(toscaInputEntry.getKey());
clElementParticipantId.setVersion(toscaInputEntry.getValue().getVersion());
clElement.setParticipantId(clElementParticipantId);
+ clElement.setParticipantType(clElementParticipantId);
clElement.setDefinition(clElementParticipantId);
clElement.setState(ControlLoopState.UNINITIALISED);
@@ -210,29 +210,6 @@ public class TestListenerUtils {
}
/**
- * Method to create ParticipantHealthCheck message.
- *
- * @return ParticipantHealthCheck message
- */
- public static ParticipantHealthCheck createParticipantHealthCheckMsg() {
- ToscaConceptIdentifier participantId = new ToscaConceptIdentifier();
- participantId.setName("org.onap.PM_Policy");
- participantId.setVersion("0.0.0");
-
- ToscaConceptIdentifier controlLoopId = new ToscaConceptIdentifier();
- controlLoopId.setName("PMSHInstance0");
- controlLoopId.setVersion("1.0.0");
-
- final ParticipantHealthCheck participantHealthCheckMsg = new ParticipantHealthCheck();
- participantHealthCheckMsg.setParticipantId(participantId);
- participantHealthCheckMsg.setControlLoopId(controlLoopId);
- participantHealthCheckMsg.setTimestamp(Instant.now());
- participantHealthCheckMsg.setState(ParticipantState.PASSIVE);
-
- return participantHealthCheckMsg;
- }
-
- /**
* Method to create ControlLoopUpdate using the arguments passed.
*
* @param jsonFilePath the path of the controlloop content
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/MessageSender.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/MessageSender.java
index 1741d9514..3ff420ffa 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/MessageSender.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/MessageSender.java
@@ -22,7 +22,10 @@ package org.onap.policy.clamp.controlloop.participant.intermediary.comm;
import java.io.Closeable;
import java.time.Instant;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.TimerTask;
+import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -30,9 +33,9 @@ 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.ControlLoops;
import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatistics;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopAck;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregister;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegister;
-import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseDetails;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseStatus;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdateAck;
@@ -84,48 +87,23 @@ public class MessageSender extends TimerTask implements Closeable {
/**
* Send a response message for this participant.
*
- * @param response the details to include in the response message
+ * @param ackMessage the details to include in the response message
*/
- public void sendResponse(ParticipantResponseDetails response) {
- sendResponse(null, response);
+ public void sendAckResponse(ControlLoopAck ackMessage) {
+ sendAckResponse(null, ackMessage);
}
/**
* Dispatch a response message for this participant.
*
* @param controlLoopId the control loop to which this message is a response
- * @param response the details to include in the response message
+ * @param ackMessage the details to include in the response message
*/
- public void sendResponse(ToscaConceptIdentifier controlLoopId, ParticipantResponseDetails response) {
- var status = new ParticipantStatus();
-
+ public void sendAckResponse(ToscaConceptIdentifier controlLoopId, ControlLoopAck ackMessage) {
// Participant related fields
- status.setParticipantType(participantHandler.getParticipantType());
- status.setParticipantId(participantHandler.getParticipantId());
- status.setState(participantHandler.getState());
- status.setHealthStatus(participantHandler.getHealthStatus());
-
- // Control loop related fields
- var controlLoops = participantHandler.getControlLoopHandler().getControlLoops();
- status.setControlLoopId(controlLoopId);
- status.setControlLoops(controlLoops);
- status.setResponse(response);
-
- var participantStatistics = new ParticipantStatistics();
- participantStatistics.setTimeStamp(Instant.now());
- participantStatistics.setParticipantId(participantHandler.getParticipantId());
- participantStatistics.setHealthStatus(participantHandler.getHealthStatus());
- participantStatistics.setState(participantHandler.getState());
- status.setParticipantStatistics(participantStatistics);
-
- for (ControlLoopElementListener clElementListener :
- participantHandler.getControlLoopHandler().getListeners()) {
- updateClElementStatistics(controlLoops, clElementListener);
- }
-
- status.setControlLoops(controlLoops);
-
- publisher.sendParticipantStatus(status);
+ ackMessage.setParticipantType(participantHandler.getParticipantType());
+ ackMessage.setParticipantId(participantHandler.getParticipantId());
+ publisher.sendControlLoopAck(ackMessage);
}
/**
@@ -156,6 +134,21 @@ public class MessageSender extends TimerTask implements Closeable {
}
/**
+ * Send a ParticipantStatus message for this participant.
+ *
+ * @param participantStatus the ParticipantStatus message
+ */
+ public void sendParticipantStatus(ParticipantStatus participantStatus) {
+ var controlLoops = participantHandler.getControlLoopHandler().getControlLoops();
+ for (ControlLoopElementListener clElementListener :
+ participantHandler.getControlLoopHandler().getListeners()) {
+ updateClElementStatistics(controlLoops, clElementListener);
+ }
+
+ publisher.sendParticipantStatus(participantStatus);
+ }
+
+ /**
* Dispatch a heartbeat for this participant.
*/
public void sendHeartbeat() {
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantMessagePublisher.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantMessagePublisher.java
index 051f00095..d8cc9eb6b 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantMessagePublisher.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantMessagePublisher.java
@@ -21,6 +21,7 @@
package org.onap.policy.clamp.controlloop.participant.intermediary.comm;
import java.util.List;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopAck;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregister;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegister;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus;
@@ -92,6 +93,16 @@ public class ParticipantMessagePublisher {
}
/**
+ * Method to send ControlLoop Update/StateChange Ack message to runtime.
+ *
+ * @param controlLoopAck ControlLoop Update/StateChange Ack
+ */
+ public void sendControlLoopAck(final ControlLoopAck controlLoopAck) {
+ topicSinkClient.send(controlLoopAck);
+ LOGGER.debug("Sent ControlLoop Update/StateChange Ack to runtime - {}", controlLoopAck);
+ }
+
+ /**
* Method to send Participant heartbeat to clamp on demand.
*
* @param participantStatus the Participant Status
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantHealthCheckListener.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantStatusReqListener.java
index 15f5140eb..0881edb19 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantHealthCheckListener.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/comm/ParticipantStatusReqListener.java
@@ -20,22 +20,22 @@
package org.onap.policy.clamp.controlloop.participant.intermediary.comm;
-import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantHealthCheck;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatusReq;
import org.onap.policy.clamp.controlloop.participant.intermediary.handler.ParticipantHandler;
import org.springframework.stereotype.Component;
/**
- * Listener for Participant health status messages sent by CLAMP.
+ * Listener for Participant status request messages sent by runtime to all/one participant.
*/
@Component
-public class ParticipantHealthCheckListener extends ParticipantListener<ParticipantHealthCheck> {
+public class ParticipantStatusReqListener extends ParticipantListener<ParticipantStatusReq> {
/**
* Constructs the object.
*
* @param participantHandler the handler for managing the state and health of the participant
*/
- public ParticipantHealthCheckListener(final ParticipantHandler participantHandler) {
- super(ParticipantHealthCheck.class, participantHandler, participantHandler::handleParticipantHealthCheck);
+ public ParticipantStatusReqListener(final ParticipantHandler participantHandler) {
+ super(ParticipantStatusReq.class, participantHandler, participantHandler::handleParticipantStatusReq);
}
}
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ControlLoopHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ControlLoopHandler.java
index c9da1279d..876a4cc52 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ControlLoopHandler.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ControlLoopHandler.java
@@ -28,6 +28,7 @@ import java.util.UUID;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.tuple.Pair;
import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatistics;
import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
@@ -35,10 +36,10 @@ 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.clamp.controlloop.models.controlloop.concepts.ControlLoops;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopAck;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopStateChange;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopUpdate;
-import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseDetails;
-import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseStatus;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessageType;
import org.onap.policy.clamp.controlloop.participant.intermediary.api.ControlLoopElementListener;
import org.onap.policy.clamp.controlloop.participant.intermediary.comm.MessageSender;
import org.onap.policy.clamp.controlloop.participant.intermediary.parameters.ParticipantIntermediaryParameters;
@@ -60,6 +61,7 @@ public class ControlLoopHandler {
private final Map<ToscaConceptIdentifier, ControlLoop> controlLoopMap = new LinkedHashMap<>();
+ @Getter
private final Map<UUID, ControlLoopElement> elementsOnThisParticipant = new LinkedHashMap<>();
@Getter
@@ -93,21 +95,23 @@ public class ControlLoopHandler {
ControlLoopState newState) {
if (id == null) {
- return null;
+ LOGGER.warn("Cannot update Control loop element state, id is null");
}
+ ControlLoopAck controlLoopStateChangeAck =
+ new ControlLoopAck(ParticipantMessageType.CONTROLLOOP_STATECHANGE_ACK);
ControlLoopElement clElement = elementsOnThisParticipant.get(id);
if (clElement != null) {
clElement.setOrderedState(orderedState);
clElement.setState(newState);
+ controlLoopStateChangeAck.getControlLoopResultMap().put(clElement.getId(),
+ Pair.of(true, "Control loop element {} state changed to {}\", id, newState)"));
LOGGER.debug("Control loop element {} state changed to {}", id, newState);
- var response = new ParticipantResponseDetails();
- response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
- response.setResponseMessage("ControlLoopElement state changed to {} " + newState);
- messageSender.sendResponse(response);
+ controlLoopStateChangeAck.setMessage("ControlLoopElement state changed to {} " + newState);
+ controlLoopStateChangeAck.setResult(true);
+ messageSender.sendAckResponse(controlLoopStateChangeAck);
return clElement;
}
-
return null;
}
@@ -143,9 +147,11 @@ public class ControlLoopHandler {
return;
}
- var response = new ParticipantResponseDetails(stateChangeMsg);
- handleState(controlLoop, response, stateChangeMsg.getOrderedState());
- messageSender.sendResponse(response);
+ var controlLoopStateChangeAck = new ControlLoopAck(ParticipantMessageType.CONTROLLOOP_STATECHANGE_ACK);
+ controlLoopStateChangeAck.setResponseTo(stateChangeMsg.getMessageId());
+ controlLoopStateChangeAck.setControlLoopId(stateChangeMsg.getControlLoopId());
+ handleState(controlLoop, controlLoopStateChangeAck, stateChangeMsg.getOrderedState());
+ messageSender.sendAckResponse(controlLoopStateChangeAck);
}
/**
@@ -155,7 +161,7 @@ public class ControlLoopHandler {
* @param response participant response
* @param orderedState controlloop ordered state
*/
- private void handleState(final ControlLoop controlLoop, final ParticipantResponseDetails response,
+ private void handleState(final ControlLoop controlLoop, final ControlLoopAck response,
ControlLoopOrderedState orderedState) {
switch (orderedState) {
case UNINITIALISED:
@@ -187,16 +193,17 @@ public class ControlLoopHandler {
var controlLoop = controlLoopMap.get(updateMsg.getControlLoopId());
- var response = new ParticipantResponseDetails(updateMsg);
+ var controlLoopUpdateAck = new ControlLoopAck(ParticipantMessageType.CONTROLLOOP_UPDATE_ACK);
// TODO: Updates to existing ControlLoops are not supported yet (Addition/Removal of ControlLoop
// elements to existing ControlLoop has to be supported).
if (controlLoop != null) {
- response.setResponseStatus(ParticipantResponseStatus.FAIL);
- response.setResponseMessage("Control loop " + updateMsg.getControlLoopId()
- + " already defined on participant " + participantId);
-
- messageSender.sendResponse(response);
+ controlLoopUpdateAck.setResponseTo(updateMsg.getMessageId());
+ controlLoopUpdateAck.setControlLoopId(updateMsg.getControlLoopId());
+ controlLoopUpdateAck.setMessage("Control loop " + updateMsg.getControlLoopId()
+ + " already defined on participant " + participantId);
+ controlLoopUpdateAck.setResult(false);
+ messageSender.sendAckResponse(controlLoopUpdateAck);
return;
}
@@ -221,11 +228,12 @@ public class ControlLoopHandler {
}
}
- response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
- response.setResponseMessage(
- "Control loop " + updateMsg.getControlLoopId() + " defined on participant " + participantId);
-
- messageSender.sendResponse(response);
+ controlLoopUpdateAck.setResponseTo(updateMsg.getMessageId());
+ controlLoopUpdateAck.setControlLoopId(updateMsg.getControlLoopId());
+ controlLoopUpdateAck.setMessage("Control loop " + updateMsg.getControlLoopId()
+ + " defined on participant " + participantId);
+ controlLoopUpdateAck.setResult(true);
+ messageSender.sendAckResponse(controlLoopUpdateAck);
}
/**
@@ -236,7 +244,7 @@ public class ControlLoopHandler {
* @param response participant response
*/
private void handleUninitialisedState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
- final ParticipantResponseDetails response) {
+ final ControlLoopAck response) {
handleStateChange(controlLoop, orderedState, ControlLoopState.UNINITIALISED, response);
controlLoopMap.remove(controlLoop.getKey().asIdentifier());
@@ -259,7 +267,7 @@ public class ControlLoopHandler {
* @param response participant response
*/
private void handlePassiveState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
- final ParticipantResponseDetails response) {
+ final ControlLoopAck response) {
handleStateChange(controlLoop, orderedState, ControlLoopState.PASSIVE, response);
}
@@ -271,7 +279,7 @@ public class ControlLoopHandler {
* @param response participant response
*/
private void handleRunningState(final ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
- final ParticipantResponseDetails response) {
+ final ControlLoopAck response) {
handleStateChange(controlLoop, orderedState, ControlLoopState.RUNNING, response);
}
@@ -284,11 +292,11 @@ public class ControlLoopHandler {
* @param response the response to the state change request
*/
private void handleStateChange(ControlLoop controlLoop, final ControlLoopOrderedState orderedState,
- ControlLoopState newState, ParticipantResponseDetails response) {
+ ControlLoopState newState, ControlLoopAck response) {
if (orderedState.equals(controlLoop.getOrderedState())) {
- response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
- response.setResponseMessage("Control loop is already in state " + orderedState);
+ response.setMessage("Control loop is already in state " + orderedState);
+ response.setResult(false);
return;
}
@@ -299,9 +307,8 @@ public class ControlLoopHandler {
});
}
- response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
- response.setResponseMessage(
- "ControlLoop state changed from " + controlLoop.getOrderedState() + " to " + orderedState);
+ response.setMessage("ControlLoop state changed from " + controlLoop.getOrderedState() + " to " + orderedState);
+ response.setResult(true);
controlLoop.setOrderedState(orderedState);
}
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/IntermediaryActivator.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/IntermediaryActivator.java
index f846b2d75..4fc0ae1b1 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/IntermediaryActivator.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/IntermediaryActivator.java
@@ -28,8 +28,8 @@ import org.onap.policy.clamp.controlloop.participant.intermediary.api.Participan
import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ControlLoopStateChangeListener;
import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ControlLoopUpdateListener;
import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ParticipantDeregisterAckListener;
-import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ParticipantHealthCheckListener;
import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ParticipantRegisterAckListener;
+import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ParticipantStatusReqListener;
import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ParticipantUpdateListener;
import org.onap.policy.clamp.controlloop.participant.intermediary.parameters.ParticipantParameters;
import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
@@ -119,8 +119,8 @@ public class IntermediaryActivator extends ServiceManagerContainer implements Cl
private void registerMsgDispatcher() {
MessageTypeDispatcher msgDispatcher = applicationContext.getBean(MessageTypeDispatcher.class);
- msgDispatcher.register(ParticipantMessageType.PARTICIPANT_HEALTH_CHECK.name(),
- applicationContext.getBean(ParticipantHealthCheckListener.class));
+ msgDispatcher.register(ParticipantMessageType.PARTICIPANT_STATUS_REQ.name(),
+ applicationContext.getBean(ParticipantStatusReqListener.class));
msgDispatcher.register(ParticipantMessageType.CONTROL_LOOP_STATE_CHANGE.name(),
applicationContext.getBean(ControlLoopStateChangeListener.class));
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ParticipantHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ParticipantHandler.java
index 9daff7239..6a0e758dd 100644
--- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ParticipantHandler.java
+++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/controlloop/participant/intermediary/handler/ParticipantHandler.java
@@ -32,17 +32,18 @@ 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.ParticipantStatistics;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopAck;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopStateChange;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopUpdate;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregister;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregisterAck;
-import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantHealthCheck;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessage;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessageType;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegister;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegisterAck;
-import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseDetails;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseStatus;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatusReq;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdate;
import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdateAck;
import org.onap.policy.clamp.controlloop.participant.intermediary.comm.MessageSender;
@@ -99,14 +100,15 @@ public class ParticipantHandler implements Closeable {
/**
* Method which handles a participant health check event from clamp.
*
- * @param healthCheckMsg participant health check message
+ * @param participantStatusReqMsg participant participantStatusReq message
*/
- public void handleParticipantHealthCheck(final ParticipantHealthCheck healthCheckMsg) {
- var response = new ParticipantResponseDetails(healthCheckMsg);
- response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
- response.setResponseMessage(healthStatus.toString());
-
- sender.sendResponse(response);
+ public void handleParticipantStatusReq(final ParticipantStatusReq participantStatusReqMsg) {
+ ParticipantStatus participantStatus = new ParticipantStatus();
+ participantStatus.setParticipantId(participantId);
+ participantStatus.setParticipantStatistics(participantStatistics);
+ participantStatus.setParticipantType(participantType);
+ participantStatus.setHealthStatus(healthStatus);
+ sender.sendParticipantStatus(participantStatus);
}
/**
@@ -127,13 +129,13 @@ public class ParticipantHandler implements Closeable {
controlLoopHandler.handleControlLoopStateChange(stateChangeMsg);
}
- private void handleStateChange(ParticipantState newParticipantState, ParticipantResponseDetails response) {
+ private void handleStateChange(ParticipantState newParticipantState, ParticipantUpdateAck response) {
if (state.equals(newParticipantState)) {
- response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
- response.setResponseMessage("Participant already in state " + newParticipantState);
+ response.setResult(false);
+ response.setMessage("Participant already in state " + newParticipantState);
} else {
- response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
- response.setResponseMessage("Participant state changed from " + state + " to " + newParticipantState);
+ response.setResult(true);
+ response.setMessage("Participant state changed from " + state + " to " + newParticipantState);
state = newParticipantState;
}
}
@@ -150,9 +152,10 @@ public class ParticipantHandler implements Closeable {
LOGGER.debug("No participant with this ID {}", definition.getName());
return null;
}
- var response = new ParticipantResponseDetails();
- handleStateChange(participantState, response);
- sender.sendResponse(response);
+
+ var participantUpdateAck = new ParticipantUpdateAck();
+ handleStateChange(participantState, participantUpdateAck);
+ sender.sendParticipantUpdateAck(participantUpdateAck);
return getParticipant(definition.getName(), definition.getVersion());
}
@@ -257,6 +260,8 @@ public class ParticipantHandler implements Closeable {
participantUpdateAck.setResponseTo(messageId);
participantUpdateAck.setMessage("Participant Update Ack message");
participantUpdateAck.setResult(true);
+ participantUpdateAck.setParticipantId(participantId);
+ participantUpdateAck.setParticipantType(participantType);
sender.sendParticipantUpdateAck(participantUpdateAck);
}
@@ -270,7 +275,6 @@ public class ParticipantHandler implements Closeable {
heartbeat.setParticipantStatistics(participantStatistics);
heartbeat.setParticipantType(participantType);
heartbeat.setHealthStatus(healthStatus);
- heartbeat.setMessage("Participant heartbeat message sent from -> " + participantId.getName());
return heartbeat;
}
}
diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounter.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounter.java
new file mode 100644
index 000000000..2151dc143
--- /dev/null
+++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounter.java
@@ -0,0 +1,91 @@
+/*-
+ * ============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.runtime.supervision;
+
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import lombok.Getter;
+import lombok.Setter;
+
+public class HandleCounter<K> {
+ @Getter
+ @Setter
+ private long maxWaitMs;
+
+ @Getter
+ @Setter
+ private int maxRetryCount;
+
+ private Map<K, Integer> mapCounter = new HashMap<>();
+ private Set<K> mapFault = new HashSet<>();
+ private Map<K, Long> mapTimer = new HashMap<>();
+
+ public long getDuration(K id) {
+ mapTimer.putIfAbsent(id, getEpochMilli());
+ return getEpochMilli() - mapTimer.get(id);
+ }
+
+ /**
+ * Reset timer and clear counter and fault by id.
+ *
+ * @param id the id
+ */
+ public void clear(K id) {
+ mapFault.remove(id);
+ mapCounter.put(id, 0);
+ mapTimer.put(id, getEpochMilli());
+ }
+
+ public void setFault(K id) {
+ mapCounter.put(id, 0);
+ mapFault.add(id);
+ }
+
+ /**
+ * Increment RetryCount by id e return true if minor or equal of maxRetryCount.
+ *
+ * @param id the identifier
+ * @return false if count is major of maxRetryCount
+ */
+ public boolean count(K id) {
+ int counter = mapCounter.getOrDefault(id, 0) + 1;
+ if (counter <= maxRetryCount) {
+ mapCounter.put(id, counter);
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isFault(K id) {
+ return mapFault.contains(id);
+ }
+
+ public int getCounter(K id) {
+ return mapCounter.getOrDefault(id, 0);
+ }
+
+ protected long getEpochMilli() {
+ return Instant.now().toEpochMilli();
+ }
+}
diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspect.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspect.java
index 293b5d5da..d0d18ab1a 100644
--- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspect.java
+++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspect.java
@@ -28,6 +28,8 @@ import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
@@ -64,6 +66,11 @@ public class SupervisionAspect implements Closeable {
}
}
+ @Before("@annotation(MessageIntercept) && args(participantStatusMessage,..)")
+ public void handleParticipantStatus(ParticipantStatus participantStatusMessage) {
+ executor.execute(() -> supervisionScanner.handleParticipantStatus(participantStatusMessage.getParticipantId()));
+ }
+
@Override
public void close() throws IOException {
executor.shutdown();
diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java
index dadfe0de2..16dba0f07 100644
--- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java
+++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java
@@ -21,12 +21,14 @@
package org.onap.policy.clamp.controlloop.runtime.supervision;
import java.util.List;
+import java.util.Map;
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.ControlLoopElement;
+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;
import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
@@ -310,39 +312,17 @@ public class SupervisionHandler {
private void superviseControlLoops(ParticipantStatus participantStatusMessage)
throws PfModelException, ControlLoopException {
- if (CollectionUtils.isEmpty(participantStatusMessage.getControlLoops().getControlLoopList())) {
- return;
- }
-
- for (ControlLoop controlLoop : participantStatusMessage.getControlLoops().getControlLoopList()) {
- if (controlLoop == null) {
- exceptionOccured(Response.Status.NOT_FOUND,
- "PARTICIPANT_STATUS message references unknown control loop: " + controlLoop);
- }
-
- var dbControlLoop = controlLoopProvider
- .getControlLoop(new ToscaConceptIdentifier(controlLoop.getName(), controlLoop.getVersion()));
+ for (Map.Entry<ToscaConceptIdentifier, ControlLoopInfo> clEntry :
+ participantStatusMessage.getControlLoopInfoMap().entrySet()) {
+ var dbControlLoop = controlLoopProvider.getControlLoop(new ToscaConceptIdentifier(
+ clEntry.getKey().getName(), clEntry.getKey().getVersion()));
if (dbControlLoop == null) {
exceptionOccured(Response.Status.NOT_FOUND,
- "PARTICIPANT_STATUS control loop not found in database: " + controlLoop);
+ "PARTICIPANT_STATUS control loop not found in database: " + clEntry.getKey());
}
-
- for (ControlLoopElement element : controlLoop.getElements().values()) {
- ControlLoopElement dbElement = dbControlLoop.getElements().get(element.getId());
-
- if (dbElement == null) {
- exceptionOccured(Response.Status.NOT_FOUND,
- "PARTICIPANT_STATUS message references unknown control loop element: " + element);
- }
-
- // Replace element entry in the database
- dbControlLoop.getElements().put(element.getId(), element);
- }
- controlLoopProvider.updateControlLoop(dbControlLoop);
- }
-
- for (ControlLoop controlLoop : participantStatusMessage.getControlLoops().getControlLoopList()) {
- monitoringProvider.createClElementStatistics(controlLoop.getControlLoopElementStatisticsList(controlLoop));
+ dbControlLoop.setState(clEntry.getValue().getState());
+ monitoringProvider.createClElementStatistics(clEntry.getValue()
+ .getControlLoopStatistics().getClElementStatisticsList().getClElementStatistics());
}
}
diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScanner.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScanner.java
index b360f6703..7be407c3f 100644
--- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScanner.java
+++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScanner.java
@@ -20,19 +20,18 @@
package org.onap.policy.clamp.controlloop.runtime.supervision;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import lombok.Getter;
-import lombok.Setter;
+import java.util.List;
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.ControlLoopState;
+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.persistence.provider.ControlLoopProvider;
+import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider;
import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopStateChangePublisher;
import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopUpdatePublisher;
+import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantStatusReqPublisher;
import org.onap.policy.models.base.PfModelException;
import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
import org.slf4j.Logger;
@@ -46,67 +45,49 @@ import org.springframework.stereotype.Component;
public class SupervisionScanner {
private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionScanner.class);
- @Getter
- @Setter
- static class HandleCounter {
- private int maxRetryCount;
- private long maxWaitMs;
- private Map<ToscaConceptIdentifier, Integer> mapCounter = new HashMap<>();
- private Set<ToscaConceptIdentifier> mapFault = new HashSet<>();
-
- public void clear(ToscaConceptIdentifier id) {
- mapCounter.put(id, 0);
- mapFault.remove(id);
- }
-
- public void setFault(ToscaConceptIdentifier id) {
- mapCounter.put(id, 0);
- mapFault.add(id);
- }
-
- public boolean count(ToscaConceptIdentifier id) {
- int counter = mapCounter.getOrDefault(id, 0) + 1;
- if (counter <= maxRetryCount) {
- mapCounter.put(id, counter);
- return true;
- }
- return false;
- }
-
- public boolean isFault(ToscaConceptIdentifier id) {
- return mapFault.contains(id);
- }
-
- public int getCounter(ToscaConceptIdentifier id) {
- return mapCounter.getOrDefault(id, 0);
- }
- }
-
- private HandleCounter stateChange = new HandleCounter();
+ private HandleCounter<ToscaConceptIdentifier> controlLoopCounter = new HandleCounter<>();
+ private HandleCounter<ToscaConceptIdentifier> participantCounter = new HandleCounter<>();
private final ControlLoopProvider controlLoopProvider;
private final ControlLoopStateChangePublisher controlLoopStateChangePublisher;
private final ControlLoopUpdatePublisher controlLoopUpdatePublisher;
+ private final ParticipantProvider participantProvider;
+ private final ParticipantStatusReqPublisher participantStatusReqPublisher;
+
+ private final long maxMessageAgeMs;
/**
* Constructor for instantiating SupervisionScanner.
*
* @param controlLoopProvider the provider to use to read control loops from the database
- * @param controlLoopStateChangePublisher the ControlLoopStateChange Publisher
+ * @param controlLoopStateChangePublisher the ControlLoop StateChange Publisher
+ * @param controlLoopUpdatePublisher the ControlLoopUpdate Publisher
+ * @param participantProvider the Participant Provider
+ * @param participantStatusReqPublisher the Participant StatusReq Publisher
* @param clRuntimeParameterGroup the parameters for the control loop runtime
*/
public SupervisionScanner(final ControlLoopProvider controlLoopProvider,
final ControlLoopStateChangePublisher controlLoopStateChangePublisher,
- ControlLoopUpdatePublisher controlLoopUpdatePublisher,
+ ControlLoopUpdatePublisher controlLoopUpdatePublisher, ParticipantProvider participantProvider,
+ ParticipantStatusReqPublisher participantStatusReqPublisher,
final ClRuntimeParameterGroup clRuntimeParameterGroup) {
this.controlLoopProvider = controlLoopProvider;
this.controlLoopStateChangePublisher = controlLoopStateChangePublisher;
this.controlLoopUpdatePublisher = controlLoopUpdatePublisher;
+ this.participantProvider = participantProvider;
+ this.participantStatusReqPublisher = participantStatusReqPublisher;
+
+ controlLoopCounter.setMaxRetryCount(
+ clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
+ controlLoopCounter
+ .setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs());
- stateChange.setMaxRetryCount(
+ participantCounter.setMaxRetryCount(
clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount());
- stateChange.setMaxWaitMs(
- clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs());
+ participantCounter
+ .setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs());
+
+ maxMessageAgeMs = clRuntimeParameterGroup.getParticipantParameters().getMaxMessageAgeMs();
}
/**
@@ -117,6 +98,17 @@ public class SupervisionScanner {
public void run(boolean counterCheck) {
LOGGER.debug("Scanning control loops in the database . . .");
+ if (counterCheck) {
+ try {
+ for (Participant participant : participantProvider.getParticipants(null, null)) {
+ scanParticipant(participant);
+ }
+ } catch (PfModelException pfme) {
+ LOGGER.warn("error reading participant from database", pfme);
+ return;
+ }
+ }
+
try {
for (ControlLoop controlLoop : controlLoopProvider.getControlLoops(null, null)) {
scanControlLoop(controlLoop, counterCheck);
@@ -128,6 +120,33 @@ public class SupervisionScanner {
LOGGER.debug("Control loop scan complete . . .");
}
+ private void scanParticipant(Participant participant) throws PfModelException {
+ ToscaConceptIdentifier id = participant.getKey().asIdentifier();
+ if (participantCounter.isFault(id)) {
+ LOGGER.debug("report Participant fault");
+ return;
+ }
+ if (participantCounter.getDuration(id) > maxMessageAgeMs) {
+ if (participantCounter.count(id)) {
+ LOGGER.debug("retry message ParticipantStatusReq");
+ participantStatusReqPublisher.send(id);
+ participant.setHealthStatus(ParticipantHealthStatus.NOT_HEALTHY);
+ } else {
+ LOGGER.debug("report Participant fault");
+ participantCounter.setFault(id);
+ participant.setHealthStatus(ParticipantHealthStatus.OFF_LINE);
+ }
+ participantProvider.updateParticipants(List.of(participant));
+ }
+ }
+
+ /**
+ * handle participant Status message.
+ */
+ public void handleParticipantStatus(ToscaConceptIdentifier id) {
+ participantCounter.clear(id);
+ }
+
private void scanControlLoop(final ControlLoop controlLoop, boolean counterCheck) throws PfModelException {
LOGGER.debug("scanning control loop {} . . .", controlLoop.getKey().asIdentifier());
@@ -166,17 +185,17 @@ public class SupervisionScanner {
}
private void clearFaultAndCounter(ControlLoop controlLoop) {
- stateChange.clear(controlLoop.getKey().asIdentifier());
+ controlLoopCounter.clear(controlLoop.getKey().asIdentifier());
}
private void handleCounter(ControlLoop controlLoop) {
ToscaConceptIdentifier id = controlLoop.getKey().asIdentifier();
- if (stateChange.isFault(id)) {
+ if (controlLoopCounter.isFault(id)) {
LOGGER.debug("report ControlLoop fault");
return;
}
- if (stateChange.count(id)) {
+ if (controlLoopCounter.count(id)) {
if (ControlLoopState.UNINITIALISED2PASSIVE.equals(controlLoop.getState())) {
LOGGER.debug("retry message ControlLoopUpdate");
controlLoopUpdatePublisher.send(controlLoop);
@@ -186,7 +205,7 @@ public class SupervisionScanner {
}
} else {
LOGGER.debug("report ControlLoop fault");
- stateChange.setFault(id);
+ controlLoopCounter.setFault(id);
}
}
}
diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusReqPublisher.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusReqPublisher.java
new file mode 100644
index 000000000..69d598285
--- /dev/null
+++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusReqPublisher.java
@@ -0,0 +1,48 @@
+/*-
+ * ============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.runtime.supervision.comm;
+
+import java.time.Instant;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatusReq;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ParticipantStatusReqPublisher extends AbstractParticipantPublisher<ParticipantStatusReq> {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantStatusReqPublisher.class);
+
+ /**
+ * Send ParticipantStatusReq to Participant.
+ *
+ * @param participantId the participant Id
+ */
+ public void send(ToscaConceptIdentifier participantId) {
+ ParticipantStatusReq message = new ParticipantStatusReq();
+ message.setParticipantId(participantId);
+ message.setTimestamp(Instant.now());
+
+ LOGGER.debug("Participant StatusReq sent {}", message);
+ super.send(message);
+ }
+}
diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounterTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounterTest.java
new file mode 100644
index 000000000..51f3b4a32
--- /dev/null
+++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounterTest.java
@@ -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.runtime.supervision;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class HandleCounterTest {
+
+ private static final int ID = 1;
+
+ @Test
+ void testCount() {
+ var handleCounter = new HandleCounter<Integer>();
+ handleCounter.setMaxRetryCount(2);
+ assertThat(handleCounter.count(ID)).isTrue();
+ assertThat(handleCounter.getCounter(ID)).isEqualTo(1);
+ assertThat(handleCounter.count(ID)).isTrue();
+ assertThat(handleCounter.getCounter(ID)).isEqualTo(2);
+ assertThat(handleCounter.count(ID)).isFalse();
+ assertThat(handleCounter.getCounter(ID)).isEqualTo(2);
+
+ handleCounter.clear(ID);
+ assertThat(handleCounter.count(ID)).isTrue();
+ assertThat(handleCounter.getCounter(ID)).isEqualTo(1);
+ }
+
+ @Test
+ void testFault() {
+ var handleCounter = new HandleCounter<Integer>();
+ handleCounter.setFault(ID);
+ assertThat(handleCounter.isFault(ID)).isTrue();
+ handleCounter.clear(ID);
+ assertThat(handleCounter.isFault(ID)).isFalse();
+ }
+
+ @Test
+ void testDuration() throws InterruptedException {
+
+ var handleCounter = new HandleCounter<Integer>() {
+ long epochMilli = 0;
+
+ @Override
+ protected long getEpochMilli() {
+ return epochMilli;
+ }
+ };
+ handleCounter.epochMilli = 100;
+ var result = handleCounter.getDuration(ID);
+ assertThat(result).isZero();
+
+ handleCounter.epochMilli += 100;
+ result = handleCounter.getDuration(ID);
+ assertThat(result).isEqualTo(100);
+
+ handleCounter.epochMilli += 100;
+ result = handleCounter.getDuration(ID);
+ assertThat(result).isEqualTo(200);
+
+ handleCounter.epochMilli += 100;
+ handleCounter.clear(ID);
+ result = handleCounter.getDuration(ID);
+ assertThat(result).isZero();
+ }
+}
diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspectTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspectTest.java
new file mode 100644
index 000000000..30ee9b1b9
--- /dev/null
+++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspectTest.java
@@ -0,0 +1,66 @@
+/*-
+ * ============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.runtime.supervision;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import org.junit.jupiter.api.Test;
+import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+class SupervisionAspectTest {
+
+ @Test
+ void testSchedule() throws Exception {
+ var supervisionScanner = spy(mock(SupervisionScanner.class));
+ try (var supervisionAspect = new SupervisionAspect(supervisionScanner)) {
+ supervisionAspect.schedule();
+ verify(supervisionScanner, timeout(500)).run(eq(true));
+ }
+ }
+
+ @Test
+ void testDoCheck() throws Exception {
+ var supervisionScanner = spy(mock(SupervisionScanner.class));
+ try (var supervisionAspect = new SupervisionAspect(supervisionScanner)) {
+ supervisionAspect.doCheck();
+ supervisionAspect.doCheck();
+ verify(supervisionScanner, timeout(500).times(2)).run(eq(false));
+ }
+ }
+
+ @Test
+ void testHandleParticipantStatus() throws Exception {
+ var supervisionScanner = spy(mock(SupervisionScanner.class));
+ var participantStatusMessage = new ParticipantStatus();
+ var identifier = new ToscaConceptIdentifier("abc", "1.0.0");
+ participantStatusMessage.setParticipantId(identifier);
+
+ try (var supervisionAspect = new SupervisionAspect(supervisionScanner)) {
+ supervisionAspect.handleParticipantStatus(participantStatusMessage);
+ verify(supervisionScanner, timeout(500)).handleParticipantStatus(eq(identifier));
+ }
+ }
+}
diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScannerTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScannerTest.java
new file mode 100644
index 000000000..485f58dba
--- /dev/null
+++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScannerTest.java
@@ -0,0 +1,160 @@
+/*-
+ * ============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.runtime.supervision;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+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;
+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.persistence.provider.ControlLoopProvider;
+import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider;
+import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopStateChangePublisher;
+import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopUpdatePublisher;
+import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantStatusReqPublisher;
+import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+class SupervisionScannerTest {
+
+ @Test
+ void testScannerOrderedStateEqualsToState() throws PfModelException {
+ var controlLoopProvider = mock(ControlLoopProvider.class);
+ var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class);
+ var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class);
+ var participantProvider = mock(ParticipantProvider.class);
+ var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class);
+ var clRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
+
+ var controlLoop = new ControlLoop();
+ when(controlLoopProvider.getControlLoops(null, null)).thenReturn(List.of(controlLoop));
+
+ var supervisionScanner =
+ new SupervisionScanner(controlLoopProvider, controlLoopStateChangePublisher, controlLoopUpdatePublisher,
+ participantProvider, participantStatusReqPublisher, clRuntimeParameterGroup);
+ supervisionScanner.run(false);
+
+ verify(controlLoopProvider, times(0)).updateControlLoop(any(ControlLoop.class));
+ }
+
+ @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()));
+ var controlLoopProvider = mock(ControlLoopProvider.class);
+ when(controlLoopProvider.getControlLoops(null, null)).thenReturn(List.of(controlLoop));
+
+ var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class);
+ var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class);
+ var participantProvider = mock(ParticipantProvider.class);
+ var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class);
+ var clRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
+
+ var supervisionScanner =
+ new SupervisionScanner(controlLoopProvider, controlLoopStateChangePublisher, controlLoopUpdatePublisher,
+ participantProvider, participantStatusReqPublisher, clRuntimeParameterGroup);
+ supervisionScanner.run(false);
+
+ verify(controlLoopProvider, times(1)).updateControlLoop(any(ControlLoop.class));
+ }
+
+ @Test
+ void testScanner() throws PfModelException {
+ var controlLoopProvider = mock(ControlLoopProvider.class);
+ var controlLoop = new ControlLoop();
+ when(controlLoopProvider.getControlLoops(null, null)).thenReturn(List.of(controlLoop));
+
+ var participantProvider = mock(ParticipantProvider.class);
+ var participant = new Participant();
+ participant.setName("Participant0");
+ participant.setVersion("1.0.0");
+ when(participantProvider.getParticipants(null, null)).thenReturn(List.of(participant));
+
+ var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class);
+ var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class);
+ var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class);
+ var clRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
+
+ var supervisionScanner =
+ new SupervisionScanner(controlLoopProvider, controlLoopStateChangePublisher, controlLoopUpdatePublisher,
+ participantProvider, participantStatusReqPublisher, clRuntimeParameterGroup);
+
+ supervisionScanner.handleParticipantStatus(participant.getKey().asIdentifier());
+ supervisionScanner.run(true);
+ verify(controlLoopProvider, times(0)).updateControlLoop(any(ControlLoop.class));
+ verify(participantStatusReqPublisher, times(0)).send(any(ToscaConceptIdentifier.class));
+ }
+
+ @Test
+ void testScanParticipant() throws PfModelException {
+ var controlLoopProvider = mock(ControlLoopProvider.class);
+ var controlLoop = new ControlLoop();
+ when(controlLoopProvider.getControlLoops(null, null)).thenReturn(List.of(controlLoop));
+
+ var clRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanParticipant");
+ clRuntimeParameterGroup.getParticipantParameters().setMaxMessageAgeMs(0);
+
+ var participant = new Participant();
+ participant.setName("Participant0");
+ participant.setVersion("1.0.0");
+ participant.setHealthStatus(ParticipantHealthStatus.HEALTHY);
+ participant.setParticipantState(ParticipantState.ACTIVE);
+ participant.setDefinition(new ToscaConceptIdentifier("unknown", "0.0.0"));
+ var participantProvider = new ParticipantProvider(clRuntimeParameterGroup.getDatabaseProviderParameters());
+ participantProvider.updateParticipants(List.of(participant));
+
+ var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class);
+ var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class);
+ var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class);
+
+ var supervisionScanner =
+ new SupervisionScanner(controlLoopProvider, controlLoopStateChangePublisher, controlLoopUpdatePublisher,
+ participantProvider, participantStatusReqPublisher, clRuntimeParameterGroup);
+
+ supervisionScanner.handleParticipantStatus(participant.getKey().asIdentifier());
+ supervisionScanner.run(true);
+ verify(participantStatusReqPublisher, times(1)).send(any(ToscaConceptIdentifier.class));
+
+ List<Participant> participants = participantProvider.getParticipants(null, null);
+ assertThat(participants.get(0).getHealthStatus()).isEqualTo(ParticipantHealthStatus.NOT_HEALTHY);
+
+ supervisionScanner.run(true);
+ supervisionScanner.run(true);
+ participants = participantProvider.getParticipants(null, null);
+ assertThat(participants.get(0).getHealthStatus()).isEqualTo(ParticipantHealthStatus.OFF_LINE);
+ }
+}