diff options
Diffstat (limited to 'tosca-controlloop')
17 files changed, 1566 insertions, 117 deletions
diff --git a/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ClElementStatistics.java b/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ClElementStatistics.java index ec96830e2..014323090 100644 --- a/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ClElementStatistics.java +++ b/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ClElementStatistics.java @@ -22,21 +22,23 @@ package org.onap.policy.clamp.controlloop.models.controlloop.concepts; import java.io.Serializable; import java.time.Instant; +import java.util.UUID; 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 ClElementStatistics implements Serializable { private static final long serialVersionUID = 3284285693112271055L; @NonNull - private ToscaConceptIdentifier controlLoopElementId; + private UUID id = UUID.randomUUID(); + + @NonNull + private ToscaConceptIdentifier participantId; @NonNull private Instant timeStamp; diff --git a/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaClElementStatistics.java b/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaClElementStatistics.java index abe0737f6..ec5dbb32c 100644 --- a/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaClElementStatistics.java +++ b/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaClElementStatistics.java @@ -22,16 +22,18 @@ package org.onap.policy.clamp.controlloop.models.controlloop.persistence.concept import java.io.Serializable; import java.util.List; +import java.util.UUID; import javax.persistence.AttributeOverride; +import javax.persistence.AttributeOverrides; import javax.persistence.Column; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.Table; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; import lombok.NonNull; import org.apache.commons.lang3.builder.CompareToBuilder; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatistics; @@ -41,7 +43,7 @@ import org.onap.policy.models.base.PfAuthorative; import org.onap.policy.models.base.PfConcept; import org.onap.policy.models.base.PfConceptKey; import org.onap.policy.models.base.PfKey; -import org.onap.policy.models.base.PfTimestampKey; +import org.onap.policy.models.base.PfReferenceTimestampKey; import org.onap.policy.models.base.validation.annotations.VerifyKey; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; @@ -54,7 +56,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; @Table(name = "ClElementStatistics") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Data -@NoArgsConstructor +@AllArgsConstructor @EqualsAndHashCode(callSuper = false) public class JpaClElementStatistics extends PfConcept implements PfAuthorative<ClElementStatistics>, Serializable { @@ -63,14 +65,15 @@ public class JpaClElementStatistics extends PfConcept implements PfAuthorative<C @EmbeddedId @VerifyKey @NotNull - private PfTimestampKey key = new PfTimestampKey(); + private PfReferenceTimestampKey key = new PfReferenceTimestampKey(); + @VerifyKey @NotNull // @formatter:off - @AttributeOverride(name = "name", column = @Column(name = "cl_element_name")) - @AttributeOverride(name = "version", column = @Column(name = "cl_element_version")) - private PfConceptKey clElementId; + @AttributeOverride(name = "name", column = @Column(name = "participant_name")) + @AttributeOverride(name = "version", column = @Column(name = "participant_version")) + private PfConceptKey participantId; // @formatter: on @Column @@ -80,24 +83,34 @@ public class JpaClElementStatistics extends PfConcept implements PfAuthorative<C @Column private long clElementUptime; + /** - * The Key Constructor creates a {@link JpaClElementStatistics} object with the given Timestamp key. + * The Default Constructor creates a {@link JpaClElementStatistics} object with a null key. + */ + public JpaClElementStatistics() { + this(new PfReferenceTimestampKey()); + } + + + /** + * The Key Constructor creates a {@link JpaClElementStatistics} object with the given Reference Timestamp key. * * @param key the key */ - public JpaClElementStatistics(@NonNull final PfTimestampKey key) { - this(key, new PfConceptKey()); + public JpaClElementStatistics(@NonNull final PfReferenceTimestampKey key) { + this(key, new PfConceptKey(), ControlLoopState.PASSIVE, 0L); } /** * The Key Constructor creates a {@link JpaClElementStatistics} object with all mandatory fields. * * @param key the key - * @param clElementId the TOSCA definition of the control loop element + * @param participantId the TOSCA definition of the control loop element */ - public JpaClElementStatistics(@NonNull final PfTimestampKey key, @NonNull final PfConceptKey clElementId) { + public JpaClElementStatistics(@NonNull final PfReferenceTimestampKey key, + @NonNull final PfConceptKey participantId) { this.key = key; - this.clElementId = clElementId; + this.participantId = participantId; } /** @@ -107,8 +120,8 @@ public class JpaClElementStatistics extends PfConcept implements PfAuthorative<C */ public JpaClElementStatistics(@NonNull final JpaClElementStatistics copyConcept) { super(copyConcept); - this.key = new PfTimestampKey(copyConcept.key); - this.clElementId = new PfConceptKey(copyConcept.clElementId); + this.key = new PfReferenceTimestampKey(copyConcept.key); + this.participantId = new PfConceptKey(copyConcept.participantId); this.state = copyConcept.state; this.clElementUptime = copyConcept.clElementUptime; } @@ -123,11 +136,14 @@ public class JpaClElementStatistics extends PfConcept implements PfAuthorative<C this.fromAuthorative(authorativeConcept); } + + @Override public ClElementStatistics toAuthorative() { ClElementStatistics clElementStatistics = new ClElementStatistics(); - clElementStatistics.setTimeStamp(key.getTimeStamp().toInstant()); - clElementStatistics.setControlLoopElementId(new ToscaConceptIdentifier(clElementId)); + clElementStatistics.setId(UUID.fromString(getKey().getReferenceKey().getLocalName())); + clElementStatistics.setTimeStamp(key.getInstant()); + clElementStatistics.setParticipantId(new ToscaConceptIdentifier(participantId)); clElementStatistics.setControlLoopState(state); clElementStatistics.setClElementUptime(clElementUptime); @@ -138,14 +154,12 @@ public class JpaClElementStatistics extends PfConcept implements PfAuthorative<C public void fromAuthorative(@NonNull ClElementStatistics clElementStatistics) { // @formatter:off if (this.key == null || this.getKey().isNullKey()) { - this.setKey( - new PfTimestampKey( - clElementStatistics.getControlLoopElementId().getName(), - clElementStatistics.getControlLoopElementId().getVersion(), - clElementStatistics.getTimeStamp())); + this.setKey(new PfReferenceTimestampKey(clElementStatistics.getParticipantId().getName(), + clElementStatistics.getParticipantId().getVersion(), clElementStatistics.getId().toString(), + clElementStatistics.getTimeStamp())); } // @formatter:on - this.setClElementId(clElementStatistics.getControlLoopElementId().asConceptKey()); + this.setParticipantId(clElementStatistics.getParticipantId().asConceptKey()); this.setState(clElementStatistics.getControlLoopState()); this.setClElementUptime(clElementStatistics.getClElementUptime()); } @@ -158,7 +172,7 @@ public class JpaClElementStatistics extends PfConcept implements PfAuthorative<C @Override public void clean() { key.clean(); - clElementId.clean(); + participantId.clean(); } @@ -176,6 +190,6 @@ public class JpaClElementStatistics extends PfConcept implements PfAuthorative<C final JpaClElementStatistics other = (JpaClElementStatistics) otherConcept; return new CompareToBuilder().append(this.key, other.key).append(this.state, other.state) - .append(this.clElementUptime, other.clElementUptime).toComparison(); + .append(this.clElementUptime, other.clElementUptime).toComparison(); } } diff --git a/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaParticipantStatistics.java b/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaParticipantStatistics.java index 84c7f0d59..b97f9ed69 100644 --- a/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaParticipantStatistics.java +++ b/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaParticipantStatistics.java @@ -53,7 +53,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; * @author Ramesh Murugan Iyer (ramesh.murugan.iyer@est.tech) */ @Entity -@Table(name = "ControlLoopStatistics") +@Table(name = "ParticipantStatistics") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Data @AllArgsConstructor diff --git a/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ClElementStatisticsProvider.java b/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ClElementStatisticsProvider.java index 1250dfce0..c09658f80 100644 --- a/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ClElementStatisticsProvider.java +++ b/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ClElementStatisticsProvider.java @@ -32,7 +32,7 @@ import org.onap.policy.clamp.controlloop.models.controlloop.persistence.concepts import org.onap.policy.common.parameters.BeanValidationResult; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; -import org.onap.policy.models.base.PfTimestampKey; +import org.onap.policy.models.base.PfReferenceTimestampKey; import org.onap.policy.models.provider.PolicyModelsProviderParameters; import org.onap.policy.models.provider.impl.AbstractModelsProvider; @@ -62,10 +62,10 @@ public class ClElementStatisticsProvider extends AbstractModelsProvider { * @throws PfModelException on errors creating clElement statistics */ public List<ClElementStatistics> createClElementStatistics( - @NonNull final List<ClElementStatistics> clElementStatisticsList) throws PfModelException { + @NonNull final List<ClElementStatistics> clElementStatisticsList) throws PfModelException { BeanValidationResult validationResult = - new BeanValidationResult("control loop element statistics list", clElementStatisticsList); + new BeanValidationResult("control loop element statistics list", clElementStatisticsList); for (ClElementStatistics clElementStatistics : clElementStatisticsList) { JpaClElementStatistics jpaClElementStatistics = new JpaClElementStatistics(); jpaClElementStatistics.fromAuthorative(clElementStatistics); @@ -80,7 +80,6 @@ public class ClElementStatisticsProvider extends AbstractModelsProvider { for (ClElementStatistics clElementStatistics : clElementStatisticsList) { JpaClElementStatistics jpaClElementStatistics = new JpaClElementStatistics(); jpaClElementStatistics.fromAuthorative(clElementStatistics); - getPfDao().create(jpaClElementStatistics); } @@ -89,8 +88,9 @@ public class ClElementStatisticsProvider extends AbstractModelsProvider { for (ClElementStatistics clElementStat : clElementStatisticsList) { JpaClElementStatistics jpaClElementStatistics = getPfDao().get(JpaClElementStatistics.class, - new PfTimestampKey(clElementStat.getControlLoopElementId().getName(), - clElementStat.getControlLoopElementId().getVersion(), clElementStat.getTimeStamp())); + new PfReferenceTimestampKey(clElementStat.getParticipantId().getName(), + clElementStat.getParticipantId().getVersion(), clElementStat.getId().toString(), + clElementStat.getTimeStamp())); elementStatistics.add(jpaClElementStatistics.toAuthorative()); } @@ -110,21 +110,28 @@ public class ClElementStatisticsProvider extends AbstractModelsProvider { /** * Get clElement statistics. * - * @param name the name of the clElement statistics to get, null to get all stats + * @param name the name of the participant + * @param version version of the participant + * @param id of the control loop element + * @param timestamp timestamp of the statistics * @return the clElement statistics found * @throws PfModelException on errors getting clElement statistics */ - public List<ClElementStatistics> getClElementStatistics(final String name, final String version, - final Instant timestamp) throws PfModelException { - - if (name != null && version != null && timestamp != null) { - List<ClElementStatistics> clElementStatistics = new ArrayList<>(1); + public List<ClElementStatistics> getClElementStatistics(final String name, final String version, final String id, + final Instant timestamp) throws PfModelException { + List<ClElementStatistics> clElementStatistics = new ArrayList<>(1); + if (name != null && version != null && timestamp != null && id != null) { clElementStatistics.add(getPfDao() - .get(JpaClElementStatistics.class, new PfTimestampKey(name, version, timestamp)).toAuthorative()); + .get(JpaClElementStatistics.class, new PfReferenceTimestampKey(name, version, id, timestamp)) + .toAuthorative()); return clElementStatistics; + } else if (name != null) { + clElementStatistics.addAll(getFilteredClElementStatistics(name, version, null, null, null, + "DESC", 0)); } else { - return asClElementStatisticsList(getPfDao().getAll(JpaClElementStatistics.class)); + clElementStatistics.addAll(asClElementStatisticsList(getPfDao().getAll(JpaClElementStatistics.class))); } + return clElementStatistics; } /** @@ -139,9 +146,11 @@ public class ClElementStatisticsProvider extends AbstractModelsProvider { * @throws PfModelException on errors getting policies */ public List<ClElementStatistics> getFilteredClElementStatistics(final String name, final String version, - final Instant startTimeStamp, final Instant endTimeStamp, Map<String, Object> filterMap, - final String sortOrder, final int getRecordNum) { + final Instant startTimeStamp, + final Instant endTimeStamp, + Map<String, Object> filterMap, + final String sortOrder, final int getRecordNum) { return asClElementStatisticsList(getPfDao().getFiltered(JpaClElementStatistics.class, name, version, - startTimeStamp, endTimeStamp, filterMap, sortOrder, getRecordNum)); + startTimeStamp, endTimeStamp, filterMap, sortOrder, getRecordNum)); } } diff --git a/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ParticipantStatisticsProvider.java b/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ParticipantStatisticsProvider.java index 3cbe901ab..ebb81942b 100644 --- a/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ParticipantStatisticsProvider.java +++ b/tosca-controlloop/models/src/main/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ParticipantStatisticsProvider.java @@ -62,13 +62,16 @@ public class ParticipantStatisticsProvider extends AbstractModelsProvider { * @throws PfModelException on errors getting participant statistics */ public List<ParticipantStatistics> getParticipantStatistics(final String name, final String version, - final Instant timestamp) throws PfModelException { + final Instant timestamp) throws PfModelException { if (name != null && version != null && timestamp != null) { List<ParticipantStatistics> participantStatistics = new ArrayList<>(1); participantStatistics.add(getPfDao() - .get(JpaParticipantStatistics.class, new PfTimestampKey(name, version, timestamp)).toAuthorative()); + .get(JpaParticipantStatistics.class, new PfTimestampKey(name, version, timestamp)).toAuthorative()); return participantStatistics; + } else if (name != null) { + return getFilteredParticipantStatistics(name, version, timestamp, null, null, + "DESC", 0); } else { return asParticipantStatisticsList(getPfDao().getAll(JpaParticipantStatistics.class)); } @@ -87,11 +90,14 @@ public class ParticipantStatisticsProvider extends AbstractModelsProvider { * @throws PfModelException on errors getting policies */ public List<ParticipantStatistics> getFilteredParticipantStatistics(final String name, final String version, - final Instant startTimeStamp, final Instant endTimeStamp, Map<String, Object> filterMap, - final String sortOrder, final int getRecordNum) { + final Instant startTimeStamp, + final Instant endTimeStamp, + Map<String, Object> filterMap, + final String sortOrder, + final int getRecordNum) { return asParticipantStatisticsList(getPfDao().getFiltered(JpaParticipantStatistics.class, name, version, - startTimeStamp, endTimeStamp, filterMap, sortOrder, getRecordNum)); + startTimeStamp, endTimeStamp, filterMap, sortOrder, getRecordNum)); } @@ -103,10 +109,10 @@ public class ParticipantStatisticsProvider extends AbstractModelsProvider { * @throws PfModelException on errors creating participant statistics */ public List<ParticipantStatistics> createParticipantStatistics( - @NonNull final List<ParticipantStatistics> participantStatisticsList) throws PfModelException { + @NonNull final List<ParticipantStatistics> participantStatisticsList) throws PfModelException { BeanValidationResult validationResult = - new BeanValidationResult("participant statistics List", participantStatisticsList); + new BeanValidationResult("participant statistics List", participantStatisticsList); for (ParticipantStatistics participantStatistics : participantStatisticsList) { JpaParticipantStatistics jpaParticipantStatistics = new JpaParticipantStatistics(); @@ -131,9 +137,9 @@ public class ParticipantStatisticsProvider extends AbstractModelsProvider { for (ParticipantStatistics participantStatisticsItem : participantStatisticsList) { JpaParticipantStatistics jpaParticipantStatistics = getPfDao().get(JpaParticipantStatistics.class, - new PfTimestampKey(participantStatisticsItem.getParticipantId().getName(), - participantStatisticsItem.getParticipantId().getVersion(), - participantStatisticsItem.getTimeStamp())); + new PfTimestampKey(participantStatisticsItem.getParticipantId().getName(), + participantStatisticsItem.getParticipantId().getVersion(), + participantStatisticsItem.getTimeStamp())); participantStatistics.add(jpaParticipantStatistics.toAuthorative()); } @@ -148,9 +154,9 @@ public class ParticipantStatisticsProvider extends AbstractModelsProvider { * @return the participant statistics list */ private List<ParticipantStatistics> asParticipantStatisticsList( - List<JpaParticipantStatistics> jpaParticipantStatisticsList) { + List<JpaParticipantStatistics> jpaParticipantStatisticsList) { return jpaParticipantStatisticsList.stream().map(JpaParticipantStatistics::toAuthorative) - .collect(Collectors.toList()); + .collect(Collectors.toList()); } } diff --git a/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ClElementStatisticsTest.java b/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ClElementStatisticsTest.java index 5318fcfc3..0addc25ad 100644 --- a/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ClElementStatisticsTest.java +++ b/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/concepts/ClElementStatisticsTest.java @@ -27,6 +27,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import java.time.Instant; +import java.util.UUID; import org.junit.Test; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; @@ -43,7 +44,7 @@ public class ClElementStatisticsTest { ClElementStatistics cles1 = new ClElementStatistics(); - cles1.setControlLoopElementId(new ToscaConceptIdentifier("defName", "0.0.1")); + cles1.setParticipantId(new ToscaConceptIdentifier("defName", "0.0.1")); cles1.setTimeStamp(Instant.now()); assertThat(cles1.toString()).contains("ClElementStatistics("); @@ -54,12 +55,13 @@ public class ClElementStatisticsTest { assertNotEquals(cles1, cles0); ClElementStatistics cles2 = new ClElementStatistics(); + cles2.setId(UUID.randomUUID()); // @formatter:off - assertThatThrownBy(() -> cles2.setControlLoopElementId(null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> cles2.setTimeStamp(null)). isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> cles2.setParticipantId(null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> cles2.setTimeStamp(null)).isInstanceOf(NullPointerException.class); // @formatter:on - assertEquals(cles2, cles0); + assertNotEquals(cles2, cles0); } } diff --git a/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaClElementStatisticsTest.java b/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaClElementStatisticsTest.java index 5c41d9647..c82dcf060 100644 --- a/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaClElementStatisticsTest.java +++ b/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/concepts/JpaClElementStatisticsTest.java @@ -28,12 +28,13 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.time.Instant; +import java.util.UUID; import org.junit.Test; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatistics; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant; import org.onap.policy.models.base.PfConceptKey; -import org.onap.policy.models.base.PfTimestampKey; +import org.onap.policy.models.base.PfReferenceTimestampKey; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; /** @@ -50,7 +51,7 @@ public class JpaClElementStatisticsTest { }).hasMessageMatching("copyConcept is marked .*ull but is null"); assertThatThrownBy(() -> { - new JpaClElementStatistics((PfTimestampKey) null); + new JpaClElementStatistics((PfReferenceTimestampKey) null); }).hasMessageMatching(NULL_KEY_ERROR); assertThatThrownBy(() -> { @@ -62,12 +63,12 @@ public class JpaClElementStatisticsTest { }).hasMessageMatching(NULL_KEY_ERROR); assertThatThrownBy(() -> { - new JpaClElementStatistics(new PfTimestampKey(), null); - }).hasMessageMatching("clElementId is marked .*ull but is null"); + new JpaClElementStatistics(new PfReferenceTimestampKey(), null); + }).hasMessageMatching("participantId is marked .*ull but is null"); assertNotNull(new JpaClElementStatistics()); - assertNotNull(new JpaClElementStatistics((new PfTimestampKey()))); - assertNotNull(new JpaClElementStatistics(new PfTimestampKey(), new PfConceptKey())); + assertNotNull(new JpaClElementStatistics((new PfReferenceTimestampKey()))); + assertNotNull(new JpaClElementStatistics(new PfReferenceTimestampKey(), new PfConceptKey())); } @Test @@ -82,16 +83,17 @@ public class JpaClElementStatisticsTest { }).hasMessageMatching("clElementStatistics is marked .*ull but is null"); assertThatThrownBy(() -> new JpaClElementStatistics((JpaClElementStatistics) null)) - .isInstanceOf(NullPointerException.class); + .isInstanceOf(NullPointerException.class); JpaClElementStatistics testJpaClElementStatisticsFa = new JpaClElementStatistics(); testJpaClElementStatisticsFa.setKey(null); testJpaClElementStatisticsFa.fromAuthorative(cles); assertEquals(testJpaClElementStatistics, testJpaClElementStatisticsFa); - testJpaClElementStatisticsFa.setKey(PfTimestampKey.getNullKey()); + testJpaClElementStatisticsFa.setKey(PfReferenceTimestampKey.getNullKey()); testJpaClElementStatisticsFa.fromAuthorative(cles); assertEquals(testJpaClElementStatistics, testJpaClElementStatisticsFa); - testJpaClElementStatisticsFa.setKey(new PfTimestampKey("elementName", "0.0.1", Instant.ofEpochMilli(123456L))); + testJpaClElementStatisticsFa.setKey(new PfReferenceTimestampKey("elementName", "0.0.1", + "a95757ba-b34a-4049-a2a8-46773abcbe5e", Instant.ofEpochSecond(123456L))); testJpaClElementStatisticsFa.fromAuthorative(cles); assertEquals(testJpaClElementStatistics, testJpaClElementStatisticsFa); @@ -100,10 +102,10 @@ public class JpaClElementStatisticsTest { assertEquals(1, testJpaClElementStatistics.getKeys().size()); - assertEquals("elementName", testJpaClElementStatistics.getKey().getName()); + assertEquals("elementName", testJpaClElementStatistics.getKey().getReferenceKey().getParentKeyName()); testJpaClElementStatistics.clean(); - assertEquals("elementName", testJpaClElementStatistics.getKey().getName()); + assertEquals("elementName", testJpaClElementStatistics.getKey().getReferenceKey().getParentKeyName()); JpaClElementStatistics testJpaClElementStatistics2 = new JpaClElementStatistics(testJpaClElementStatistics); assertEquals(testJpaClElementStatistics, testJpaClElementStatistics2); @@ -121,7 +123,7 @@ public class JpaClElementStatisticsTest { } @Test - public void testJpaClElementStatisticsConmpareTo() { + public void testJpaClElementStatisticsCompareTo() { JpaClElementStatistics testJpaClElementStatistics = createJpaClElementStatisticsInstance(); JpaClElementStatistics otherJpaClElementStatistics = new JpaClElementStatistics(testJpaClElementStatistics); @@ -169,7 +171,7 @@ public class JpaClElementStatisticsTest { JpaClElementStatistics testJpaClElementStatistics = new JpaClElementStatistics(); testJpaClElementStatistics.setKey(null); testJpaClElementStatistics.fromAuthorative(testCles); - testJpaClElementStatistics.setKey(PfTimestampKey.getNullKey()); + testJpaClElementStatistics.setKey(PfReferenceTimestampKey.getNullKey()); testJpaClElementStatistics.fromAuthorative(testCles); return testJpaClElementStatistics; @@ -177,8 +179,9 @@ public class JpaClElementStatisticsTest { private ClElementStatistics createClElementStatisticsInstance() { ClElementStatistics clElementStatistics = new ClElementStatistics(); - clElementStatistics.setControlLoopElementId(new ToscaConceptIdentifier("elementName", "0.0.1")); - clElementStatistics.setTimeStamp(Instant.ofEpochMilli(123456L)); + clElementStatistics.setParticipantId(new ToscaConceptIdentifier("elementName", "0.0.1")); + clElementStatistics.setId(UUID.fromString("a95757ba-b34a-4049-a2a8-46773abcbe5e")); + clElementStatistics.setTimeStamp(Instant.ofEpochSecond(123456L)); clElementStatistics.setControlLoopState(ControlLoopState.UNINITIALISED); return clElementStatistics; diff --git a/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ClElementStatisticsProviderTest.java b/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ClElementStatisticsProviderTest.java index 1d2b9913a..f5d094f9e 100644 --- a/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ClElementStatisticsProviderTest.java +++ b/tosca-controlloop/models/src/test/java/org/onap/policy/clamp/controlloop/models/controlloop/persistence/provider/ClElementStatisticsProviderTest.java @@ -95,16 +95,18 @@ public class ClElementStatisticsProviderTest { List<ClElementStatistics> getResponse; //Return empty list when no data present in db - getResponse = clElementStatisticsProvider.getClElementStatistics(null, null, null); + getResponse = clElementStatisticsProvider.getClElementStatistics(null, null, null, + null); assertThat(getResponse).isEmpty(); clElementStatisticsProvider.createClElementStatistics(inputClElementStats .getClElementStatistics()); ToscaConceptIdentifier identifier = inputClElementStats.getClElementStatistics().get(0) - .getControlLoopElementId(); + .getParticipantId(); Instant instant = inputClElementStats.getClElementStatistics().get(0).getTimeStamp(); + String id = inputClElementStats.getClElementStatistics().get(0).getId().toString(); assertEquals(1, clElementStatisticsProvider.getClElementStatistics(identifier.getName(), - identifier.getVersion(), instant).size()); + identifier.getVersion(), id, instant).size()); assertEquals(1, clElementStatisticsProvider.getFilteredClElementStatistics("name2", "1.0.1", null, null, null, diff --git a/tosca-controlloop/models/src/test/resources/providers/TestClElementStatistics.json b/tosca-controlloop/models/src/test/resources/providers/TestClElementStatistics.json index 78aeb3a6e..ae19e560d 100644 --- a/tosca-controlloop/models/src/test/resources/providers/TestClElementStatistics.json +++ b/tosca-controlloop/models/src/test/resources/providers/TestClElementStatistics.json @@ -1,19 +1,21 @@ { "clElementStatistics":[ { - "controlLoopElementId":{ + "participantId":{ "name":"name1", "version":"1.001" }, + "id": "709c62b3-8918-41b9-a747-d21eb79c6c20", "timeStamp": "2021-01-10T13:45:00.000Z", "controlLoopState": "UNINITIALISED", "clElementUptime":250 }, { - "controlLoopElementId":{ + "participantId":{ "name":"name2", "version":"1.001" }, + "id": "709c62b3-8918-41b9-a747-d21eb79c6c21", "timeStamp": "2021-01-10T14:25:00.000Z", "controlLoopState": "UNINITIALISED", "clElementUptime":330 diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningHandler.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningHandler.java new file mode 100644 index 000000000..ab917b74e --- /dev/null +++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningHandler.java @@ -0,0 +1,101 @@ +/*- + * ============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.commissioning; + +import java.io.IOException; +import java.util.List; +import java.util.Set; +import javax.ws.rs.core.Response; +import lombok.Getter; +import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler; +import org.onap.policy.clamp.controlloop.runtime.commissioning.rest.CommissioningController; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; +import org.onap.policy.common.endpoints.event.comm.TopicSink; +import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher; +import org.onap.policy.common.utils.services.Registry; +import org.onap.policy.models.base.PfModelRuntimeException; + +/** + * This class handles commissioning of control loop definitions. + */ +public final class CommissioningHandler extends ControlLoopHandler { + + @Getter + private CommissioningProvider provider; + + /** + * Gets the CommissioningHandler. + * + * @return CommissioningHandler + */ + public static CommissioningHandler getInstance() { + return Registry.get(CommissioningHandler.class.getName()); + } + + /** + * Create a handler. + * + * @param controlLoopParameters the parameters for access to the database + */ + public CommissioningHandler(ClRuntimeParameterGroup controlLoopParameters) { + super(controlLoopParameters.getDatabaseProviderParameters()); + } + + @Override + public Set<Class<?>> getProviderClasses() { + return Set.of(CommissioningController.class); + } + + @Override + public void startAndRegisterListeners(MessageTypeDispatcher msgDispatcher) { + // No topic communication on this handler + } + + @Override + public void startAndRegisterPublishers(List<TopicSink> topicSinks) { + // No topic communication on this handler + } + + @Override + public void stopAndUnregisterPublishers() { + // No topic communication on this handler + } + + @Override + public void stopAndUnregisterListeners(MessageTypeDispatcher msgDispatcher) { + // No topic communication on this handler + } + + @Override + public void startProviders() { + provider = new CommissioningProvider(getDatabaseProviderParameters()); + } + + @Override + public void stopProviders() { + try { + provider.close(); + } catch (IOException e) { + throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR, + "an error has occured while stopping commissioning providers", e); + } + } +} diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningController.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningController.java new file mode 100644 index 000000000..cd6c08e30 --- /dev/null +++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningController.java @@ -0,0 +1,351 @@ +/*- + * ============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.commissioning.rest; + +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Authorization; +import io.swagger.annotations.Extension; +import io.swagger.annotations.ExtensionProperty; +import io.swagger.annotations.ResponseHeader; +import java.util.List; +import java.util.UUID; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse; +import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningHandler; +import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; +import org.onap.policy.clamp.controlloop.runtime.main.rest.RestController; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.base.PfModelRuntimeException; +import org.onap.policy.models.errors.concepts.ErrorResponseInfo; +import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class to provide REST end points for creating, deleting, querying commissioned control loops. + */ +public class CommissioningController extends RestController { + + private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class); + + private final CommissioningProvider provider; + + /** + * create Commissioning Controller. + */ + public CommissioningController() { + this.provider = CommissioningHandler.getInstance().getProvider(); + } + + /** + * Creates a control loop definition. + * + * @param requestId request ID used in ONAP logging + * @param body the body of control loop following TOSCA definition + * @return a response + */ + // @formatter:off + @POST + @Path("/commission") + @ApiOperation( + value = "Commissions control loop definitions", + notes = "Commissions control loop definitions, returning the commissioned control loop definition IDs", + response = CommissioningResponse.class, + tags = { + "Control Loop Commissioning API" + }, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, + description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = VERSION_PATCH_NAME, + description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = VERSION_LATEST_NAME, + description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = REQUEST_ID_NAME, + description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class) + }, + extensions = { + @Extension( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public Response create( + @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Entity Body of Control Loop", required = true) ToscaServiceTemplate body) { + + try { + CommissioningResponse response = provider.createControlLoopDefinitions(body); + return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId) + .entity(response).build(); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Commissioning of the control loops failed", e); + return createCommissioningErrorResponse(e, requestId); + } + + } + + /** + * Deletes a control loop definition. + * + * @param requestId request ID used in ONAP logging + * @param name the name of the control loop definition to delete + * @param version the version of the control loop definition to delete + * @return a response + */ + // @formatter:off + @DELETE + @Path("/commission") + @ApiOperation(value = "Delete a commissioned control loop", + notes = "Deletes a Commissioned Control Loop, returning optional error details", + response = CommissioningResponse.class, + tags = { + "Clamp Control Loop Commissioning API" + }, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, + description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = VERSION_PATCH_NAME, + description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = VERSION_LATEST_NAME, + description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = REQUEST_ID_NAME, + description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses(value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public Response delete( + @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name, + @ApiParam(value = "Control Loop definition version", required = true) + @QueryParam("version") String version) { + + try { + CommissioningResponse response = provider.deleteControlLoopDefinition(name, version); + return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId) + .entity(response).build(); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Decommisssioning of control loop failed", e); + return createCommissioningErrorResponse(e, requestId); + } + + } + + /** + * Queries details of all or specific control loop definitions. + * + * @param requestId request ID used in ONAP logging + * @param name the name of the control loop definition to get, null for all definitions + * @param version the version of the control loop definition to get, null for all definitions + * @return the control loop definitions + */ + // @formatter:off + @GET + @Path("/commission") + @ApiOperation(value = "Query details of the requested commissioned control loop definitions", + notes = "Queries details of the requested commissioned control loop definitions, " + + "returning all control loop details", + response = ToscaNodeTemplate.class, + tags = { + "Clamp Control Loop Commissioning API" + }, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public Response query(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop definition name", required = true) + @QueryParam("name") String name, + @ApiParam(value = "Control Loop definition version", required = true) + @QueryParam("version") String version) { + + try { + List<ToscaNodeTemplate> response = provider.getControlLoopDefinitions(name, version); + return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response) + .build(); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Get of control loop definitions failed", e); + return createCommissioningErrorResponse(e, requestId); + } + + } + + /** + * Queries the elements of a specific control loop. + * + * @param requestId request ID used in ONAP logging + * @param name the name of the control loop definition to get + * @param version the version of the control loop definition to get + * @return the control loop element definitions + */ + // @formatter:off + @GET + @Path("/commission/elements") + @ApiOperation(value = "Query details of the requested commissioned control loop element definitions", + notes = "Queries details of the requested commissioned control loop element definitions, " + + "returning all control loop elements' details", + response = ToscaNodeTemplate.class, + tags = { + "Clamp Control Loop Commissioning API" + }, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public Response queryElements(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop definition name", required = true) + @QueryParam("name") String name, + @ApiParam(value = "Control Loop definition version", required = true) + @QueryParam("version") String version) throws Exception { + + try { + List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version); + //Prevent ambiguous queries with multiple returns + if (nodeTemplate.size() > 1) { + throw new Exception(); + } + List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0)); + return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response) + .build(); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Get of control loop element definitions failed", e); + return createCommissioningErrorResponse(e, requestId); + } + + } + + private Response createCommissioningErrorResponse(ErrorResponseInfo e, UUID requestId) { + CommissioningResponse resp = new CommissioningResponse(); + resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); + return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), + requestId).entity(resp).build(); + } + +} diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java index c4b0955f9..fd5288fda 100644 --- a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java +++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java @@ -27,6 +27,7 @@ import java.util.Set; import javax.ws.rs.core.Response; import lombok.Getter; import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler; +import org.onap.policy.clamp.controlloop.runtime.commissioning.rest.CommissioningController; import org.onap.policy.clamp.controlloop.runtime.instantiation.rest.InstantiationController; import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.common.endpoints.event.comm.TopicSink; @@ -66,11 +67,7 @@ public final class InstantiationHandler extends ControlLoopHandler { @Override public Set<Class<?>> getProviderClasses() { - Set<Class<?>> providerClasses = new HashSet<>(); - - providerClasses.add(InstantiationController.class); - - return providerClasses; + return Set.of(InstantiationController.class); } @Override diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java index d3a5c5810..0078f6129 100644 --- a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java +++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java @@ -20,11 +20,14 @@ package org.onap.policy.clamp.controlloop.runtime.main.startstop; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import javax.ws.rs.core.Response.Status; import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException; +import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler; +import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningHandler; import org.onap.policy.clamp.controlloop.runtime.instantiation.InstantiationHandler; import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.clamp.controlloop.runtime.main.rest.ControlLoopAafFilter; @@ -61,7 +64,6 @@ public class ClRuntimeActivator extends ServiceManagerContainer { * @param clRuntimeParameterGroup the parameters for the control loop runtime service */ public ClRuntimeActivator(final ClRuntimeParameterGroup clRuntimeParameterGroup) { - if (clRuntimeParameterGroup == null || !clRuntimeParameterGroup.isValid()) { throw new ControlLoopRuntimeException(Status.INTERNAL_SERVER_ERROR, "ParameterGroup not valid"); } @@ -81,53 +83,61 @@ public class ClRuntimeActivator extends ServiceManagerContainer { "topic message dispatcher failed to start", e); } - final AtomicReference<InstantiationHandler> instantiationHandler = new AtomicReference<>(); - final AtomicReference<RestServer> restServer = new AtomicReference<>(); + final AtomicReference<ControlLoopHandler> commissioningHandler = new AtomicReference<>(); + final AtomicReference<ControlLoopHandler> instantiationHandler = new AtomicReference<>(); + final AtomicReference<RestServer> restServer = new AtomicReference<>(); // @formatter:off addAction("Control loop runtime parameters", - () -> ParameterService.register(clRuntimeParameterGroup), - () -> ParameterService.deregister(clRuntimeParameterGroup.getName())); - + () -> ParameterService.register(clRuntimeParameterGroup), + () -> ParameterService.deregister(clRuntimeParameterGroup.getName())); addAction("Topic endpoint management", - () -> TopicEndpointManager.getManager().start(), - () -> TopicEndpointManager.getManager().shutdown()); - + () -> TopicEndpointManager.getManager().start(), + () -> TopicEndpointManager.getManager().shutdown()); + addAction("Commissioning Handler", + () -> commissioningHandler.set(new CommissioningHandler(clRuntimeParameterGroup)), + () -> commissioningHandler.get().close()); addAction("Instantiation Handler", - () -> instantiationHandler.set(new InstantiationHandler(clRuntimeParameterGroup)), - () -> instantiationHandler.get().close()); - - addAction("Providers", - () -> instantiationHandler.get().startProviders(), - () -> instantiationHandler.get().stopProviders()); + () -> instantiationHandler.set(new InstantiationHandler(clRuntimeParameterGroup)), + () -> instantiationHandler.get().close()); - addAction("Listeners", - () -> instantiationHandler.get().startAndRegisterListeners(msgDispatcher), - () -> instantiationHandler.get().stopAndUnregisterListeners(msgDispatcher)); - - addAction("Publishers", - () -> instantiationHandler.get().startAndRegisterPublishers(topicSinks), - () -> instantiationHandler.get().stopAndUnregisterPublishers()); + addHandlerActions("Commissioning", commissioningHandler); + addHandlerActions("Instantiation", instantiationHandler); addAction("Topic Message Dispatcher", this::registerMsgDispatcher, this::unregisterMsgDispatcher); clRuntimeParameterGroup.getRestServerParameters().setName(clRuntimeParameterGroup.getName()); addAction("REST server", - () -> { - Set<Class<?>> providerClasses = instantiationHandler.get().getProviderClasses(); + () -> { + Set<Class<?>> providerClasses = new HashSet<>(); + providerClasses.addAll(commissioningHandler.get().getProviderClasses()); + providerClasses.addAll(instantiationHandler.get().getProviderClasses()); - RestServer server = new RestServer(clRuntimeParameterGroup.getRestServerParameters(), + RestServer server = new RestServer(clRuntimeParameterGroup.getRestServerParameters(), ControlLoopAafFilter.class, providerClasses.toArray(new Class<?>[providerClasses.size()])); - - restServer.set(server); - restServer.get().start(); - }, - () -> restServer.get().stop()); + restServer.set(server); + restServer.get().start(); + }, + () -> restServer.get().stop()); // @formatter:on } + private void addHandlerActions(final String name, final AtomicReference<ControlLoopHandler> handler) { + addAction(name + " Providers", + () -> handler.get().startProviders(), + () -> handler.get().stopProviders()); + + addAction(name + " Listeners", + () -> handler.get().startAndRegisterListeners(msgDispatcher), + () -> handler.get().stopAndUnregisterListeners(msgDispatcher)); + + addAction(name + " Publishers", + () -> handler.get().startAndRegisterPublishers(topicSinks), + () -> handler.get().stopAndUnregisterPublishers()); + } + /** * Registers the dispatcher with the topic source(s). */ diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringHandler.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringHandler.java new file mode 100644 index 000000000..04f458e7d --- /dev/null +++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringHandler.java @@ -0,0 +1,104 @@ +/*- + * ============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.monitoring; + +import java.io.IOException; +import java.util.List; +import java.util.Set; +import javax.ws.rs.core.Response; +import lombok.Getter; +import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; +import org.onap.policy.clamp.controlloop.runtime.monitoring.rest.MonitoringQueryController; +import org.onap.policy.common.endpoints.event.comm.TopicSink; +import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher; +import org.onap.policy.common.utils.services.Registry; +import org.onap.policy.models.base.PfModelRuntimeException; + +/** + * This class handles monitoring of control loop definitions, + * so only one object of this type should be built at a time. + * + * <p/> + * It is effectively a singleton that is started at system start. + */ +public class MonitoringHandler extends ControlLoopHandler { + + @Getter + private MonitoringProvider monitoringProvider; + + /** + * Gets the Monitoring Handler. + * + * @return MonitoringHandler + */ + public static MonitoringHandler getInstance() { + return Registry.get(MonitoringHandler.class.getName()); + } + + /** + * Create a handler. + * + * @param controlLoopParameters the parameters for access to the database + */ + public MonitoringHandler(ClRuntimeParameterGroup controlLoopParameters) { + super(controlLoopParameters.getDatabaseProviderParameters()); + } + + @Override + public Set<Class<?>> getProviderClasses() { + return Set.of(MonitoringQueryController.class); + } + + @Override + public void startAndRegisterListeners(MessageTypeDispatcher msgDispatcher) { + // No topic communication on this handler + } + + @Override + public void startAndRegisterPublishers(List<TopicSink> topicSinks) { + // No topic communication on this handler + } + + @Override + public void stopAndUnregisterPublishers() { + // No topic communication on this handler + } + + @Override + public void stopAndUnregisterListeners(MessageTypeDispatcher msgDispatcher) { + // No topic communication on this handler + } + + @Override + public void startProviders() { + monitoringProvider = new MonitoringProvider(getDatabaseProviderParameters()); + } + + @Override + public void stopProviders() { + try { + monitoringProvider.close(); + } catch (IOException e) { + throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR, "Cannot stop provider", e); + } + } +} diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringProvider.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringProvider.java new file mode 100644 index 000000000..aeabce7a5 --- /dev/null +++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringProvider.java @@ -0,0 +1,273 @@ +/*- + * ============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.monitoring; + +import java.io.Closeable; +import java.io.IOException; +import java.time.Instant; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.NonNull; +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.ControlLoop; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatistics; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatisticsList; +import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ClElementStatisticsProvider; +import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider; +import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantStatisticsProvider; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.base.PfModelRuntimeException; +import org.onap.policy.models.provider.PolicyModelsProviderParameters; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +/** + * This class provides information about statistics data of CL elements and CL Participants in database to callers. + */ +public class MonitoringProvider implements Closeable { + + private static final String DESC_ORDER = "DESC"; + private final ParticipantStatisticsProvider participantStatisticsProvider; + private final ClElementStatisticsProvider clElementStatisticsProvider; + private final ControlLoopProvider controlLoopProvider; + + /** + * Create a Monitoring provider. + * + */ + public MonitoringProvider(PolicyModelsProviderParameters parameters) { + + try { + participantStatisticsProvider = new ParticipantStatisticsProvider(parameters); + clElementStatisticsProvider = new ClElementStatisticsProvider(parameters); + controlLoopProvider = new ControlLoopProvider(parameters); + } catch (PfModelException e) { + throw new PfModelRuntimeException(e); + } + } + + @Override + public void close() throws IOException { + controlLoopProvider.close(); + clElementStatisticsProvider.close(); + participantStatisticsProvider.close(); + } + + /** + * Create participant statistics. + * + * @param participantStatistics the participant statistics + * @return the result of create operation + * @throws PfModelException on creation errors + */ + public ParticipantStatisticsList createParticipantStatistics(List<ParticipantStatistics> participantStatistics) + throws PfModelException { + ParticipantStatisticsList participantStatisticsList = new ParticipantStatisticsList(); + participantStatisticsList.setStatisticsList(participantStatisticsProvider + .createParticipantStatistics(participantStatistics)); + + return participantStatisticsList; + } + + /** + * Create clElement statistics. + * + * @param clElementStatisticsList the clElement statistics + * @return the result of create operation + * @throws PfModelException on creation errors + */ + public ClElementStatisticsList createClElementStatistics(List<ClElementStatistics> clElementStatisticsList) + throws PfModelException { + ClElementStatisticsList elementStatisticsList = new ClElementStatisticsList(); + elementStatisticsList.setClElementStatistics(clElementStatisticsProvider + .createClElementStatistics(clElementStatisticsList)); + + return elementStatisticsList; + } + + /** + * Get participant statistics based on specific filters. + * + * @param name the name of the participant statistics to get, null to get all statistics + * @param version the version of the participant statistics to get, null to get all statistics + * @param recordCount number of records to be fetched. + * @param startTime start of the timestamp, from statistics to be filtered + * @param endTime end of the timestamp up to which statistics to be filtered + * @return the participant found + */ + public ParticipantStatisticsList fetchFilteredParticipantStatistics(@NonNull final String name, + final String version, int recordCount, + Instant startTime, Instant endTime) { + ParticipantStatisticsList participantStatisticsList = new ParticipantStatisticsList(); + + //Additional parameters can be added in filterMap for filtering data. + Map<String, Object> filterMap = null; + participantStatisticsList.setStatisticsList(participantStatisticsProvider.getFilteredParticipantStatistics( + name, version, startTime, endTime, filterMap, DESC_ORDER, recordCount)); + + return participantStatisticsList; + } + + /** + * Get all participant statistics records found for a specific control loop. * + * + * @param controlLoopName name of the control loop + * @param controlLoopVersion version of the control loop + * @return All the participant statistics found + * @throws PfModelException on errors getting participant statistics + */ + public ParticipantStatisticsList fetchParticipantStatsPerControlLoop(@NonNull final String controlLoopName, + @NonNull final String controlLoopVersion) + throws PfModelException { + ParticipantStatisticsList statisticsList = new ParticipantStatisticsList(); + List<ParticipantStatistics> participantStatistics = new ArrayList<>(); + try { + //Fetch all participantIds for a specific control loop + List<ToscaConceptIdentifier> participantIds = getAllParticipantIdsPerControlLoop(controlLoopName, + controlLoopVersion); + for (ToscaConceptIdentifier id: participantIds) { + participantStatistics.addAll(participantStatisticsProvider.getFilteredParticipantStatistics( + id.getName(), id.getVersion(), null, null, null, DESC_ORDER, 0)); + } + statisticsList.setStatisticsList(participantStatistics); + } catch (PfModelException e) { + throw new PfModelRuntimeException(e); + } + return statisticsList; + } + + + + /** + * Get clElement statistics based on specific filters. + * + * @param name the name of the clElement statistics to get, null to get all statistics + * @param version the version of the clElement statistics to get, null to get all statistics + * @param id UUID of the control loop element + * @param startTime start of the timestamp, from statistics to be filtered + * @param endTime end of the timestamp up to which statistics to be filtered + * @param recordCount number of records to be fetched. + * @return the participant found + * @throws PfModelException on errors getting control loop statistics + */ + public ClElementStatisticsList fetchFilteredClElementStatistics(@NonNull final String name, final String version, + final String id, Instant startTime, Instant endTime, + int recordCount) throws PfModelException { + ClElementStatisticsList clElementStatisticsList = new ClElementStatisticsList(); + Map<String, Object> filterMap = new HashMap<>(); + //Adding UUID in filter if present + if (id != null) { + filterMap.put("localName", id); + } + clElementStatisticsList.setClElementStatistics(clElementStatisticsProvider.getFilteredClElementStatistics( + name, version, startTime, endTime, filterMap, DESC_ORDER, recordCount)); + + return clElementStatisticsList; + } + + + /** + * Get clElement statistics per control loop. + * + * @param name the name of the control loop + * @param version the version of the control loop + * @return the clElement statistics found + * @throws PfModelException on errors getting control loop statistics + */ + public ClElementStatisticsList fetchClElementStatsPerControlLoop(@NonNull final String name, + @NonNull final String version) + throws PfModelException { + ClElementStatisticsList clElementStatisticsList = new ClElementStatisticsList(); + List<ClElementStatistics> clElementStats = new ArrayList<>(); + try { + List<ControlLoopElement> clElements = new ArrayList<>(); + //Fetch all control loop elements for the control loop + ControlLoop controlLoop = controlLoopProvider.getControlLoop(new ToscaConceptIdentifier(name, + version)); + clElements.addAll(controlLoop.getElements()); + + //Collect control loop element statistics for each cl element. + for (ControlLoopElement clElement : clElements) { + clElementStats.addAll(fetchFilteredClElementStatistics(clElement.getParticipantId().getName(), + clElement.getParticipantId().getVersion(), clElement.getId().toString(), null, + null, 0).getClElementStatistics()); + } + clElementStatisticsList.setClElementStatistics(clElementStats); + } catch (PfModelException e) { + throw new PfModelRuntimeException(e); + } + + return clElementStatisticsList; + } + + /** + * If required, REST end point can be defined for this method to fetch associated participant Ids + * for a control loop. + * + * @param name the name of the control loop + * @param version the version of the control loop + * @return List of participant Id + * @throws PfModelException on errors + */ + public List<ToscaConceptIdentifier> getAllParticipantIdsPerControlLoop(String name, String version) + throws PfModelException { + List<ToscaConceptIdentifier> participantIds = new ArrayList<>(); + ControlLoop controlLoop = controlLoopProvider.getControlLoop(new ToscaConceptIdentifier(name, version)); + if (controlLoop != null) { + for (ControlLoopElement clElement : controlLoop.getElements()) { + participantIds.add(clElement.getParticipantId()); + } + } + return participantIds; + } + + /** + * If required, REST end point can be defined for this method to fetch associated control loop element Ids + * for a control loop. + * + * @param name the name of the control loop + * @param version the version of the control loop + * @return Map of control loop Id and participant details + * @throws PfModelException on errors + */ + public Map<String, ToscaConceptIdentifier> getAllClElementsIdPerControlLoop(String name, String version) + throws PfModelException { + Map<String, ToscaConceptIdentifier> clElementId = new HashMap<>(); + ControlLoop controlLoop = controlLoopProvider.getControlLoop(new ToscaConceptIdentifier(name, version)); + for (ControlLoopElement clElement : controlLoop.getElements()) { + clElementId.put(clElement.getId().toString(), clElement.getParticipantId()); + } + return clElementId; + } + + + + public void updateClElementStatistics(List<ClElementStatistics> clElementStatistics) { + // TODO Auto-generated method stub + } + + public void updateParticipantStatistics(List<ParticipantStatistics> statisticsList) { + // TODO Auto-generated method stub + } +} diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryController.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryController.java new file mode 100644 index 000000000..2e19ffe3a --- /dev/null +++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryController.java @@ -0,0 +1,371 @@ +/*- + * ============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.monitoring.rest; + +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Authorization; +import io.swagger.annotations.Extension; +import io.swagger.annotations.ExtensionProperty; +import io.swagger.annotations.ResponseHeader; +import java.time.Instant; +import java.util.UUID; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatisticsList; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatisticsList; +import org.onap.policy.clamp.controlloop.runtime.main.rest.RestController; +import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringHandler; +import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.base.PfModelRuntimeException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class handles REST endpoints for CL Statistics monitoring. + */ +public class MonitoringQueryController extends RestController { + + private static final Logger LOGGER = LoggerFactory.getLogger(MonitoringQueryController.class); + private final MonitoringProvider provider; + + /** + * Create Monitoring Controller. + */ + public MonitoringQueryController() { + this.provider = MonitoringHandler.getInstance().getMonitoringProvider(); + } + + + /** + * Queries details of control loop participants statistics. + * + * @param requestId request ID used in ONAP logging + * @param name the name of the participant to get, null for all participants statistics + * @param recordCount the record count to be fetched + * @return the participant statistics + */ + // @formatter:off + @GET + @Path("/monitoring/participant") + @ApiOperation(value = "Query details of the requested participant stats", + notes = "Queries details of the requested participant stats, returning all participant stats", + response = ParticipantStatisticsList.class, + tags = { + "Clamp control loop Monitoring API" + }, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public Response queryParticipantStatistics(@HeaderParam(REQUEST_ID_NAME) + @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop participant name", required = true) + @QueryParam("name") final String name, + @ApiParam(value = "Control Loop participant version", required = true) + @QueryParam("version") final String version, + @ApiParam(value = "Record count", required = false) @DefaultValue("0") + @QueryParam("recordCount") final int recordCount, + @ApiParam(value = "start time", required = false) + @QueryParam("startTime") final String startTime, + @ApiParam(value = "end time", required = false) + @QueryParam("endTime") final String endTime) { + + try { + Instant startTimestamp = null; + Instant endTimestamp = null; + + if (startTime != null) { + startTimestamp = Instant.parse(startTime); + } + if (endTime != null) { + endTimestamp = Instant.parse(endTime); + } + ParticipantStatisticsList response = provider.fetchFilteredParticipantStatistics(name, version, recordCount, + startTimestamp, endTimestamp); + return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) + .entity(response) + .build(); + + } catch (PfModelRuntimeException e) { + LOGGER.warn("Monitoring of participants statistics failed", e); + return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), + requestId).build(); + } + + } + + /** + * Queries details of all participant statistics per control loop. + * + * @param requestId request ID used in ONAP logging + * @param name the name of the control loop + * @param version version of the control loop + * @return the control loop element statistics + */ + // @formatter:off + @GET + @Path("/monitoring/participants/controlloop") + @ApiOperation(value = "Query details of all the participant stats in a control loop", + notes = "Queries details of the participant stats, returning all participant stats", + response = ClElementStatisticsList.class, + tags = { + "Clamp control loop Monitoring API" + }, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + }) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public Response queryParticipantStatisticsPerControlLoop(@HeaderParam(REQUEST_ID_NAME) + @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop name", required = true) + @QueryParam("name") final String name, + @ApiParam(value = "Control Loop version", required = true) + @QueryParam("version") final String version) { + + try { + ParticipantStatisticsList response = provider.fetchParticipantStatsPerControlLoop(name, version); + return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) + .entity(response) + .build(); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Monitoring of Cl participant statistics failed", e); + return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), + requestId).build(); + } + + } + + + + /** + * Queries details of all control loop element statistics per control loop. + * + * @param requestId request ID used in ONAP logging + * @param name the name of the control loop + * @param version version of the control loop + * @return the control loop element statistics + */ + // @formatter:off + @GET + @Path("/monitoring/clelements/controlloop") + @ApiOperation(value = "Query details of the requested cl element stats in a control loop", + notes = "Queries details of the requested cl element stats, returning all clElement stats", + response = ClElementStatisticsList.class, + tags = { + "Clamp control loop Monitoring API" + }, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + }) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public Response queryElementStatisticsPerControlLoop(@HeaderParam(REQUEST_ID_NAME) + @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop name", required = true) + @QueryParam("name") final String name, + @ApiParam(value = "Control Loop version", required = true) + @QueryParam("version") final String version) { + + try { + ClElementStatisticsList response = provider.fetchClElementStatsPerControlLoop(name, version); + return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) + .entity(response) + .build(); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Monitoring of Cl Element statistics failed", e); + return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), + requestId).build(); + } + + } + + + + + /** + * Queries details of all control loop element statistics per control loop. + * + * @param requestId request ID used in ONAP logging + * @param name the name of the control loop + * @param version version of the control loop + * @param id Id of the control loop element + * @param recordCount the record count to be fetched + * @return the control loop element statistics + */ + // @formatter:off + @GET + @Path("/monitoring/clelement") + @ApiOperation(value = "Query details of the requested cl element stats", + notes = "Queries details of the requested cl element stats, returning all clElement stats", + response = ClElementStatisticsList.class, + tags = { + "Clamp control loop Monitoring API" + }, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + }) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public Response queryElementStatistics(@HeaderParam(REQUEST_ID_NAME) + @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Participant name", required = true) + @QueryParam("name") final String name, + @ApiParam(value = "Participant version", required = true) + @QueryParam("version") final String version, + @ApiParam(value = "Record count", required = false) + @DefaultValue("0") @QueryParam("recordCount") final int recordCount, + @ApiParam(value = "Control Loop element id", required = false) + @QueryParam("id") final String id, + @ApiParam(value = "start time", required = false) + @QueryParam("startTime") final String startTime, + @ApiParam(value = "end time", required = false) + @QueryParam("endTime") final String endTime) { + + try { + Instant startTimestamp = null; + Instant endTimestamp = null; + + if (startTime != null) { + startTimestamp = Instant.parse(startTime); + } + if (endTime != null) { + endTimestamp = Instant.parse(endTime); + } + ClElementStatisticsList response = provider.fetchFilteredClElementStatistics(name, version, id, + startTimestamp, endTimestamp, recordCount); + return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) + .entity(response) + .build(); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Monitoring of Cl Element statistics failed", e); + return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), + requestId).build(); + } + + } + +} diff --git a/tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningControllerTest.java b/tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningControllerTest.java new file mode 100644 index 000000000..fa146635d --- /dev/null +++ b/tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningControllerTest.java @@ -0,0 +1,202 @@ +/*- + * ============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.commissioning.rest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Response; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse; +import org.onap.policy.clamp.controlloop.runtime.util.rest.CommonRestController; +import org.onap.policy.common.utils.coder.YamlJsonTranslator; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.provider.PolicyModelsProvider; +import org.onap.policy.models.provider.PolicyModelsProviderFactory; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; + +public class CommissioningControllerTest extends CommonRestController { + + private static final String TOSCA_SERVICE_TEMPLATE_YAML = + "src/test/resources/servicetemplates/pmsh_multiple_cl_tosca.yaml"; + private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator(); + private static final String COMMISSIONING_ENDPOINT = "commission"; + private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate(); + + /** + * starts Main and inserts a commissioning template. + * + * @throws Exception if an error occurs + */ + @BeforeClass + public static void setUpBeforeClass() throws Exception { + CommonRestController.setUpBeforeClass("CommissioningApi"); + + serviceTemplate = yamlTranslator.fromYaml(ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), + ToscaServiceTemplate.class); + } + + @AfterClass + public static void teardownAfterClass() { + CommonRestController.teardownAfterClass(); + } + + @Test + public void testSwagger() throws Exception { + super.testSwagger(COMMISSIONING_ENDPOINT); + } + + @Test + public void testUnauthorizedCreate() throws Exception { + assertUnauthorizedPost(COMMISSIONING_ENDPOINT, Entity.json(serviceTemplate)); + } + + @Test + public void testUnauthorizedQuery() throws Exception { + assertUnauthorizedGet(COMMISSIONING_ENDPOINT); + } + + @Test + public void testUnauthorizedQueryElements() throws Exception { + assertUnauthorizedGet(COMMISSIONING_ENDPOINT + "/elements"); + } + + @Test + public void testUnauthorizedDelete() throws Exception { + assertUnauthorizedDelete(COMMISSIONING_ENDPOINT); + } + + @Test + public void testCreateBadRequest() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); + Response resp = invocationBuilder.post(Entity.json("NotToscaServiceTempalte")); + + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + CommissioningResponse commissioningResponse = resp.readEntity(CommissioningResponse.class); + assertNotNull(commissioningResponse.getErrorDetails()); + assertNull(commissioningResponse.getAffectedControlLoopDefinitions()); + } + + @Test + public void testCreate() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); + Response resp = invocationBuilder.post(Entity.json(serviceTemplate)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + CommissioningResponse commissioningResponse = resp.readEntity(CommissioningResponse.class); + + assertNotNull(commissioningResponse); + assertNull(commissioningResponse.getErrorDetails()); + // Response should return the number of node templates present in the service template + assertThat(commissioningResponse.getAffectedControlLoopDefinitions()).hasSize(13); + for (String nodeTemplateName : serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().keySet()) { + assertTrue(commissioningResponse.getAffectedControlLoopDefinitions().stream() + .anyMatch(ac -> ac.getName().equals(nodeTemplateName))); + } + } + + @Test + public void testQuery_NoResultWithThisName() throws Exception { + createEntryInDB(); + + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "?name=noResultWithThisName"); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + List entityList = rawresp.readEntity(List.class); + assertThat(entityList).isEmpty(); + } + + @Test + public void testQuery() throws Exception { + createEntryInDB(); + + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + List entityList = rawresp.readEntity(List.class); + assertNotNull(entityList); + assertThat(entityList).hasSize(2); + } + + @Test + public void testQueryElementsBadRequest() throws Exception { + createEntryInDB(); + + //Call get elements with no info + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/elements"); + Response resp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), resp.getStatus()); + } + + @Test + public void testQueryElements() throws Exception { + createEntryInDB(); + + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/elements" + + "?name=org.onap.domain.pmsh.PMSHControlLoopDefinition"); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + List entityList = rawresp.readEntity(List.class); + assertNotNull(entityList); + assertThat(entityList).hasSize(4); + } + + @Test + public void testDeleteBadRequest() throws Exception { + createEntryInDB(); + + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); + //Call delete with no info + Response resp = invocationBuilder.delete(); + assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), resp.getStatus()); + } + + @Test + public void testDelete() throws Exception { + createEntryInDB(); + + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "?name=" + + serviceTemplate.getName() + "&version=" + serviceTemplate.getVersion()); + //Call delete with no info + Response resp = invocationBuilder.delete(); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + + try (PolicyModelsProvider modelsProvider = new PolicyModelsProviderFactory() + .createPolicyModelsProvider(CommonRestController.getParameters())) { + List<ToscaServiceTemplate> templatesInDB = modelsProvider.getServiceTemplateList(null, null); + assertThat(templatesInDB).isEmpty(); + } + } + + private synchronized void createEntryInDB() throws Exception { + try (PolicyModelsProvider modelsProvider = new PolicyModelsProviderFactory() + .createPolicyModelsProvider(CommonRestController.getParameters())) { + modelsProvider.createServiceTemplate(serviceTemplate); + } + } +} |