diff options
Diffstat (limited to 'runtime-controlloop')
52 files changed, 2091 insertions, 1096 deletions
diff --git a/runtime-controlloop/pom.xml b/runtime-controlloop/pom.xml index e436451ff..508f44a80 100644 --- a/runtime-controlloop/pom.xml +++ b/runtime-controlloop/pom.xml @@ -67,6 +67,11 @@ </dependency> <dependency> <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-aop</artifactId> + <version>${version.springboot}</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/Application.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/Application.java index 6b772513c..5fbd36c06 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/Application.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/Application.java @@ -22,11 +22,15 @@ package org.onap.policy.clamp.controlloop.runtime; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; +@EnableScheduling @SpringBootApplication @ComponentScan({"org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider", "org.onap.policy.clamp.controlloop.runtime"}) +@ConfigurationPropertiesScan("org.onap.policy.clamp.controlloop.runtime.main.parameters") public class Application { public static void main(String[] args) { diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java index bf6e39914..e676cbe0e 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java @@ -23,13 +23,14 @@ package org.onap.policy.clamp.controlloop.runtime.commissioning; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.module.jsonSchema.JsonSchema; import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import javax.ws.rs.core.Response.Status; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider; @@ -42,6 +43,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType; import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeType; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; +import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty; import org.onap.policy.models.tosca.authorative.concepts.ToscaRelationshipType; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplates; @@ -59,6 +61,7 @@ public class CommissioningProvider { private final PolicyModelsProvider modelsProvider; private final ControlLoopProvider clProvider; + private final ObjectMapper mapper = new ObjectMapper(); private static final Object lockit = new Object(); @@ -71,6 +74,7 @@ public class CommissioningProvider { public CommissioningProvider(PolicyModelsProvider modelsProvider, ControlLoopProvider clProvider) { this.modelsProvider = modelsProvider; this.clProvider = clProvider; + mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); } /** @@ -181,6 +185,165 @@ public class CommissioningProvider { } /** + * Get the initial node types with common or instance properties. + * + * @param fullNodeTypes map of all the node types in the specified template + * @param common boolean to indicate whether common or instance properties are required + * @return node types map that only has common properties + * @throws PfModelException on errors getting node type with common properties + */ + private Map<String, ToscaNodeType> getInitialNodeTypesMap(Map<String, ToscaNodeType> fullNodeTypes, + boolean common) { + + var tempNodeTypesMap = new HashMap<String, ToscaNodeType>(); + + fullNodeTypes.forEach((key, nodeType) -> { + var tempToscaNodeType = new ToscaNodeType(); + tempToscaNodeType.setName(key); + + var resultantPropertyMap = findCommonOrInstancePropsInNodeTypes(nodeType, common); + + if (!resultantPropertyMap.isEmpty()) { + tempToscaNodeType.setProperties(resultantPropertyMap); + tempNodeTypesMap.put(key, tempToscaNodeType); + } + }); + return tempNodeTypesMap; + } + + private Map<String, ToscaProperty> findCommonOrInstancePropsInNodeTypes(ToscaNodeType nodeType, boolean common) { + + var tempCommonPropertyMap = new HashMap<String, ToscaProperty>(); + var tempInstancePropertyMap = new HashMap<String, ToscaProperty>(); + + nodeType.getProperties().forEach((propKey, prop) -> { + + if (prop.getMetadata() != null) { + prop.getMetadata().forEach((k, v) -> { + if (k.equals("common") && v.equals("true") && common) { + tempCommonPropertyMap.put(propKey, prop); + } else if (k.equals("common") && v.equals("false") && !common) { + tempInstancePropertyMap.put(propKey, prop); + } + + }); + } else { + tempInstancePropertyMap.put(propKey, prop); + } + }); + + if (tempCommonPropertyMap.isEmpty() && !common) { + return tempInstancePropertyMap; + } else { + return tempCommonPropertyMap; + } + } + + /** + * Get the node types derived from those that have common properties. + * + * @param initialNodeTypes map of all the node types in the specified template + * @param filteredNodeTypes map of all the node types that have common or instance properties + * @return all node types that have common properties including their children + * @throws PfModelException on errors getting node type with common properties + */ + private Map<String, ToscaNodeType> getFinalNodeTypesMap(Map<String, ToscaNodeType> initialNodeTypes, + Map<String, ToscaNodeType> filteredNodeTypes) { + for (var i = 0; i < initialNodeTypes.size(); i++) { + initialNodeTypes.forEach((key, nodeType) -> { + var tempToscaNodeType = new ToscaNodeType(); + tempToscaNodeType.setName(key); + + if (filteredNodeTypes.get(nodeType.getDerivedFrom()) != null) { + tempToscaNodeType.setName(key); + + var finalProps = new HashMap<String, ToscaProperty>( + filteredNodeTypes.get(nodeType.getDerivedFrom()).getProperties()); + + tempToscaNodeType.setProperties(finalProps); + } else { + return; + } + filteredNodeTypes.putIfAbsent(key, tempToscaNodeType); + + }); + } + return filteredNodeTypes; + } + + /** + * Get the requested node types with common or instance properties. + * + * @param common boolean indicating common or instance properties + * @param name the name of the definition to get, null for all definitions + * @param version the version of the definition to get, null for all definitions + * @return the node types with common or instance properties + * @throws PfModelException on errors getting node type properties + */ + private Map<String, ToscaNodeType> getCommonOrInstancePropertiesFromNodeTypes(boolean common, String name, + String version) throws PfModelException { + var serviceTemplates = new ToscaServiceTemplates(); + serviceTemplates.setServiceTemplates(modelsProvider.getServiceTemplateList(name, version)); + var tempNodeTypesMap = + this.getInitialNodeTypesMap(serviceTemplates.getServiceTemplates().get(0).getNodeTypes(), common); + + return this.getFinalNodeTypesMap(serviceTemplates.getServiceTemplates().get(0).getNodeTypes(), + tempNodeTypesMap); + + } + + /** + * Get node templates with appropriate common or instance properties added. + * + * @param initialNodeTemplates map of all the node templates in the specified template + * @param nodeTypeProps map of all the node types that have common or instance properties including children + * @return all node templates with appropriate common or instance properties added + * @throws PfModelException on errors getting map of node templates with common or instance properties added + */ + private Map<String, ToscaNodeTemplate> getDerivedCommonOrInstanceNodeTemplates( + Map<String, ToscaNodeTemplate> initialNodeTemplates, Map<String, ToscaNodeType> nodeTypeProps) { + + var finalNodeTemplatesMap = new HashMap<String, ToscaNodeTemplate>(); + + initialNodeTemplates.forEach((templateKey, template) -> { + if (nodeTypeProps.containsKey(template.getType())) { + var finalMergedProps = new HashMap<String, Object>(); + + nodeTypeProps.get(template.getType()).getProperties().forEach(finalMergedProps::putIfAbsent); + + template.setProperties(finalMergedProps); + + finalNodeTemplatesMap.put(templateKey, template); + } else { + return; + } + }); + return finalNodeTemplatesMap; + } + + /** + * Get node templates with common properties added. + * + * @param common boolean indicating common or instance properties to be used + * @param name the name of the definition to use, null for all definitions + * @param version the version of the definition to use, null for all definitions + * @return the nodes templates with common or instance properties + * @throws PfModelException on errors getting common or instance properties from node_templates + */ + public Map<String, ToscaNodeTemplate> getNodeTemplatesWithCommonOrInstanceProperties(boolean common, String name, + String version) throws PfModelException { + + var commonOrInstanceNodeTypeProps = this.getCommonOrInstancePropertiesFromNodeTypes(common, name, version); + + var serviceTemplates = new ToscaServiceTemplates(); + serviceTemplates.setServiceTemplates(modelsProvider.getServiceTemplateList(name, version)); + + return this.getDerivedCommonOrInstanceNodeTemplates( + serviceTemplates.getServiceTemplates().get(0).getToscaTopologyTemplate().getNodeTemplates(), + commonOrInstanceNodeTypeProps); + } + + /** * Get the requested control loop definitions. * * @param name the name of the definition to get, null for all definitions @@ -195,47 +358,77 @@ public class CommissioningProvider { } /** + * Get the tosca service template with only required sections. + * + * @param name the name of the template to get, null for all definitions + * @param version the version of the template to get, null for all definitions + * @return the tosca service template + * @throws PfModelException on errors getting tosca service template + */ + public String getToscaServiceTemplateReduced(String name, String version) throws PfModelException { + var serviceTemplates = new ToscaServiceTemplates(); + serviceTemplates.setServiceTemplates(modelsProvider.getServiceTemplateList(name, version)); + + ToscaServiceTemplate fullTemplate = serviceTemplates.getServiceTemplates().get(0); + + var template = new HashMap<String, Object>(); + template.put("tosca_definitions_version", fullTemplate.getToscaDefinitionsVersion()); + template.put("data_types", fullTemplate.getDataTypes()); + template.put("policy_types", fullTemplate.getPolicyTypes()); + template.put("node_types", fullTemplate.getNodeTypes()); + template.put("topology_template", fullTemplate.getToscaTopologyTemplate()); + + try { + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(template); + + } catch (JsonProcessingException e) { + throw new PfModelException(Status.BAD_REQUEST, "Converion to Json Schema failed", e); + } + } + + /** * Get the requested json schema. * * @param section section of the tosca service template to get schema for * @return the specified tosca service template or section Json Schema * @throws PfModelException on errors with retrieving the classes - * @throws JsonProcessingException on errors generating the schema */ - public String getToscaServiceTemplateSchema(String section) throws PfModelException, JsonProcessingException { - ObjectMapper mapper = new ObjectMapper(); - mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); - SchemaFactoryWrapper visitor = new SchemaFactoryWrapper(); - - switch (section) { - case "data_types": - mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaDataType.class), visitor); - break; - case "capability_types": - mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaCapabilityType.class), visitor); - break; - case "node_types": - mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaNodeType.class), visitor); - break; - case "relationship_types": - mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaRelationshipType.class), visitor); - break; - case "policy_types": - mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaPolicyType.class), visitor); - break; - case "topology_template": - mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaTopologyTemplate.class), visitor); - break; - case "node_templates": - mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaNodeTemplate.class), visitor); - break; - default: - mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaServiceTemplate.class), visitor); - } + public String getToscaServiceTemplateSchema(String section) throws PfModelException { + var visitor = new SchemaFactoryWrapper(); - JsonSchema jsonSchema = visitor.finalSchema(); - String response = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema); + try { + switch (section) { + case "data_types": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaDataType.class), visitor); + break; + case "capability_types": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaCapabilityType.class), visitor); + break; + case "node_types": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaNodeType.class), visitor); + break; + case "relationship_types": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaRelationshipType.class), visitor); + break; + case "policy_types": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaPolicyType.class), visitor); + break; + case "topology_template": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaTopologyTemplate.class), visitor); + break; + case "node_templates": + mapper.acceptJsonFormatVisitor( + mapper.getTypeFactory().constructCollectionType(List.class, ToscaNodeTemplate.class), + visitor); + break; + default: + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaServiceTemplate.class), visitor); + } - return response; + var jsonSchema = visitor.finalSchema(); + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema); + } catch (JsonProcessingException e) { + throw new PfModelException(Status.BAD_REQUEST, "Converion to Json Schema failed", e); + } } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/PropertiesConfig.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/PropertiesConfig.java deleted file mode 100644 index 04bd35da3..000000000 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/PropertiesConfig.java +++ /dev/null @@ -1,38 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.clamp.controlloop.runtime.config; - -import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException; -import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; -import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterHandler; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class PropertiesConfig { - - @Bean - public ClRuntimeParameterGroup clRuntimeParameterGroup(@Value("${runtime.file}") String file) - throws ControlLoopException { - return new ClRuntimeParameterHandler().getParameters(file); - } -} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterGroup.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterGroup.java index d1fa31261..86473caa8 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterGroup.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterGroup.java @@ -20,38 +20,49 @@ package org.onap.policy.clamp.controlloop.runtime.main.parameters; -import javax.validation.constraints.NotBlank; +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; import lombok.Getter; -import org.onap.policy.common.endpoints.parameters.RestServerParameters; +import lombok.Setter; import org.onap.policy.common.endpoints.parameters.TopicParameterGroup; -import org.onap.policy.common.parameters.ParameterGroupImpl; -import org.onap.policy.common.parameters.annotations.NotNull; +import org.onap.policy.common.parameters.validation.ParameterGroupConstraint; import org.onap.policy.models.provider.PolicyModelsProviderParameters; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; /** * Class to hold all parameters needed for the Control Loop runtime component. * */ -@NotNull -@NotBlank +@Validated @Getter -public class ClRuntimeParameterGroup extends ParameterGroupImpl { - private RestServerParameters restServerParameters; +@Setter +@ConfigurationProperties(prefix = "runtime") +public class ClRuntimeParameterGroup { + + @NotNull + @ParameterGroupConstraint private PolicyModelsProviderParameters databaseProviderParameters; + + @Valid + @NotNull private ParticipantParameters participantParameters; + + @NotNull + @ParameterGroupConstraint private TopicParameterGroup topicParameterGroup; + @Min(value = 0) private long supervisionScannerIntervalSec; - private long participantStateChangeIntervalSec; + + @Min(value = 0) private long participantClUpdateIntervalSec; + + @Min(value = 0) private long participantClStateChangeIntervalSec; + private long participantRegisterAckIntervalSec; + private long participantDeregisterAckIntervalSec; + private long participantUpdateIntervalSec; - /** - * Create the Control Loop parameter group. - * - * @param name the parameter group name - */ - public ClRuntimeParameterGroup(final String name) { - super(name); - } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterHandler.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterHandler.java deleted file mode 100644 index bcf1124d2..000000000 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterHandler.java +++ /dev/null @@ -1,72 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.clamp.controlloop.runtime.main.parameters; - -import java.io.File; -import javax.ws.rs.core.Response; -import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException; -import org.onap.policy.common.parameters.ValidationResult; -import org.onap.policy.common.utils.coder.Coder; -import org.onap.policy.common.utils.coder.CoderException; -import org.onap.policy.common.utils.coder.StandardCoder; - -/** - * This class handles reading, parsing and validating of control loop runtime parameters from JSON files. - */ -public class ClRuntimeParameterHandler { - - private static final Coder CODER = new StandardCoder(); - - /** - * Read the parameters from the parameter file. - * - * @param path the path passed to control loop runtime - * @return the parameters read from the configuration file - * @throws ControlLoopException on parameter exceptions - */ - public ClRuntimeParameterGroup getParameters(final String path) throws ControlLoopException { - ClRuntimeParameterGroup clRuntimeParameterGroup = null; - - // Read the parameters - try { - // Read the parameters from JSON - File file = new File(path); - clRuntimeParameterGroup = CODER.decode(file, ClRuntimeParameterGroup.class); - } catch (final CoderException e) { - throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE, - "error reading parameters from \"" + path + "\"\n" + "(" + e.getClass().getSimpleName() + ")", e); - } - - // The JSON processing returns null if there is an empty file - if (clRuntimeParameterGroup == null) { - throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE, "no parameters found in \"" + path + "\""); - } - - // validate the parameters - final ValidationResult validationResult = clRuntimeParameterGroup.validate(); - if (!validationResult.isValid()) { - throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE, - "validation error(s) on parameters from \"" + path + "\"\n" + validationResult.getResult()); - } - - return clRuntimeParameterGroup; - } -} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantParameters.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantParameters.java index dfc1b2806..47a99ca29 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantParameters.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantParameters.java @@ -19,19 +19,20 @@ package org.onap.policy.clamp.controlloop.runtime.main.parameters; import java.util.concurrent.TimeUnit; +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; import lombok.Getter; -import org.onap.policy.common.parameters.ParameterGroupImpl; -import org.onap.policy.common.parameters.annotations.Min; -import org.onap.policy.common.parameters.annotations.NotBlank; -import org.onap.policy.common.parameters.annotations.NotNull; +import lombok.Setter; +import org.springframework.validation.annotation.Validated; /** * Parameters for communicating with participants. */ -@NotNull -@NotBlank @Getter -public class ParticipantParameters extends ParameterGroupImpl { +@Setter +@Validated +public class ParticipantParameters { /** * Default maximum message age, in milliseconds, that should be examined. Any message @@ -39,21 +40,13 @@ public class ParticipantParameters extends ParameterGroupImpl { */ public static final long DEFAULT_MAX_AGE_MS = TimeUnit.MILLISECONDS.convert(10, TimeUnit.MINUTES); - @Min(1) private long heartBeatMs; @Min(1) private long maxMessageAgeMs = DEFAULT_MAX_AGE_MS; + @Valid + @NotNull private ParticipantUpdateParameters updateParameters; - private ParticipantStateChangeParameters stateChangeParameters; - - - /** - * Constructs the object. - */ - public ParticipantParameters() { - super(ParticipantParameters.class.getSimpleName()); - } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantStateChangeParameters.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantStateChangeParameters.java deleted file mode 100644 index 2eea4ab51..000000000 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantStateChangeParameters.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.clamp.controlloop.runtime.main.parameters; - -import lombok.Getter; -import org.onap.policy.common.parameters.ParameterGroupImpl; -import org.onap.policy.common.parameters.annotations.Min; -import org.onap.policy.common.parameters.annotations.NotBlank; -import org.onap.policy.common.parameters.annotations.NotNull; - -/** - * Parameters for Participant STATE-CHANGE requests. - */ -@NotNull -@NotBlank -@Getter -public class ParticipantStateChangeParameters extends ParameterGroupImpl { - - /** - * Maximum number of times to re-send a request to a PDP. - */ - @Min(value = 0) - private int maxRetryCount; - - /** - * Maximum time to wait, in milliseconds, for a PDP response. - */ - @Min(value = 0) - private long maxWaitMs; - - /** - * Constructs the object. - */ - public ParticipantStateChangeParameters() { - super(ParticipantStateChangeParameters.class.getSimpleName()); - } -} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantUpdateParameters.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantUpdateParameters.java index 2af5be534..8102fe90e 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantUpdateParameters.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ParticipantUpdateParameters.java @@ -18,19 +18,18 @@ package org.onap.policy.clamp.controlloop.runtime.main.parameters; +import javax.validation.constraints.Min; import lombok.Getter; -import org.onap.policy.common.parameters.ParameterGroupImpl; -import org.onap.policy.common.parameters.annotations.Min; -import org.onap.policy.common.parameters.annotations.NotBlank; -import org.onap.policy.common.parameters.annotations.NotNull; +import lombok.Setter; +import org.springframework.validation.annotation.Validated; /** * Parameters for Participant UPDATE requests. */ -@NotNull -@NotBlank @Getter -public class ParticipantUpdateParameters extends ParameterGroupImpl { +@Setter +@Validated +public class ParticipantUpdateParameters { /** * Maximum number of times to re-send a request to a PDP. @@ -44,11 +43,4 @@ public class ParticipantUpdateParameters extends ParameterGroupImpl { @Min(value = 0) private long maxWaitMs; - /** - * Constructs the object. - */ - public ParticipantUpdateParameters() { - super(ParticipantUpdateParameters.class.getSimpleName()); - } } - diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java index b50e7a0ed..ec7f14d8b 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java @@ -20,11 +20,6 @@ package org.onap.policy.clamp.controlloop.runtime.main.rest; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.module.jsonSchema.JsonSchema; -import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; @@ -34,18 +29,16 @@ import io.swagger.annotations.Extension; import io.swagger.annotations.ExtensionProperty; import io.swagger.annotations.ResponseHeader; import java.util.List; +import java.util.Map; import java.util.UUID; import javax.ws.rs.core.Response.Status; +import lombok.RequiredArgsConstructor; import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse; import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController; import org.onap.policy.models.base.PfModelException; -import org.onap.policy.models.base.PfModelRuntimeException; 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; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; @@ -60,27 +53,20 @@ import org.springframework.web.bind.annotation.RestController; * Class to provide REST end points for creating, deleting, querying commissioned control loops. */ @RestController +@RequiredArgsConstructor public class CommissioningController extends AbstractRestController { - private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class); + private static final String TAGS = "Clamp Control Loop Commissioning API"; private final CommissioningProvider provider; /** - * Create Commissioning Controller. - * - * @param provider the CommissioningProvider - */ - public CommissioningController(CommissioningProvider provider) { - this.provider = provider; - } - - /** * 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 + * @throws PfModelException on errors creating a control loop definition */ // @formatter:off @PostMapping(value = "/commission", @@ -90,7 +76,7 @@ public class CommissioningController extends AbstractRestController { 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"}, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -133,17 +119,10 @@ public class CommissioningController extends AbstractRestController { @RequestHeader( name = REQUEST_ID_NAME, required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ToscaServiceTemplate body) { - try { - return ResponseEntity.ok().body(provider.createControlLoopDefinitions(body)); - - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Commissioning of the control loops failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); - } + @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ToscaServiceTemplate body) + throws PfModelException { + return ResponseEntity.ok().body(provider.createControlLoopDefinitions(body)); } /** @@ -153,6 +132,7 @@ public class CommissioningController extends AbstractRestController { * @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 + * @throws PfModelException on errors deleting a control loop definition */ // @formatter:off @DeleteMapping(value = "/commission", @@ -160,7 +140,7 @@ public class CommissioningController extends AbstractRestController { @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"}, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -206,18 +186,10 @@ public class CommissioningController extends AbstractRestController { value = "name") String name, @ApiParam( value = "Control Loop definition version", - required = true) @RequestParam("version") String version) { - - try { - return ResponseEntity.ok().body(provider.deleteControlLoopDefinition(name, version)); - - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Decommisssioning of control loop failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); - } + required = true) @RequestParam("version") String version) + throws PfModelException { + return ResponseEntity.ok().body(provider.deleteControlLoopDefinition(name, version)); } /** @@ -227,6 +199,7 @@ public class CommissioningController extends AbstractRestController { * @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 + * @throws PfModelException on errors getting details of all or specific control loop definitions */ // @formatter:off @GetMapping(value = "/commission", @@ -235,7 +208,7 @@ public class CommissioningController extends AbstractRestController { notes = "Queries details of the requested commissioned control loop definitions, " + "returning all control loop details", response = ToscaNodeTemplate.class, - tags = {"Clamp Control Loop Commissioning API"}, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -266,7 +239,7 @@ public class CommissioningController extends AbstractRestController { } ) // @formatter:on - public ResponseEntity<?> query( + public ResponseEntity<List<ToscaNodeTemplate>> query( @RequestHeader( name = REQUEST_ID_NAME, required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, @@ -275,18 +248,10 @@ public class CommissioningController extends AbstractRestController { required = false) String name, @ApiParam(value = "Control Loop definition version", required = false) @RequestParam( value = "version", - required = false) String version) { - - try { - return ResponseEntity.ok().body(provider.getControlLoopDefinitions(name, version)); - - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Get of control loop definitions failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); - } + required = false) String version) + throws PfModelException { + return ResponseEntity.ok().body(provider.getControlLoopDefinitions(name, version)); } /** @@ -296,6 +261,7 @@ public class CommissioningController extends AbstractRestController { * @param name the name of the tosca service template to retrieve * @param version the version of the tosca service template to get * @return the specified tosca service template + * @throws PfModelException on errors getting the Tosca Service Template */ // @formatter:off @GetMapping(value = "/commission/toscaservicetemplate", @@ -304,7 +270,7 @@ public class CommissioningController extends AbstractRestController { notes = "Queries details of the requested commissioned tosca service template, " + "returning all tosca service template details", response = ToscaServiceTemplate.class, - tags = {"Clamp Control Loop Commissioning API"}, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -335,27 +301,19 @@ public class CommissioningController extends AbstractRestController { } ) // @formatter:on - public ResponseEntity<?> queryToscaServiceTemplate( + public ResponseEntity<String> queryToscaServiceTemplate( @RequestHeader( name = REQUEST_ID_NAME, required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, @ApiParam(value = "Tosca service template name", required = false) @RequestParam( value = "name", required = false) String name, - @ApiParam(value = "Tosca service template version", required = true) @RequestParam( + @ApiParam(value = "Tosca service template version", required = false) @RequestParam( value = "version", - required = false) String version) { - - try { - return ResponseEntity.ok().body(provider.getToscaServiceTemplate(name, version)); - - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Get of tosca service template failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); - } + required = false) String version) + throws PfModelException { + return ResponseEntity.ok().body(provider.getToscaServiceTemplateReduced(name, version)); } /** @@ -364,6 +322,7 @@ public class CommissioningController extends AbstractRestController { * @param requestId request ID used in ONAP logging * @param section section of the tosca service template to get schema for * @return the specified tosca service template or section Json Schema + * @throws PfModelException on errros getting the Json Schema for the specified Tosca Service Template */ // @formatter:off @GetMapping(value = "/commission/toscaServiceTemplateSchema", @@ -372,7 +331,7 @@ public class CommissioningController extends AbstractRestController { notes = "Queries details of the requested commissioned tosca service template json schema, " + "returning all tosca service template json schema details", response = ToscaServiceTemplate.class, - tags = {"Clamp Control Loop Commissioning API"}, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -403,27 +362,84 @@ public class CommissioningController extends AbstractRestController { } ) // @formatter:on - public ResponseEntity<?> queryToscaServiceTemplateJsonSchema( - @RequestHeader( - name = REQUEST_ID_NAME, - required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Section of Template schema is desired for", required = false) @RequestParam( - value = "section", - required = false, defaultValue = "all") String section) { - try { - return ResponseEntity.ok().body(provider.getToscaServiceTemplateSchema(section)); + public ResponseEntity<String> queryToscaServiceTemplateJsonSchema( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Section of Template schema is desired for", required = false) @RequestParam( + value = "section", + required = false, + defaultValue = "all") String section) + throws PfModelException { + + return ResponseEntity.ok().body(provider.getToscaServiceTemplateSchema(section)); + } - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Get of tosca service template json schema failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); - } catch (JsonProcessingException e) { - LOGGER.warn("Get of tosca service template json schema failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getMessage()); - return ResponseEntity.status(Status.BAD_REQUEST.getStatusCode()).body(resp); + /** + * Retrieves the Common or Instance Properties for the specified Tosca Service Template. + * + * @param requestId request ID used in ONAP logging + * @param common a flag, true to get common properties, false to get instance properties + * @param name the name of the tosca service template to retrieve + * @param version the version of the tosca service template to get + * @return the specified tosca service template or section Json Schema + * @throws PfModelException on errors getting the Common or Instance Properties + */ + // @formatter:off + @GetMapping(value = "/commission/getCommonOrInstanceProperties", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) + @ApiOperation(value = "Query details of the requested tosca service template common or instance properties", + notes = "Queries details of the requested commissioned tosca service template json common" + + "or instance properties, returning all tosca service template common or instance property details", + response = ToscaServiceTemplate.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 ResponseEntity<Map<String, ToscaNodeTemplate>> queryToscaServiceCommonOrInstanceProperties( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Flag, true for common properties, false for instance", required = false) @RequestParam( + value = "common", + defaultValue = "false", + required = false) boolean common, + @ApiParam(value = "Tosca service template name", required = false) @RequestParam( + value = "name", + required = false) String name, + @ApiParam(value = "Tosca service template version", required = false) @RequestParam( + value = "version", + required = false) String version) + throws PfModelException { + + return ResponseEntity.ok().body(provider.getNodeTemplatesWithCommonOrInstanceProperties(common, name, version)); } /** @@ -433,6 +449,7 @@ public class CommissioningController extends AbstractRestController { * @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 + * @throws PfModelException on errors getting the elements of a specific control loop */ // @formatter:off @GetMapping(value = "/commission/elements", @@ -441,7 +458,7 @@ public class CommissioningController extends AbstractRestController { 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"}, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -472,35 +489,25 @@ public class CommissioningController extends AbstractRestController { } ) // @formatter:on - public ResponseEntity<?> queryElements( + public ResponseEntity<List<ToscaNodeTemplate>> queryElements( @RequestHeader( name = REQUEST_ID_NAME, required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, @ApiParam(value = "Control Loop definition name", required = false) @RequestParam( value = "name", required = false) String name, - @ApiParam(value = "Control Loop definition version", required = true) @RequestParam( + @ApiParam(value = "Control Loop definition version", required = false) @RequestParam( value = "version", - required = false) String version) { - - try { - List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version); - // Prevent ambiguous queries with multiple returns - if (nodeTemplate.size() > 1) { - var resp = new CommissioningResponse(); - resp.setErrorDetails("Multiple ControlLoops are not supported"); - return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).body(resp); - } - - List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0)); - return ResponseEntity.ok().body(response); + required = false) String version) + throws PfModelException { - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Get of control loop element definitions failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version); + // Prevent ambiguous queries with multiple returns + if (nodeTemplate.size() > 1) { + throw new PfModelException(Status.NOT_ACCEPTABLE, "Multiple ControlLoops are not supported"); } + List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0)); + return ResponseEntity.ok().body(response); } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/InstantiationController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/InstantiationController.java index aba585e29..29919f528 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/InstantiationController.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/InstantiationController.java @@ -29,6 +29,7 @@ import io.swagger.annotations.Extension; import io.swagger.annotations.ExtensionProperty; import io.swagger.annotations.ResponseHeader; import java.util.UUID; +import lombok.RequiredArgsConstructor; import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops; import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand; @@ -36,10 +37,6 @@ import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.Inst import org.onap.policy.clamp.controlloop.runtime.instantiation.ControlLoopInstantiationProvider; import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController; import org.onap.policy.models.base.PfModelException; -import org.onap.policy.models.base.PfModelRuntimeException; -import org.onap.policy.models.errors.concepts.ErrorResponseInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; @@ -55,28 +52,21 @@ import org.springframework.web.bind.annotation.RestController; * Class to provide REST end points for creating, deleting, query and commanding a control loop definition. */ @RestController +@RequiredArgsConstructor public class InstantiationController extends AbstractRestController { - private static final Logger LOGGER = LoggerFactory.getLogger(InstantiationController.class); + private static final String TAGS = "Clamp Control Loop Instantiation API"; // The CL provider for instantiation requests private final ControlLoopInstantiationProvider provider; /** - * Create Instantiation Controller. - * - * @param provider the ControlLoopInstantiationProvider - */ - public InstantiationController(ControlLoopInstantiationProvider provider) { - this.provider = provider; - } - - /** * Creates a control loop. * * @param requestId request ID used in ONAP logging * @param controlLoops the control loops * @return a response + * @throws PfModelException on errors creating a control loop */ // @formatter:off @PostMapping(value = "/instantiation", @@ -86,7 +76,7 @@ public class InstantiationController extends AbstractRestController { value = "Commissions control loop definitions", notes = "Commissions control loop definitions, returning the control loop IDs", response = InstantiationResponse.class, - tags = {"Control Loop Instantiation API"}, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -126,18 +116,13 @@ public class InstantiationController extends AbstractRestController { ) // @formatter:on public ResponseEntity<InstantiationResponse> create( - @RequestHeader(name = REQUEST_ID_NAME, required = false) - @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Entity Body of Control Loop", required = true) - @RequestBody ControlLoops controlLoops) { - - try { - return ResponseEntity.ok().body(provider.createControlLoops(controlLoops)); + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ControlLoops controlLoops) + throws PfModelException { - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("creation of control loop failed", e); - return createInstantiationErrorResponse(e); - } + return ResponseEntity.ok().body(provider.createControlLoops(controlLoops)); } /** @@ -147,6 +132,7 @@ public class InstantiationController extends AbstractRestController { * @param name the name of the control loop to get, null for all control loops * @param version the version of the control loop to get, null for all control loops * @return the control loops + * @throws PfModelException on errors getting commissioning of control loop */ // @formatter:off @GetMapping(value = "/instantiation", @@ -154,9 +140,7 @@ public class InstantiationController extends AbstractRestController { @ApiOperation(value = "Query details of the requested control loops", notes = "Queries details of the requested control loops, returning all control loop details", response = ControlLoops.class, - tags = { - "Clamp control loop Instantiation API" - }, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -187,22 +171,19 @@ public class InstantiationController extends AbstractRestController { } ) // @formatter:on - public ResponseEntity<?> query( - @RequestHeader(name = REQUEST_ID_NAME, required = false) - @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Control Loop definition name", required = false) - @RequestParam(value = "name", required = false) String name, - @ApiParam(value = "Control Loop definition version", required = false) - @RequestParam(value = "version", required = false) String version) { - - try { - return ResponseEntity.ok().body(provider.getControlLoops(name, version)); - - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("commisssioning of control loop failed", e); - return createInstantiationErrorResponse(e); - } + public ResponseEntity<ControlLoops> query( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop definition name", required = false) @RequestParam( + value = "name", + required = false) String name, + @ApiParam(value = "Control Loop definition version", required = false) @RequestParam( + value = "version", + required = false) String version) + throws PfModelException { + return ResponseEntity.ok().body(provider.getControlLoops(name, version)); } /** @@ -211,6 +192,7 @@ public class InstantiationController extends AbstractRestController { * @param requestId request ID used in ONAP logging * @param controlLoops the control loops * @return a response + * @throws PfModelException on errors updating of control loops */ // @formatter:off @PutMapping(value = "/instantiation", @@ -220,9 +202,7 @@ public class InstantiationController extends AbstractRestController { value = "Updates control loop definitions", notes = "Updates control loop definitions, returning the updated control loop definition IDs", response = InstantiationResponse.class, - tags = { - "Control Loop Instantiation API" - }, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -262,18 +242,13 @@ public class InstantiationController extends AbstractRestController { ) // @formatter:on public ResponseEntity<InstantiationResponse> update( - @RequestHeader(name = REQUEST_ID_NAME, required = false) - @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Entity Body of Control Loop", required = true) - @RequestBody ControlLoops controlLoops) { - - try { - return ResponseEntity.ok().body(provider.updateControlLoops(controlLoops)); + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ControlLoops controlLoops) + throws PfModelException { - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("update of control loops failed", e); - return createInstantiationErrorResponse(e); - } + return ResponseEntity.ok().body(provider.updateControlLoops(controlLoops)); } /** @@ -283,6 +258,7 @@ public class InstantiationController extends AbstractRestController { * @param name the name of the control loop to delete * @param version the version of the control loop to delete * @return a response + * @throws PfModelException on errors deleting of control loop */ // @formatter:off @DeleteMapping(value = "/instantiation", @@ -290,9 +266,7 @@ public class InstantiationController extends AbstractRestController { @ApiOperation(value = "Delete a control loop", notes = "Deletes a control loop, returning optional error details", response = InstantiationResponse.class, - tags = { - "Clamp Control Loop Instantiation API" - }, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -332,20 +306,16 @@ public class InstantiationController extends AbstractRestController { // @formatter:on public ResponseEntity<InstantiationResponse> delete( - @RequestHeader(name = REQUEST_ID_NAME, required = false) - @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Control Loop definition name", required = true) - @RequestParam("name") String name, - @ApiParam(value = "Control Loop definition version") - @RequestParam(value = "version", required = false) String version) { - - try { - return ResponseEntity.ok().body(provider.deleteControlLoop(name, version)); + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop definition name", required = true) @RequestParam("name") String name, + @ApiParam(value = "Control Loop definition version") @RequestParam( + value = "version", + required = false) String version) + throws PfModelException { - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("delete of control loop failed", e); - return createInstantiationErrorResponse(e); - } + return ResponseEntity.ok().body(provider.deleteControlLoop(name, version)); } /** @@ -354,6 +324,8 @@ public class InstantiationController extends AbstractRestController { * @param requestId request ID used in ONAP logging * @param command the command to issue to control loops * @return the control loop definitions + * @throws PfModelException on errors issuing a command + * @throws ControlLoopException on errors issuing a command */ // @formatter:off @PutMapping(value = "/instantiation/command", @@ -362,9 +334,7 @@ public class InstantiationController extends AbstractRestController { @ApiOperation(value = "Issue a command to the requested control loops", notes = "Issues a command to a control loop, ordering a state change on the control loop", response = InstantiationResponse.class, - tags = { - "Clamp Control Loop Instantiation API" - }, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -396,29 +366,14 @@ public class InstantiationController extends AbstractRestController { ) // @formatter:on public ResponseEntity<InstantiationResponse> issueControlLoopCommand( - @RequestHeader(name = REQUEST_ID_NAME, required = false) - @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Entity Body of control loop command", required = true) - @RequestBody InstantiationCommand command) { - - try { - return ResponseEntity.accepted().body(provider.issueControlLoopCommand(command)); - - } catch (PfModelRuntimeException | PfModelException | ControlLoopException e) { - LOGGER.warn("creation of control loop failed", e); - return createInstantiationErrorResponse(e); - } - } + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam( + value = "Entity Body of control loop command", + required = true) @RequestBody InstantiationCommand command) + throws ControlLoopException, PfModelException { - /** - * create a Instantiation Response from an exception. - * - * @param e the error - * @return the Instantiation Response - */ - private ResponseEntity<InstantiationResponse> createInstantiationErrorResponse(ErrorResponseInfo e) { - var resp = new InstantiationResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + return ResponseEntity.accepted().body(provider.issueControlLoopCommand(command)); } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/MonitoringQueryController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/MonitoringQueryController.java index 86531597a..c4ce5bb05 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/MonitoringQueryController.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/MonitoringQueryController.java @@ -30,14 +30,12 @@ import io.swagger.annotations.ExtensionProperty; import io.swagger.annotations.ResponseHeader; import java.time.Instant; import java.util.UUID; +import lombok.RequiredArgsConstructor; 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.web.AbstractRestController; 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; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -49,21 +47,13 @@ import org.springframework.web.bind.annotation.RestController; * This class handles REST endpoints for CL Statistics monitoring. */ @RestController +@RequiredArgsConstructor public class MonitoringQueryController extends AbstractRestController { - private static final Logger LOGGER = LoggerFactory.getLogger(MonitoringQueryController.class); + private static final String TAGS = "Clamp Control Loop Monitoring API"; private final MonitoringProvider provider; /** - * Create Monitoring Controller. - * - * @param provider the MonitoringProvider - */ - public MonitoringQueryController(MonitoringProvider provider) { - this.provider = provider; - } - - /** * Queries details of control loop participants statistics. * * @param requestId request ID used in ONAP logging @@ -80,9 +70,7 @@ public class MonitoringQueryController extends AbstractRestController { @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" - }, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -134,24 +122,17 @@ public class MonitoringQueryController extends AbstractRestController { value = "endTime", required = false) final String endTime) { - try { - Instant startTimestamp = null; - Instant endTimestamp = null; + Instant startTimestamp = null; + Instant endTimestamp = null; - if (startTime != null) { - startTimestamp = Instant.parse(startTime); - } - if (endTime != null) { - endTimestamp = Instant.parse(endTime); - } - return ResponseEntity.ok().body(provider.fetchFilteredParticipantStatistics(name, version, recordCount, - startTimestamp, endTimestamp)); - - } catch (PfModelRuntimeException e) { - LOGGER.warn("Monitoring of participants statistics failed", e); - return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build(); + if (startTime != null) { + startTimestamp = Instant.parse(startTime); } - + if (endTime != null) { + endTimestamp = Instant.parse(endTime); + } + return ResponseEntity.ok().body( + provider.fetchFilteredParticipantStatistics(name, version, recordCount, startTimestamp, endTimestamp)); } /** @@ -168,9 +149,7 @@ public class MonitoringQueryController extends AbstractRestController { @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" - }, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -211,14 +190,7 @@ public class MonitoringQueryController extends AbstractRestController { value = "version", required = false) final String version) { - try { - return ResponseEntity.ok().body(provider.fetchParticipantStatsPerControlLoop(name, version)); - - } catch (PfModelRuntimeException e) { - LOGGER.warn("Monitoring of Cl participant statistics failed", e); - return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build(); - } - + return ResponseEntity.ok().body(provider.fetchParticipantStatsPerControlLoop(name, version)); } /** @@ -235,9 +207,7 @@ public class MonitoringQueryController extends AbstractRestController { @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" - }, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -278,14 +248,7 @@ public class MonitoringQueryController extends AbstractRestController { value = "version", required = false) final String version) { - try { - return ResponseEntity.ok().body(provider.fetchClElementStatsPerControlLoop(name, version)); - - } catch (PfModelRuntimeException e) { - LOGGER.warn("Monitoring of Cl Element statistics failed", e); - return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build(); - } - + return ResponseEntity.ok().body(provider.fetchClElementStatsPerControlLoop(name, version)); } /** @@ -299,6 +262,7 @@ public class MonitoringQueryController extends AbstractRestController { * @param startTime the time from which to get statistics * @param endTime the time to which to get statistics * @return the control loop element statistics + * @throws PfModelException on errors getting details of all control loop element statistics per control loop */ // @formatter:off @GetMapping(value = "/monitoring/clelement", @@ -306,9 +270,7 @@ public class MonitoringQueryController extends AbstractRestController { @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" - }, + tags = {TAGS}, authorizations = @Authorization(value = AUTHORIZATION_TYPE), responseHeaders = { @ResponseHeader( @@ -360,26 +322,20 @@ public class MonitoringQueryController extends AbstractRestController { required = false) final String startTime, @ApiParam(value = "end time", required = false) @RequestParam( value = "endTime", - required = false) final String endTime) { - - try { - Instant startTimestamp = null; - Instant endTimestamp = null; + required = false) final String endTime) + throws PfModelException { - if (startTime != null) { - startTimestamp = Instant.parse(startTime); - } - if (endTime != null) { - endTimestamp = Instant.parse(endTime); - } - return ResponseEntity.ok().body(provider.fetchFilteredClElementStatistics(name, version, id, startTimestamp, - endTimestamp, recordCount)); + Instant startTimestamp = null; + Instant endTimestamp = null; - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Monitoring of Cl Element statistics failed", e); - return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build(); + if (startTime != null) { + startTimestamp = Instant.parse(startTime); } - + if (endTime != null) { + endTimestamp = Instant.parse(endTime); + } + return ResponseEntity.ok().body(provider.fetchFilteredClElementStatistics(name, version, id, startTimestamp, + endTimestamp, recordCount)); } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/GlobalControllerExceptionHandler.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/GlobalControllerExceptionHandler.java new file mode 100644 index 000000000..d093c677f --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/GlobalControllerExceptionHandler.java @@ -0,0 +1,73 @@ +/*- + * ============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.main.web; + +import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException; +import org.onap.policy.clamp.controlloop.models.messages.rest.SimpleResponse; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.base.PfModelRuntimeException; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalControllerExceptionHandler { + + /** + * Handle ControlLoopException. + * + * @param ex ControlLoopException + * @return ResponseEntity + */ + @ExceptionHandler(ControlLoopException.class) + public ResponseEntity<SimpleResponse> handleBadRequest(ControlLoopException ex) { + var resp = new SimpleResponse(); + resp.setErrorDetails(ex.getErrorResponse().getErrorMessage()); + return ResponseEntity.status(ex.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + } + + /** + * Handle PfModelRuntimeException. + * + * @param ex PfModelRuntimeException + * @return ResponseEntity + */ + @ExceptionHandler(PfModelRuntimeException.class) + public ResponseEntity<SimpleResponse> handleBadRequest(PfModelRuntimeException ex) { + var resp = new SimpleResponse(); + resp.setErrorDetails(ex.getErrorResponse().getErrorMessage()); + return ResponseEntity.status(ex.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + } + + /** + * Handle PfModelException. + * + * @param ex PfModelException + * @return ResponseEntity + */ + @ExceptionHandler(PfModelException.class) + public ResponseEntity<SimpleResponse> handleBadRequest(PfModelException ex) { + var resp = new SimpleResponse(); + resp.setErrorDetails(ex.getErrorResponse().getErrorMessage()); + return ResponseEntity.status(ex.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + } + +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounter.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounter.java new file mode 100644 index 000000000..2151dc143 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounter.java @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision; + +import java.time.Instant; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import lombok.Getter; +import lombok.Setter; + +public class HandleCounter<K> { + @Getter + @Setter + private long maxWaitMs; + + @Getter + @Setter + private int maxRetryCount; + + private Map<K, Integer> mapCounter = new HashMap<>(); + private Set<K> mapFault = new HashSet<>(); + private Map<K, Long> mapTimer = new HashMap<>(); + + public long getDuration(K id) { + mapTimer.putIfAbsent(id, getEpochMilli()); + return getEpochMilli() - mapTimer.get(id); + } + + /** + * Reset timer and clear counter and fault by id. + * + * @param id the id + */ + public void clear(K id) { + mapFault.remove(id); + mapCounter.put(id, 0); + mapTimer.put(id, getEpochMilli()); + } + + public void setFault(K id) { + mapCounter.put(id, 0); + mapFault.add(id); + } + + /** + * Increment RetryCount by id e return true if minor or equal of maxRetryCount. + * + * @param id the identifier + * @return false if count is major of maxRetryCount + */ + public boolean count(K id) { + int counter = mapCounter.getOrDefault(id, 0) + 1; + if (counter <= maxRetryCount) { + mapCounter.put(id, counter); + return true; + } + return false; + } + + public boolean isFault(K id) { + return mapFault.contains(id); + } + + public int getCounter(K id) { + return mapCounter.getOrDefault(id, 0); + } + + protected long getEpochMilli() { + return Instant.now().toEpochMilli(); + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStateChangePublisher.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/MessageIntercept.java index b63cbdf03..c23ed833d 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStateChangePublisher.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/MessageIntercept.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. + * 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. @@ -18,15 +18,15 @@ * ============LICENSE_END========================================================= */ -package org.onap.policy.clamp.controlloop.runtime.supervision.comm; +package org.onap.policy.clamp.controlloop.runtime.supervision; -import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStateChange; -import org.springframework.stereotype.Component; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; -/** - * This class is used to send ParticipantStateChange messages to participants on DMaaP. - */ -@Component -public class ParticipantStateChangePublisher extends AbstractParticipantPublisher<ParticipantStateChange> { +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface MessageIntercept { } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspect.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspect.java new file mode 100644 index 000000000..d0d18ab1a --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspect.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision; + +import java.io.Closeable; +import java.io.IOException; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import lombok.RequiredArgsConstructor; +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Aspect +@Component +@RequiredArgsConstructor +public class SupervisionAspect implements Closeable { + + private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionAspect.class); + + private final SupervisionScanner supervisionScanner; + + private ThreadPoolExecutor executor = + new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); + + @Scheduled( + fixedRateString = "${runtime.participantParameters.heartBeatMs}", + initialDelayString = "${runtime.participantParameters.heartBeatMs}") + public void schedule() { + LOGGER.info("Add scheduled scanning"); + executor.execute(() -> supervisionScanner.run(true)); + } + + /** + * Intercept Messages from participant and run Supervision Scan. + */ + @After("@annotation(MessageIntercept)") + public void doCheck() { + if (executor.getQueue().size() < 2) { + LOGGER.debug("Add scanning Message"); + executor.execute(() -> supervisionScanner.run(false)); + } + } + + @Before("@annotation(MessageIntercept) && args(participantStatusMessage,..)") + public void handleParticipantStatus(ParticipantStatus participantStatusMessage) { + executor.execute(() -> supervisionScanner.handleParticipantStatus(participantStatusMessage.getParticipantId())); + } + + @Override + public void close() throws IOException { + executor.shutdown(); + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java index aba545750..16dba0f07 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java @@ -21,20 +21,28 @@ package org.onap.policy.clamp.controlloop.runtime.supervision; import java.util.List; +import java.util.Map; import javax.ws.rs.core.Response; import lombok.AllArgsConstructor; import org.apache.commons.collections4.CollectionUtils; import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopInfo; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant; import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider; import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregister; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegister; import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdateAck; import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider; -import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantControlLoopStateChangePublisher; -import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantControlLoopUpdatePublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopStateChangePublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopUpdatePublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantDeregisterAckPublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantRegisterAckPublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantUpdatePublisher; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.slf4j.Logger; @@ -62,8 +70,11 @@ public class SupervisionHandler { private final MonitoringProvider monitoringProvider; // Publishers for participant communication - private final ParticipantControlLoopUpdatePublisher controlLoopUpdatePublisher; - private final ParticipantControlLoopStateChangePublisher controlLoopStateChangePublisher; + private final ControlLoopUpdatePublisher controlLoopUpdatePublisher; + private final ControlLoopStateChangePublisher controlLoopStateChangePublisher; + private final ParticipantRegisterAckPublisher participantRegisterAckPublisher; + private final ParticipantDeregisterAckPublisher participantDeregisterAckPublisher; + private final ParticipantUpdatePublisher participantUpdatePublisher; /** * Supervision trigger called when a command is issued on control loops. @@ -102,9 +113,9 @@ public class SupervisionHandler { * * @param participantStatusMessage the ParticipantStatus message received from a participant */ - public void handleParticipantStatusMessage(ParticipantStatus participantStatusMessage) { + @MessageIntercept + public void handleParticipantMessage(ParticipantStatus participantStatusMessage) { LOGGER.debug("Participant Status received {}", participantStatusMessage); - try { superviseParticipant(participantStatusMessage); } catch (PfModelException | ControlLoopException svExc) { @@ -120,6 +131,42 @@ public class SupervisionHandler { } /** + * Handle a ParticipantRegister message from a participant. + * + * @param participantRegisterMessage the ParticipantRegister message received from a participant + */ + @MessageIntercept + public void handleParticipantMessage(ParticipantRegister participantRegisterMessage) { + LOGGER.debug("Participant Register received {}", participantRegisterMessage); + + participantRegisterAckPublisher.send(participantRegisterMessage.getMessageId()); + + participantUpdatePublisher.send(participantRegisterMessage.getParticipantId(), + participantRegisterMessage.getParticipantType()); + } + + /** + * Handle a ParticipantDeregister message from a participant. + * + * @param participantDeregisterMessage the ParticipantDeregister message received from a participant + */ + @MessageIntercept + public void handleParticipantMessage(ParticipantDeregister participantDeregisterMessage) { + LOGGER.debug("Participant Deregister received {}", participantDeregisterMessage); + participantDeregisterAckPublisher.send(participantDeregisterMessage.getMessageId()); + } + + /** + * Handle a ParticipantUpdateAck message from a participant. + * + * @param participantUpdateAckMessage the ParticipantUpdateAck message received from a participant + */ + @MessageIntercept + public void handleParticipantMessage(ParticipantUpdateAck participantUpdateAckMessage) { + LOGGER.debug("Participant Update Ack received {}", participantUpdateAckMessage); + } + + /** * Supervise a control loop, performing whatever actions need to be performed on the control loop. * * @param controlLoop the control loop to supervises @@ -265,39 +312,17 @@ public class SupervisionHandler { private void superviseControlLoops(ParticipantStatus participantStatusMessage) throws PfModelException, ControlLoopException { - if (CollectionUtils.isEmpty(participantStatusMessage.getControlLoops().getControlLoopList())) { - return; - } - - for (ControlLoop controlLoop : participantStatusMessage.getControlLoops().getControlLoopList()) { - if (controlLoop == null) { - exceptionOccured(Response.Status.NOT_FOUND, - "PARTICIPANT_STATUS message references unknown control loop: " + controlLoop); - } - - var dbControlLoop = controlLoopProvider - .getControlLoop(new ToscaConceptIdentifier(controlLoop.getName(), controlLoop.getVersion())); + for (Map.Entry<ToscaConceptIdentifier, ControlLoopInfo> clEntry : + participantStatusMessage.getControlLoopInfoMap().entrySet()) { + var dbControlLoop = controlLoopProvider.getControlLoop(new ToscaConceptIdentifier( + clEntry.getKey().getName(), clEntry.getKey().getVersion())); if (dbControlLoop == null) { exceptionOccured(Response.Status.NOT_FOUND, - "PARTICIPANT_STATUS control loop not found in database: " + controlLoop); + "PARTICIPANT_STATUS control loop not found in database: " + clEntry.getKey()); } - - for (ControlLoopElement element : controlLoop.getElements().values()) { - ControlLoopElement dbElement = dbControlLoop.getElements().get(element.getId()); - - if (dbElement == null) { - exceptionOccured(Response.Status.NOT_FOUND, - "PARTICIPANT_STATUS message references unknown control loop element: " + element); - } - - // Replace element entry in the database - dbControlLoop.getElements().put(element.getId(), element); - } - controlLoopProvider.updateControlLoop(dbControlLoop); - } - - for (ControlLoop controlLoop : participantStatusMessage.getControlLoops().getControlLoopList()) { - monitoringProvider.createClElementStatistics(controlLoop.getControlLoopElementStatisticsList(controlLoop)); + dbControlLoop.setState(clEntry.getValue().getState()); + monitoringProvider.createClElementStatistics(clEntry.getValue() + .getControlLoopStatistics().getClElementStatisticsList().getClElementStatistics()); } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScanner.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScanner.java index 68f5830c0..7be407c3f 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScanner.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScanner.java @@ -20,15 +20,20 @@ package org.onap.policy.clamp.controlloop.runtime.supervision; -import java.io.Closeable; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.List; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantHealthStatus; import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider; +import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider; import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopStateChangePublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopUpdatePublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantStatusReqPublisher; import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -37,35 +42,76 @@ import org.springframework.stereotype.Component; * This class is used to scan the control loops in the database and check if they are in the correct state. */ @Component -public class SupervisionScanner implements Runnable, Closeable { +public class SupervisionScanner { private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionScanner.class); - private ControlLoopProvider controlLoopProvider; - private ScheduledExecutorService timerPool; + private HandleCounter<ToscaConceptIdentifier> controlLoopCounter = new HandleCounter<>(); + private HandleCounter<ToscaConceptIdentifier> participantCounter = new HandleCounter<>(); + + private final ControlLoopProvider controlLoopProvider; + private final ControlLoopStateChangePublisher controlLoopStateChangePublisher; + private final ControlLoopUpdatePublisher controlLoopUpdatePublisher; + private final ParticipantProvider participantProvider; + private final ParticipantStatusReqPublisher participantStatusReqPublisher; + + private final long maxMessageAgeMs; /** * Constructor for instantiating SupervisionScanner. * - * @param clRuntimeParameterGroup the parameters for the control loop runtime * @param controlLoopProvider the provider to use to read control loops from the database + * @param controlLoopStateChangePublisher the ControlLoop StateChange Publisher + * @param controlLoopUpdatePublisher the ControlLoopUpdate Publisher + * @param participantProvider the Participant Provider + * @param participantStatusReqPublisher the Participant StatusReq Publisher + * @param clRuntimeParameterGroup the parameters for the control loop runtime */ public SupervisionScanner(final ControlLoopProvider controlLoopProvider, - ClRuntimeParameterGroup clRuntimeParameterGroup) { + final ControlLoopStateChangePublisher controlLoopStateChangePublisher, + ControlLoopUpdatePublisher controlLoopUpdatePublisher, ParticipantProvider participantProvider, + ParticipantStatusReqPublisher participantStatusReqPublisher, + final ClRuntimeParameterGroup clRuntimeParameterGroup) { this.controlLoopProvider = controlLoopProvider; - - // Kick off the timer - timerPool = makeTimerPool(); - timerPool.scheduleAtFixedRate(this, 0, clRuntimeParameterGroup.getSupervisionScannerIntervalSec(), - TimeUnit.SECONDS); + this.controlLoopStateChangePublisher = controlLoopStateChangePublisher; + this.controlLoopUpdatePublisher = controlLoopUpdatePublisher; + this.participantProvider = participantProvider; + this.participantStatusReqPublisher = participantStatusReqPublisher; + + controlLoopCounter.setMaxRetryCount( + clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount()); + controlLoopCounter + .setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs()); + + participantCounter.setMaxRetryCount( + clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount()); + participantCounter + .setMaxWaitMs(clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs()); + + maxMessageAgeMs = clRuntimeParameterGroup.getParticipantParameters().getMaxMessageAgeMs(); } - @Override - public void run() { + /** + * Run Scanning. + * + * @param counterCheck if true activate counter and retry + */ + public void run(boolean counterCheck) { LOGGER.debug("Scanning control loops in the database . . ."); + if (counterCheck) { + try { + for (Participant participant : participantProvider.getParticipants(null, null)) { + scanParticipant(participant); + } + } catch (PfModelException pfme) { + LOGGER.warn("error reading participant from database", pfme); + return; + } + } + try { for (ControlLoop controlLoop : controlLoopProvider.getControlLoops(null, null)) { - scanControlLoop(controlLoop); + scanControlLoop(controlLoop, counterCheck); } } catch (PfModelException pfme) { LOGGER.warn("error reading control loops from database", pfme); @@ -74,40 +120,92 @@ public class SupervisionScanner implements Runnable, Closeable { LOGGER.debug("Control loop scan complete . . ."); } - @Override - public void close() { - timerPool.shutdown(); + private void scanParticipant(Participant participant) throws PfModelException { + ToscaConceptIdentifier id = participant.getKey().asIdentifier(); + if (participantCounter.isFault(id)) { + LOGGER.debug("report Participant fault"); + return; + } + if (participantCounter.getDuration(id) > maxMessageAgeMs) { + if (participantCounter.count(id)) { + LOGGER.debug("retry message ParticipantStatusReq"); + participantStatusReqPublisher.send(id); + participant.setHealthStatus(ParticipantHealthStatus.NOT_HEALTHY); + } else { + LOGGER.debug("report Participant fault"); + participantCounter.setFault(id); + participant.setHealthStatus(ParticipantHealthStatus.OFF_LINE); + } + participantProvider.updateParticipants(List.of(participant)); + } } - private void scanControlLoop(final ControlLoop controlLoop) throws PfModelException { + /** + * handle participant Status message. + */ + public void handleParticipantStatus(ToscaConceptIdentifier id) { + participantCounter.clear(id); + } + + private void scanControlLoop(final ControlLoop controlLoop, boolean counterCheck) throws PfModelException { LOGGER.debug("scanning control loop {} . . .", controlLoop.getKey().asIdentifier()); if (controlLoop.getState().equals(controlLoop.getOrderedState().asState())) { LOGGER.debug("control loop {} scanned, OK", controlLoop.getKey().asIdentifier()); + + // Clear missed report counter on Control Loop + clearFaultAndCounter(controlLoop); return; } + boolean completed = true; for (ControlLoopElement element : controlLoop.getElements().values()) { if (!element.getState().equals(element.getOrderedState().asState())) { - LOGGER.debug("control loop scan: transitioning from state {} to {}", controlLoop.getState(), - controlLoop.getOrderedState()); - return; + completed = false; + break; } } - LOGGER.debug("control loop scan: transition from state {} to {} completed", controlLoop.getState(), - controlLoop.getOrderedState()); + if (completed) { + LOGGER.debug("control loop scan: transition from state {} to {} completed", controlLoop.getState(), + controlLoop.getOrderedState()); + + controlLoop.setState(controlLoop.getOrderedState().asState()); + controlLoopProvider.updateControlLoop(controlLoop); - controlLoop.setState(controlLoop.getOrderedState().asState()); - controlLoopProvider.updateControlLoop(controlLoop); + // Clear missed report counter on Control Loop + clearFaultAndCounter(controlLoop); + } else { + LOGGER.debug("control loop scan: transition from state {} to {} not completed", controlLoop.getState(), + controlLoop.getOrderedState()); + if (counterCheck) { + handleCounter(controlLoop); + } + } } - /** - * Makes a new timer pool. - * - * @return a new timer pool - */ - protected ScheduledExecutorService makeTimerPool() { - return Executors.newScheduledThreadPool(1); + private void clearFaultAndCounter(ControlLoop controlLoop) { + controlLoopCounter.clear(controlLoop.getKey().asIdentifier()); + } + + private void handleCounter(ControlLoop controlLoop) { + ToscaConceptIdentifier id = controlLoop.getKey().asIdentifier(); + if (controlLoopCounter.isFault(id)) { + LOGGER.debug("report ControlLoop fault"); + return; + } + + if (controlLoopCounter.count(id)) { + if (ControlLoopState.UNINITIALISED2PASSIVE.equals(controlLoop.getState())) { + LOGGER.debug("retry message ControlLoopUpdate"); + controlLoopUpdatePublisher.send(controlLoop); + } else { + LOGGER.debug("retry message ControlLoopStateChange"); + controlLoopStateChangePublisher.send(controlLoop); + } + } else { + LOGGER.debug("report ControlLoop fault"); + controlLoopCounter.setFault(id); + } } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/AbstractParticipantAckPublisher.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/AbstractParticipantAckPublisher.java new file mode 100644 index 000000000..4b4ca9915 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/AbstractParticipantAckPublisher.java @@ -0,0 +1,62 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision.comm; + +import java.util.List; +import javax.ws.rs.core.Response.Status; +import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantAckMessage; +import org.onap.policy.clamp.controlloop.runtime.config.messaging.Publisher; +import org.onap.policy.common.endpoints.event.comm.TopicSink; +import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; + +public abstract class AbstractParticipantAckPublisher<E extends ParticipantAckMessage> implements Publisher { + + private TopicSinkClient topicSinkClient; + private boolean active = false; + + /** + * Method to send Participant message to participants on demand. + * + * @param participantMessage the Participant message + */ + public void send(final E participantMessage) { + if (!active) { + throw new ControlLoopRuntimeException(Status.NOT_ACCEPTABLE, "Not Active!"); + } + topicSinkClient.send(participantMessage); + } + + + @Override + public void active(List<TopicSink> topicSinks) { + if (topicSinks.size() != 1) { + throw new IllegalArgumentException("Topic Sink must be one"); + } + this.topicSinkClient = new TopicSinkClient(topicSinks.get(0)); + active = true; + } + + @Override + public void stop() { + active = false; + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantControlLoopStateChangePublisher.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ControlLoopStateChangePublisher.java index 734ccb842..79d113c14 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantControlLoopStateChangePublisher.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ControlLoopStateChangePublisher.java @@ -22,15 +22,15 @@ package org.onap.policy.clamp.controlloop.runtime.supervision.comm; import java.util.UUID; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop; -import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantControlLoopStateChange; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopStateChange; import org.springframework.stereotype.Component; /** - * This class is used to send ParticipantControlLoopStateChangePublisher messages to participants on DMaaP. + * This class is used to send ControlLoopStateChangePublisher messages to participants on DMaaP. */ @Component -public class ParticipantControlLoopStateChangePublisher - extends AbstractParticipantPublisher<ParticipantControlLoopStateChange> { +public class ControlLoopStateChangePublisher + extends AbstractParticipantPublisher<ControlLoopStateChange> { /** * Send ControlLoopStateChange to Participant. @@ -38,7 +38,7 @@ public class ParticipantControlLoopStateChangePublisher * @param controlLoop the ControlLoop */ public void send(ControlLoop controlLoop) { - var clsc = new ParticipantControlLoopStateChange(); + var clsc = new ControlLoopStateChange(); clsc.setControlLoopId(controlLoop.getKey().asIdentifier()); clsc.setMessageId(UUID.randomUUID()); clsc.setOrderedState(controlLoop.getOrderedState()); diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ControlLoopUpdatePublisher.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ControlLoopUpdatePublisher.java new file mode 100644 index 000000000..448662cfe --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ControlLoopUpdatePublisher.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision.comm; + +import lombok.AllArgsConstructor; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopUpdate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * This class is used to send ControlLoopUpdate messages to participants on DMaaP. + */ +@Component +@AllArgsConstructor +public class ControlLoopUpdatePublisher extends AbstractParticipantPublisher<ControlLoopUpdate> { + + private static final Logger LOGGER = LoggerFactory.getLogger(ControlLoopUpdatePublisher.class); + + /** + * Send ControlLoopUpdate to Participant. + * + * @param controlLoop the ControlLoop + */ + public void send(ControlLoop controlLoop) { + var controlLoopUpdateMsg = new ControlLoopUpdate(); + controlLoopUpdateMsg.setControlLoopId(controlLoop.getKey().asIdentifier()); + controlLoopUpdateMsg.setControlLoop(controlLoop); + LOGGER.debug("ControlLoopUpdate message sent", controlLoopUpdateMsg); + super.send(controlLoopUpdateMsg); + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantControlLoopUpdatePublisher.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantControlLoopUpdatePublisher.java deleted file mode 100644 index 8d40c5e69..000000000 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantControlLoopUpdatePublisher.java +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.clamp.controlloop.runtime.supervision.comm; - -import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop; -import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantControlLoopUpdate; -import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; -import org.onap.policy.models.base.PfModelException; -import org.springframework.stereotype.Component; - -/** - * This class is used to send ParticipantControlLoopUpdate messages to participants on DMaaP. - */ -@Component -public class ParticipantControlLoopUpdatePublisher extends AbstractParticipantPublisher<ParticipantControlLoopUpdate> { - - private final CommissioningProvider commissioningProvider; - - /** - * Constructor. - * - * @param commissioningProvider the CommissioningProvider - */ - public ParticipantControlLoopUpdatePublisher(CommissioningProvider commissioningProvider) { - this.commissioningProvider = commissioningProvider; - } - - /** - * Send ControlLoopUpdate to Participant. - * - * @param controlLoop the ControlLoop - * @throws PfModelException on errors getting the Control Loop Definition - */ - public void send(ControlLoop controlLoop) throws PfModelException { - var pclu = new ParticipantControlLoopUpdate(); - pclu.setControlLoopId(controlLoop.getKey().asIdentifier()); - pclu.setControlLoop(controlLoop); - // TODO: We should look up the correct TOSCA node template here for the control loop - // Tiny hack implemented to return the tosca service template entry from the database and be passed onto dmaap - pclu.setControlLoopDefinition(commissioningProvider.getToscaServiceTemplate(null, null)); - super.send(pclu); - } -} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantDeregisterAckPublisher.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantDeregisterAckPublisher.java new file mode 100644 index 000000000..e92b6ee1b --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantDeregisterAckPublisher.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision.comm; + +import java.util.UUID; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregisterAck; +import org.springframework.stereotype.Component; + +/** + * This class is used to send ParticipantDeregisterAck messages to participants on DMaaP. + */ +@Component +public class ParticipantDeregisterAckPublisher extends AbstractParticipantAckPublisher<ParticipantDeregisterAck> { + + /** + * Sent ParticipantDeregisterAck to Participant. + * + * @param responseTo the original request id in the request. + */ + public void send(UUID responseTo) { + var message = new ParticipantDeregisterAck(); + message.setResponseTo(responseTo); + message.setMessage("Participant Deregister Ack"); + message.setResult(true); + super.send(message); + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantDeregisterListener.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantDeregisterListener.java new file mode 100644 index 000000000..a03ff0a63 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantDeregisterListener.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision.comm; + +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregister; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessageType; +import org.onap.policy.clamp.controlloop.runtime.config.messaging.Listener; +import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler; +import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; +import org.onap.policy.common.endpoints.listeners.ScoListener; +import org.onap.policy.common.utils.coder.StandardCoderObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * Listener for ParticipantDeregister messages sent by participants. + */ +@Component +public class ParticipantDeregisterListener extends ScoListener<ParticipantDeregister> implements Listener { + private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantDeregisterListener.class); + + private final SupervisionHandler supervisionHandler; + + /** + * Constructs the object. + */ + public ParticipantDeregisterListener(SupervisionHandler supervisionHandler) { + super(ParticipantDeregister.class); + this.supervisionHandler = supervisionHandler; + } + + @Override + public void onTopicEvent(final CommInfrastructure infra, final String topic, final StandardCoderObject sco, + final ParticipantDeregister participantDeregisterMessage) { + LOGGER.debug("ParticipantDeregister message received from participant - {}", participantDeregisterMessage); + supervisionHandler.handleParticipantMessage(participantDeregisterMessage); + } + + @Override + public String getType() { + return ParticipantMessageType.PARTICIPANT_DEREGISTER.name(); + } + + @Override + public ScoListener<ParticipantDeregister> getScoListener() { + return this; + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantRegisterAckPublisher.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantRegisterAckPublisher.java new file mode 100644 index 000000000..73860b5c2 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantRegisterAckPublisher.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision.comm; + +import java.util.UUID; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegisterAck; +import org.springframework.stereotype.Component; + +/** + * This class is used to send ParticipantRegisterAck messages to participants on DMaaP. + */ +@Component +public class ParticipantRegisterAckPublisher extends AbstractParticipantAckPublisher<ParticipantRegisterAck> { + + /** + * Send ParticipantRegisterAck to Participant. + * + * @param responseTo the original request id in the request. + */ + public void send(UUID responseTo) { + var message = new ParticipantRegisterAck(); + message.setResponseTo(responseTo); + message.setMessage("Participant Register Ack"); + message.setResult(true); + super.send(message); + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantRegisterListener.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantRegisterListener.java new file mode 100644 index 000000000..a4d8c7697 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantRegisterListener.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision.comm; + +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessageType; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegister; +import org.onap.policy.clamp.controlloop.runtime.config.messaging.Listener; +import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler; +import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; +import org.onap.policy.common.endpoints.listeners.ScoListener; +import org.onap.policy.common.utils.coder.StandardCoderObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * Listener for ParticipantRegister messages sent by participants. + */ +@Component +public class ParticipantRegisterListener extends ScoListener<ParticipantRegister> implements Listener { + private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantRegisterListener.class); + + private final SupervisionHandler supervisionHandler; + + /** + * Constructs the object. + */ + public ParticipantRegisterListener(SupervisionHandler supervisionHandler) { + super(ParticipantRegister.class); + this.supervisionHandler = supervisionHandler; + } + + @Override + public void onTopicEvent(final CommInfrastructure infra, final String topic, final StandardCoderObject sco, + final ParticipantRegister participantRegisterMessage) { + LOGGER.debug("ParticipantRegister message received from participant - {}", participantRegisterMessage); + supervisionHandler.handleParticipantMessage(participantRegisterMessage); + } + + @Override + public String getType() { + return ParticipantMessageType.PARTICIPANT_REGISTER.name(); + } + + @Override + public ScoListener<ParticipantRegister> getScoListener() { + return this; + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusListener.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusListener.java index 8fa076240..9da886026 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusListener.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusListener.java @@ -52,7 +52,7 @@ public class ParticipantStatusListener extends ScoListener<ParticipantStatus> im public void onTopicEvent(final CommInfrastructure infra, final String topic, final StandardCoderObject sco, final ParticipantStatus participantStatusMessage) { LOGGER.debug("ParticipantStatus message received from participant - {}", participantStatusMessage); - supervisionHandler.handleParticipantStatusMessage(participantStatusMessage); + supervisionHandler.handleParticipantMessage(participantStatusMessage); } @Override diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusReqPublisher.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusReqPublisher.java new file mode 100644 index 000000000..69d598285 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusReqPublisher.java @@ -0,0 +1,48 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision.comm; + +import java.time.Instant; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatusReq; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class ParticipantStatusReqPublisher extends AbstractParticipantPublisher<ParticipantStatusReq> { + + private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantStatusReqPublisher.class); + + /** + * Send ParticipantStatusReq to Participant. + * + * @param participantId the participant Id + */ + public void send(ToscaConceptIdentifier participantId) { + ParticipantStatusReq message = new ParticipantStatusReq(); + message.setParticipantId(participantId); + message.setTimestamp(Instant.now()); + + LOGGER.debug("Participant StatusReq sent {}", message); + super.send(message); + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantUpdateAckListener.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantUpdateAckListener.java new file mode 100644 index 000000000..4eeb0a8ce --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantUpdateAckListener.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision.comm; + +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessageType; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdateAck; +import org.onap.policy.clamp.controlloop.runtime.config.messaging.Listener; +import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler; +import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; +import org.onap.policy.common.endpoints.listeners.ScoListener; +import org.onap.policy.common.utils.coder.StandardCoderObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * Listener for ParticipantUpdateAck messages sent by participants. + */ +@Component +public class ParticipantUpdateAckListener extends ScoListener<ParticipantUpdateAck> implements Listener { + private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantUpdateAckListener.class); + + private final SupervisionHandler supervisionHandler; + + /** + * Constructs the object. + */ + public ParticipantUpdateAckListener(SupervisionHandler supervisionHandler) { + super(ParticipantUpdateAck.class); + this.supervisionHandler = supervisionHandler; + } + + @Override + public void onTopicEvent(final CommInfrastructure infra, final String topic, final StandardCoderObject sco, + final ParticipantUpdateAck participantUpdateAckMessage) { + LOGGER.debug("ParticipantUpdateAck message received from participant - {}", participantUpdateAckMessage); + supervisionHandler.handleParticipantMessage(participantUpdateAckMessage); + } + + @Override + public String getType() { + return ParticipantMessageType.PARTICIPANT_UPDATE_ACK.name(); + } + + @Override + public ScoListener<ParticipantUpdateAck> getScoListener() { + return this; + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantUpdatePublisher.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantUpdatePublisher.java new file mode 100644 index 000000000..88cf90d02 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantUpdatePublisher.java @@ -0,0 +1,82 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision.comm; + +import java.time.Instant; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; +import lombok.AllArgsConstructor; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElementDefinition; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdate; +import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * This class is used to send ParticipantUpdate messages to participants on DMaaP. + */ +@Component +@AllArgsConstructor +public class ParticipantUpdatePublisher extends AbstractParticipantPublisher<ParticipantUpdate> { + + private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantUpdatePublisher.class); + + private final CommissioningProvider commissioningProvider; + + /** + * Send ParticipantUpdate to Participant. + * + * @param participantId the participant Id + * @param participantType the participant Type + */ + public void send(ToscaConceptIdentifier participantId, ToscaConceptIdentifier participantType) { + var message = new ParticipantUpdate(); + message.setParticipantId(participantId); + message.setParticipantType(participantType); + message.setTimestamp(Instant.now()); + + var clDefinition = new ControlLoopElementDefinition(); + clDefinition.setId(UUID.randomUUID()); + + try { + clDefinition.setControlLoopElementToscaServiceTemplate( + commissioningProvider.getToscaServiceTemplate(null, null)); + } catch (PfModelException pfme) { + LOGGER.warn("Get of tosca service template failed, cannot send participantupdate", pfme); + return; + } + + Map<UUID, ControlLoopElementDefinition> controlLoopElementDefinitionMap = new LinkedHashMap<>(); + controlLoopElementDefinitionMap.put(UUID.randomUUID(), clDefinition); + + Map<ToscaConceptIdentifier, Map<UUID, ControlLoopElementDefinition>> participantDefinitionUpdateMap = + new LinkedHashMap<>(); + participantDefinitionUpdateMap.put(participantId, controlLoopElementDefinitionMap); + message.setParticipantDefinitionUpdateMap(participantDefinitionUpdateMap); + + LOGGER.debug("Participant Update sent {}", message); + super.send(message); + } +} diff --git a/runtime-controlloop/src/main/resources/application.yaml b/runtime-controlloop/src/main/resources/application.yaml index af9966d40..d0e5500d6 100644 --- a/runtime-controlloop/src/main/resources/application.yaml +++ b/runtime-controlloop/src/main/resources/application.yaml @@ -19,4 +19,33 @@ server: runtime: - file: src/main/resources/parameters/ClRuntimeParameters.json + supervisionScannerIntervalSec: 1000 + participantClUpdateIntervalSec: 1000 + participantClStateChangeIntervalSec: 1000 + participantParameters: + heartBeatMs: 120000 + updateParameters: + maxRetryCount: 1 + maxWaitMs: 30000 + databaseProviderParameters: + name: PolicyProviderParameterGroup + implementation: org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl + databaseDriver: org.mariadb.jdbc.Driver + databaseUrl: jdbc:mariadb://${mariadb.host:localhost}:${mariadb.port:3306}/controlloop + databaseUser: policy + databasePassword: P01icY + persistenceUnit: CommissioningMariaDb + topicParameterGroup: + topicSources: + - + topic: POLICY-CLRUNTIME-PARTICIPANT + servers: + - ${topicServer:localhost} + topicCommInfrastructure: dmaap + fetchTimeout: 15000 + topicSinks: + - + topic: POLICY-CLRUNTIME-PARTICIPANT + servers: + - ${topicServer:localhost} + topicCommInfrastructure: dmaap diff --git a/runtime-controlloop/src/main/resources/parameters/ClRuntimeParameters.json b/runtime-controlloop/src/main/resources/parameters/ClRuntimeParameters.json deleted file mode 100644 index 00ca7f9a6..000000000 --- a/runtime-controlloop/src/main/resources/parameters/ClRuntimeParameters.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "ControlLoopRuntimeGroup", - "supervisionScannerIntervalSec": 1000, - "participantStateChangeIntervalSec": 1000, - "participantClUpdateIntervalSec": 1000, - "participantClStateChangeIntervalSec": 1000, - "restServerParameters": { - "host": "0.0.0.0", - "port": 6969, - "userName": "healthcheck", - "password": "zb!XztG34", - "https": false, - "aaf": false - }, - "participantParameters": { - "heartBeatMs": 120000, - "updateParameters": { - "maxRetryCount": 1, - "maxWaitMs": 30000 - }, - "stateChangeParameters": { - "maxRetryCount": 1, - "maxWaitMs": 30000 - } - }, - "databaseProviderParameters": { - "name": "PolicyProviderParameterGroup", - "implementation": "org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl", - "databaseDriver": "org.mariadb.jdbc.Driver", - "databaseUrl": "jdbc:mariadb://mariadb:3306/controlloop", - "databaseUser": "policy", - "databasePassword": "P01icY", - "persistenceUnit": "CommissioningMariaDb" - }, - "topicParameterGroup": { - "topicSources": [ - { - "topic": "POLICY-CLRUNTIME-PARTICIPANT", - "servers": [ - "message-router" - ], - "topicCommInfrastructure": "dmaap", - "fetchTimeout": 15000 - } - ], - "topicSinks": [ - { - "topic": "POLICY-CLRUNTIME-PARTICIPANT", - "servers": [ - "message-router" - ], - "topicCommInfrastructure": "dmaap" - } - ] - } -} diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProviderTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProviderTest.java index 440380781..448df4199 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProviderTest.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProviderTest.java @@ -31,9 +31,6 @@ import org.junit.jupiter.api.Test; import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider; import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData; -import org.onap.policy.common.utils.coder.Coder; -import org.onap.policy.common.utils.coder.CoderException; -import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.coder.YamlJsonTranslator; import org.onap.policy.common.utils.resources.ResourceUtils; import org.onap.policy.models.provider.PolicyModelsProvider; @@ -46,31 +43,11 @@ class CommissioningProviderTest { private static final String TOSCA_SERVICE_TEMPLATE_YAML = "src/test/resources/rest/servicetemplates/pmsh_multiple_cl_tosca.yaml"; private static final String TEMPLATE_IS_NULL = ".*serviceTemplate is marked non-null but is null"; - private static final Coder CODER = new StandardCoder(); private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator(); - private static int dbNum = 0; - private static final Object lockit = new Object(); private PolicyModelsProvider modelsProvider = null; private ControlLoopProvider clProvider = null; - private static String getParameterGroupAsString() { - dbNum++; - return ResourceUtils.getResourceAsString("src/test/resources/parameters/TestParameters.json") - .replace("jdbc:h2:mem:testdb", "jdbc:h2:mem:commissioningdb" + dbNum); - } - - /** - * return a Cl Runtime Parameters. - * - * @throws CoderException . - */ - public ClRuntimeParameterGroup getClRuntimeParameterGroup() throws CoderException { - synchronized (lockit) { - return CODER.decode(getParameterGroupAsString(), ClRuntimeParameterGroup.class); - } - } - @AfterEach void close() throws Exception { if (modelsProvider != null) { @@ -88,7 +65,7 @@ class CommissioningProviderTest { */ @Test void testGetControlLoopDefinitions() throws Exception { - ClRuntimeParameterGroup clRuntimeParameterGroup = getClRuntimeParameterGroup(); + ClRuntimeParameterGroup clRuntimeParameterGroup = CommonTestData.geParameterGroup("getCLDefinitions"); modelsProvider = CommonTestData.getPolicyModelsProvider(clRuntimeParameterGroup.getDatabaseProviderParameters()); clProvider = new ControlLoopProvider(clRuntimeParameterGroup.getDatabaseProviderParameters()); @@ -125,7 +102,7 @@ class CommissioningProviderTest { */ @Test void testCreateControlLoopDefinitions() throws Exception { - ClRuntimeParameterGroup clRuntimeParameterGroup = getClRuntimeParameterGroup(); + ClRuntimeParameterGroup clRuntimeParameterGroup = CommonTestData.geParameterGroup("createCLDefinitions"); modelsProvider = CommonTestData.getPolicyModelsProvider(clRuntimeParameterGroup.getDatabaseProviderParameters()); clProvider = new ControlLoopProvider(clRuntimeParameterGroup.getDatabaseProviderParameters()); @@ -154,7 +131,7 @@ class CommissioningProviderTest { */ @Test void testDeleteControlLoopDefinitions() throws Exception { - ClRuntimeParameterGroup clRuntimeParameterGroup = getClRuntimeParameterGroup(); + ClRuntimeParameterGroup clRuntimeParameterGroup = CommonTestData.geParameterGroup("deleteCLDefinitions"); modelsProvider = CommonTestData.getPolicyModelsProvider(clRuntimeParameterGroup.getDatabaseProviderParameters()); clProvider = new ControlLoopProvider(clRuntimeParameterGroup.getDatabaseProviderParameters()); @@ -182,7 +159,7 @@ class CommissioningProviderTest { */ @Test void testGetControlLoopElementDefinitions() throws Exception { - ClRuntimeParameterGroup clRuntimeParameterGroup = getClRuntimeParameterGroup(); + ClRuntimeParameterGroup clRuntimeParameterGroup = CommonTestData.geParameterGroup("getCLElDefinitions"); modelsProvider = CommonTestData.getPolicyModelsProvider(clRuntimeParameterGroup.getDatabaseProviderParameters()); clProvider = new ControlLoopProvider(clRuntimeParameterGroup.getDatabaseProviderParameters()); diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/config/messaging/MessageDispatcherActivatorTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/config/messaging/MessageDispatcherActivatorTest.java index 2b4abaa3b..461c8b558 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/config/messaging/MessageDispatcherActivatorTest.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/config/messaging/MessageDispatcherActivatorTest.java @@ -33,8 +33,8 @@ import static org.mockito.Mockito.when; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; -import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterHandler; import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantStatusListener; +import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.coder.StandardCoderObject; @@ -52,8 +52,7 @@ class MessageDispatcherActivatorTest { @Test void testStartAndStop() throws Exception { - final String path = "src/test/resources/parameters/TestParameters.json"; - ClRuntimeParameterGroup parameterGroup = new ClRuntimeParameterHandler().getParameters(path); + ClRuntimeParameterGroup parameterGroup = CommonTestData.geParameterGroup("dbtest"); var publisherFirst = spy(mock(Publisher.class)); var publisherSecond = spy(mock(Publisher.class)); diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProviderTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProviderTest.java index 1d7a00b18..c414ffa02 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProviderTest.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProviderTest.java @@ -43,8 +43,11 @@ import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProv import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider; import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler; -import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantControlLoopStateChangePublisher; -import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantControlLoopUpdatePublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopStateChangePublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopUpdatePublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantDeregisterAckPublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantRegisterAckPublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantUpdatePublisher; import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.provider.PolicyModelsProvider; @@ -97,7 +100,7 @@ class ControlLoopInstantiationProviderTest { */ @BeforeAll public static void setupDbProviderParameters() throws PfModelException { - ClRuntimeParameterGroup controlLoopParameters = CommonTestData.geParameterGroup(0, "instantproviderdb"); + ClRuntimeParameterGroup controlLoopParameters = CommonTestData.geParameterGroup("instantproviderdb"); modelsProvider = CommonTestData.getPolicyModelsProvider(controlLoopParameters.getDatabaseProviderParameters()); @@ -110,10 +113,14 @@ class ControlLoopInstantiationProviderTest { var monitoringProvider = new MonitoringProvider(participantStatisticsProvider, clElementStatisticsProvider, clProvider); var participantProvider = new ParticipantProvider(controlLoopParameters.getDatabaseProviderParameters()); - var controlLoopUpdatePublisher = Mockito.mock(ParticipantControlLoopUpdatePublisher.class); - var controlLoopStateChangePublisher = Mockito.mock(ParticipantControlLoopStateChangePublisher.class); + var controlLoopUpdatePublisher = Mockito.mock(ControlLoopUpdatePublisher.class); + var controlLoopStateChangePublisher = Mockito.mock(ControlLoopStateChangePublisher.class); + var participantRegisterAckPublisher = Mockito.mock(ParticipantRegisterAckPublisher.class); + var participantDeregisterAckPublisher = Mockito.mock(ParticipantDeregisterAckPublisher.class); + var participantUpdatePublisher = Mockito.mock(ParticipantUpdatePublisher.class); supervisionHandler = new SupervisionHandler(clProvider, participantProvider, monitoringProvider, - controlLoopUpdatePublisher, controlLoopStateChangePublisher); + controlLoopUpdatePublisher, controlLoopStateChangePublisher, + participantRegisterAckPublisher, participantDeregisterAckPublisher, participantUpdatePublisher); } @AfterAll diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/TestMonitoringProvider.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/TestMonitoringProvider.java index c47211a2d..5f885ec97 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/TestMonitoringProvider.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/TestMonitoringProvider.java @@ -97,7 +97,7 @@ class TestMonitoringProvider { @Test void testCreateParticipantStatistics() throws Exception { - ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "createparStat"); + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup("createparStat"); participantStatisticsProvider = new ParticipantStatisticsProvider(parameters.getDatabaseProviderParameters()); clElementStatisticsProvider = new ClElementStatisticsProvider(parameters.getDatabaseProviderParameters()); clProvider = new ControlLoopProvider(parameters.getDatabaseProviderParameters()); @@ -123,7 +123,7 @@ class TestMonitoringProvider { @Test void testGetParticipantStatistics() throws Exception { - ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "getparStat"); + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup("getparStat"); participantStatisticsProvider = new ParticipantStatisticsProvider(parameters.getDatabaseProviderParameters()); clElementStatisticsProvider = new ClElementStatisticsProvider(parameters.getDatabaseProviderParameters()); clProvider = new ControlLoopProvider(parameters.getDatabaseProviderParameters()); @@ -156,7 +156,7 @@ class TestMonitoringProvider { @Test void testCreateClElementStatistics() throws Exception { - ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "createelemstat"); + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup("createelemstat"); participantStatisticsProvider = new ParticipantStatisticsProvider(parameters.getDatabaseProviderParameters()); clElementStatisticsProvider = new ClElementStatisticsProvider(parameters.getDatabaseProviderParameters()); clProvider = new ControlLoopProvider(parameters.getDatabaseProviderParameters()); @@ -183,14 +183,13 @@ class TestMonitoringProvider { @Test void testGetClElementStatistics() throws Exception { - ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "getelemstat"); + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup("getelemstat"); participantStatisticsProvider = new ParticipantStatisticsProvider(parameters.getDatabaseProviderParameters()); clElementStatisticsProvider = new ClElementStatisticsProvider(parameters.getDatabaseProviderParameters()); clProvider = new ControlLoopProvider(parameters.getDatabaseProviderParameters()); MonitoringProvider provider = new MonitoringProvider(participantStatisticsProvider, clElementStatisticsProvider, clProvider); - assertThatThrownBy(() -> { provider.fetchFilteredClElementStatistics(null, null, null, null, null, 0); }).hasMessageMatching("name is marked .*null but is null"); @@ -217,7 +216,7 @@ class TestMonitoringProvider { @Test void testGetParticipantStatsPerCL() throws Exception { - ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "getparStatCL"); + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup("getparStatCL"); participantStatisticsProvider = new ParticipantStatisticsProvider(parameters.getDatabaseProviderParameters()); clElementStatisticsProvider = new ClElementStatisticsProvider(parameters.getDatabaseProviderParameters()); var mockClProvider = Mockito.mock(ControlLoopProvider.class); @@ -253,7 +252,7 @@ class TestMonitoringProvider { mockCL.setElements(new LinkedHashMap<>()); mockCL.getElements().put(mockClElement.getId(), mockClElement); - ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "getelemstatPerCL"); + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup("getelemstatPerCL"); participantStatisticsProvider = new ParticipantStatisticsProvider(parameters.getDatabaseProviderParameters()); clElementStatisticsProvider = new ClElementStatisticsProvider(parameters.getDatabaseProviderParameters()); ControlLoopProvider mockClProvider = Mockito.mock(ControlLoopProvider.class); @@ -265,8 +264,8 @@ class TestMonitoringProvider { monitoringProvider.createClElementStatistics(inputClElementStatistics.getClElementStatistics()); - ClElementStatisticsList getResponse; - getResponse = monitoringProvider.fetchClElementStatsPerControlLoop("testCLName", "1.001"); + ClElementStatisticsList getResponse = + monitoringProvider.fetchClElementStatsPerControlLoop("testCLName", "1.001"); assertThat(getResponse.getClElementStatistics()).hasSize(2); assertEquals(getResponse.getClElementStatistics().get(1).toString().replaceAll("\\s+", ""), diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounterTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounterTest.java new file mode 100644 index 000000000..51f3b4a32 --- /dev/null +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/HandleCounterTest.java @@ -0,0 +1,84 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +class HandleCounterTest { + + private static final int ID = 1; + + @Test + void testCount() { + var handleCounter = new HandleCounter<Integer>(); + handleCounter.setMaxRetryCount(2); + assertThat(handleCounter.count(ID)).isTrue(); + assertThat(handleCounter.getCounter(ID)).isEqualTo(1); + assertThat(handleCounter.count(ID)).isTrue(); + assertThat(handleCounter.getCounter(ID)).isEqualTo(2); + assertThat(handleCounter.count(ID)).isFalse(); + assertThat(handleCounter.getCounter(ID)).isEqualTo(2); + + handleCounter.clear(ID); + assertThat(handleCounter.count(ID)).isTrue(); + assertThat(handleCounter.getCounter(ID)).isEqualTo(1); + } + + @Test + void testFault() { + var handleCounter = new HandleCounter<Integer>(); + handleCounter.setFault(ID); + assertThat(handleCounter.isFault(ID)).isTrue(); + handleCounter.clear(ID); + assertThat(handleCounter.isFault(ID)).isFalse(); + } + + @Test + void testDuration() throws InterruptedException { + + var handleCounter = new HandleCounter<Integer>() { + long epochMilli = 0; + + @Override + protected long getEpochMilli() { + return epochMilli; + } + }; + handleCounter.epochMilli = 100; + var result = handleCounter.getDuration(ID); + assertThat(result).isZero(); + + handleCounter.epochMilli += 100; + result = handleCounter.getDuration(ID); + assertThat(result).isEqualTo(100); + + handleCounter.epochMilli += 100; + result = handleCounter.getDuration(ID); + assertThat(result).isEqualTo(200); + + handleCounter.epochMilli += 100; + handleCounter.clear(ID); + result = handleCounter.getDuration(ID); + assertThat(result).isZero(); + } +} diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspectTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspectTest.java new file mode 100644 index 000000000..30ee9b1b9 --- /dev/null +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspectTest.java @@ -0,0 +1,66 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +class SupervisionAspectTest { + + @Test + void testSchedule() throws Exception { + var supervisionScanner = spy(mock(SupervisionScanner.class)); + try (var supervisionAspect = new SupervisionAspect(supervisionScanner)) { + supervisionAspect.schedule(); + verify(supervisionScanner, timeout(500)).run(eq(true)); + } + } + + @Test + void testDoCheck() throws Exception { + var supervisionScanner = spy(mock(SupervisionScanner.class)); + try (var supervisionAspect = new SupervisionAspect(supervisionScanner)) { + supervisionAspect.doCheck(); + supervisionAspect.doCheck(); + verify(supervisionScanner, timeout(500).times(2)).run(eq(false)); + } + } + + @Test + void testHandleParticipantStatus() throws Exception { + var supervisionScanner = spy(mock(SupervisionScanner.class)); + var participantStatusMessage = new ParticipantStatus(); + var identifier = new ToscaConceptIdentifier("abc", "1.0.0"); + participantStatusMessage.setParticipantId(identifier); + + try (var supervisionAspect = new SupervisionAspect(supervisionScanner)) { + supervisionAspect.handleParticipantStatus(participantStatusMessage); + verify(supervisionScanner, timeout(500)).handleParticipantStatus(eq(identifier)); + } + } +} diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScannerTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScannerTest.java new file mode 100644 index 000000000..485f58dba --- /dev/null +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionScannerTest.java @@ -0,0 +1,160 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantHealthStatus; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantState; +import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider; +import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopStateChangePublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ControlLoopUpdatePublisher; +import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantStatusReqPublisher; +import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +class SupervisionScannerTest { + + @Test + void testScannerOrderedStateEqualsToState() throws PfModelException { + var controlLoopProvider = mock(ControlLoopProvider.class); + var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class); + var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class); + var participantProvider = mock(ParticipantProvider.class); + var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class); + var clRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); + + var controlLoop = new ControlLoop(); + when(controlLoopProvider.getControlLoops(null, null)).thenReturn(List.of(controlLoop)); + + var supervisionScanner = + new SupervisionScanner(controlLoopProvider, controlLoopStateChangePublisher, controlLoopUpdatePublisher, + participantProvider, participantStatusReqPublisher, clRuntimeParameterGroup); + supervisionScanner.run(false); + + verify(controlLoopProvider, times(0)).updateControlLoop(any(ControlLoop.class)); + } + + @Test + void testScannerOrderedStateDifferentToState() throws PfModelException { + var controlLoop = new ControlLoop(); + controlLoop.setState(ControlLoopState.UNINITIALISED2PASSIVE); + controlLoop.setOrderedState(ControlLoopOrderedState.UNINITIALISED); + controlLoop.setElements(Map.of(UUID.randomUUID(), new ControlLoopElement())); + var controlLoopProvider = mock(ControlLoopProvider.class); + when(controlLoopProvider.getControlLoops(null, null)).thenReturn(List.of(controlLoop)); + + var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class); + var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class); + var participantProvider = mock(ParticipantProvider.class); + var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class); + var clRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); + + var supervisionScanner = + new SupervisionScanner(controlLoopProvider, controlLoopStateChangePublisher, controlLoopUpdatePublisher, + participantProvider, participantStatusReqPublisher, clRuntimeParameterGroup); + supervisionScanner.run(false); + + verify(controlLoopProvider, times(1)).updateControlLoop(any(ControlLoop.class)); + } + + @Test + void testScanner() throws PfModelException { + var controlLoopProvider = mock(ControlLoopProvider.class); + var controlLoop = new ControlLoop(); + when(controlLoopProvider.getControlLoops(null, null)).thenReturn(List.of(controlLoop)); + + var participantProvider = mock(ParticipantProvider.class); + var participant = new Participant(); + participant.setName("Participant0"); + participant.setVersion("1.0.0"); + when(participantProvider.getParticipants(null, null)).thenReturn(List.of(participant)); + + var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class); + var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class); + var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class); + var clRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); + + var supervisionScanner = + new SupervisionScanner(controlLoopProvider, controlLoopStateChangePublisher, controlLoopUpdatePublisher, + participantProvider, participantStatusReqPublisher, clRuntimeParameterGroup); + + supervisionScanner.handleParticipantStatus(participant.getKey().asIdentifier()); + supervisionScanner.run(true); + verify(controlLoopProvider, times(0)).updateControlLoop(any(ControlLoop.class)); + verify(participantStatusReqPublisher, times(0)).send(any(ToscaConceptIdentifier.class)); + } + + @Test + void testScanParticipant() throws PfModelException { + var controlLoopProvider = mock(ControlLoopProvider.class); + var controlLoop = new ControlLoop(); + when(controlLoopProvider.getControlLoops(null, null)).thenReturn(List.of(controlLoop)); + + var clRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanParticipant"); + clRuntimeParameterGroup.getParticipantParameters().setMaxMessageAgeMs(0); + + var participant = new Participant(); + participant.setName("Participant0"); + participant.setVersion("1.0.0"); + participant.setHealthStatus(ParticipantHealthStatus.HEALTHY); + participant.setParticipantState(ParticipantState.ACTIVE); + participant.setDefinition(new ToscaConceptIdentifier("unknown", "0.0.0")); + var participantProvider = new ParticipantProvider(clRuntimeParameterGroup.getDatabaseProviderParameters()); + participantProvider.updateParticipants(List.of(participant)); + + var controlLoopUpdatePublisher = mock(ControlLoopUpdatePublisher.class); + var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class); + var controlLoopStateChangePublisher = mock(ControlLoopStateChangePublisher.class); + + var supervisionScanner = + new SupervisionScanner(controlLoopProvider, controlLoopStateChangePublisher, controlLoopUpdatePublisher, + participantProvider, participantStatusReqPublisher, clRuntimeParameterGroup); + + supervisionScanner.handleParticipantStatus(participant.getKey().asIdentifier()); + supervisionScanner.run(true); + verify(participantStatusReqPublisher, times(1)).send(any(ToscaConceptIdentifier.class)); + + List<Participant> participants = participantProvider.getParticipants(null, null); + assertThat(participants.get(0).getHealthStatus()).isEqualTo(ParticipantHealthStatus.NOT_HEALTHY); + + supervisionScanner.run(true); + supervisionScanner.run(true); + participants = participantProvider.getParticipants(null, null); + assertThat(participants.get(0).getHealthStatus()).isEqualTo(ParticipantHealthStatus.OFF_LINE); + } +} diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/SupervisionMessagesTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/SupervisionMessagesTest.java new file mode 100644 index 000000000..5f00706e1 --- /dev/null +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/SupervisionMessagesTest.java @@ -0,0 +1,226 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.controlloop.runtime.supervision.comm; + +import java.time.Instant; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElementDefinition; +import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ClElementStatisticsProvider; +import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider; +import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantProvider; +import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantStatisticsProvider; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregister; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantDeregisterAck; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegister; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantRegisterAck; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdate; +import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdateAck; +import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; +import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider; +import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler; +import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData; +import org.onap.policy.clamp.controlloop.runtime.util.rest.CommonRestController; +import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; +import org.onap.policy.common.endpoints.event.comm.TopicSink; +import org.onap.policy.common.utils.coder.YamlJsonTranslator; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.provider.PolicyModelsProvider; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; + +class SupervisionMessagesTest extends CommonRestController { + + private static final String TOSCA_SERVICE_TEMPLATE_YAML = + "src/test/resources/rest/servicetemplates/pmsh_multiple_cl_tosca.yaml"; + private static final Object lockit = new Object(); + private static final CommInfrastructure INFRA = CommInfrastructure.NOOP; + private static final String TOPIC = "my-topic"; + private static final long interval = 1000; + private static SupervisionHandler supervisionHandler; + private static CommissioningProvider commissioningProvider; + private static ControlLoopProvider clProvider; + private static PolicyModelsProvider modelsProvider; + private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator(); + + /** + * setup Db Provider Parameters. + * + * @throws PfModelException if an error occurs + */ + @BeforeAll + public static void setupDbProviderParameters() throws PfModelException { + ClRuntimeParameterGroup controlLoopParameters = CommonTestData.geParameterGroup("instantproviderdb"); + + modelsProvider = + CommonTestData.getPolicyModelsProvider(controlLoopParameters.getDatabaseProviderParameters()); + clProvider = new ControlLoopProvider(controlLoopParameters.getDatabaseProviderParameters()); + var participantStatisticsProvider = + new ParticipantStatisticsProvider(controlLoopParameters.getDatabaseProviderParameters()); + var clElementStatisticsProvider = + new ClElementStatisticsProvider(controlLoopParameters.getDatabaseProviderParameters()); + commissioningProvider = new CommissioningProvider(modelsProvider, clProvider); + var monitoringProvider = + new MonitoringProvider(participantStatisticsProvider, clElementStatisticsProvider, clProvider); + var participantProvider = new ParticipantProvider(controlLoopParameters.getDatabaseProviderParameters()); + var controlLoopUpdatePublisher = Mockito.mock(ControlLoopUpdatePublisher.class); + var controlLoopStateChangePublisher = Mockito.mock(ControlLoopStateChangePublisher.class); + var participantRegisterAckPublisher = Mockito.mock(ParticipantRegisterAckPublisher.class); + var participantDeregisterAckPublisher = Mockito.mock(ParticipantDeregisterAckPublisher.class); + var participantUpdatePublisher = Mockito.mock(ParticipantUpdatePublisher.class); + supervisionHandler = new SupervisionHandler(clProvider, participantProvider, monitoringProvider, + controlLoopUpdatePublisher, controlLoopStateChangePublisher, + participantRegisterAckPublisher, participantDeregisterAckPublisher, participantUpdatePublisher); + } + + @AfterAll + public static void closeDbProvider() throws PfModelException { + clProvider.close(); + modelsProvider.close(); + } + + @Test + void testReceiveParticipantRegister() throws Exception { + final ParticipantRegister participantRegisterMsg = new ParticipantRegister(); + participantRegisterMsg.setParticipantId(getParticipantId()); + participantRegisterMsg.setTimestamp(Instant.now()); + participantRegisterMsg.setParticipantType(getParticipantType()); + + synchronized (lockit) { + ParticipantRegisterListener participantRegisterListener = + new ParticipantRegisterListener(supervisionHandler); + ToscaServiceTemplate serviceTemplate = yamlTranslator + .fromYaml(ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), ToscaServiceTemplate.class); + + List<ToscaNodeTemplate> listOfTemplates = commissioningProvider.getControlLoopDefinitions(null, null); + commissioningProvider.createControlLoopDefinitions(serviceTemplate); + participantRegisterListener.onTopicEvent(INFRA, TOPIC, null, participantRegisterMsg); + } + } + + @Test + void testSendParticipantRegisterAck() throws Exception { + final ParticipantRegisterAck participantRegisterAckMsg = new ParticipantRegisterAck(); + participantRegisterAckMsg.setMessage("ParticipantRegisterAck message"); + participantRegisterAckMsg.setResponseTo(UUID.randomUUID()); + participantRegisterAckMsg.setResult(true); + + synchronized (lockit) { + ParticipantRegisterAckPublisher clRegisterAckPublisher = new ParticipantRegisterAckPublisher(); + clRegisterAckPublisher.active(Collections.singletonList(Mockito.mock(TopicSink.class))); + clRegisterAckPublisher.send(participantRegisterAckMsg); + } + } + + @Test + void testReceiveParticipantDeregister() throws Exception { + final ParticipantDeregister participantDeregisterMsg = new ParticipantDeregister(); + participantDeregisterMsg.setParticipantId(getParticipantId()); + participantDeregisterMsg.setTimestamp(Instant.now()); + participantDeregisterMsg.setParticipantType(getParticipantType()); + + synchronized (lockit) { + ParticipantDeregisterListener participantDeregisterListener = + new ParticipantDeregisterListener(supervisionHandler); + participantDeregisterListener.onTopicEvent(INFRA, TOPIC, null, participantDeregisterMsg); + } + } + + @Test + void testSendParticipantDeregisterAck() throws Exception { + final ParticipantDeregisterAck participantDeregisterAckMsg = new ParticipantDeregisterAck(); + participantDeregisterAckMsg.setMessage("ParticipantDeregisterAck message"); + participantDeregisterAckMsg.setResponseTo(UUID.randomUUID()); + participantDeregisterAckMsg.setResult(true); + + synchronized (lockit) { + ParticipantDeregisterAckPublisher clDeregisterAckPublisher = new ParticipantDeregisterAckPublisher(); + clDeregisterAckPublisher.active(Collections.singletonList(Mockito.mock(TopicSink.class))); + clDeregisterAckPublisher.send(participantDeregisterAckMsg); + } + } + + @Test + void testSendParticipantUpdate() throws Exception { + final ParticipantUpdate participantUpdateMsg = new ParticipantUpdate(); + participantUpdateMsg.setParticipantId(getParticipantId()); + participantUpdateMsg.setTimestamp(Instant.now()); + participantUpdateMsg.setParticipantType(getParticipantType()); + participantUpdateMsg.setTimestamp(Instant.ofEpochMilli(3000)); + participantUpdateMsg.setMessageId(UUID.randomUUID()); + + ToscaServiceTemplate toscaServiceTemplate = new ToscaServiceTemplate(); + toscaServiceTemplate.setName("serviceTemplate"); + toscaServiceTemplate.setDerivedFrom("parentServiceTemplate"); + toscaServiceTemplate.setDescription("Description of serviceTemplate"); + toscaServiceTemplate.setVersion("1.2.3"); + + ControlLoopElementDefinition clDefinition = new ControlLoopElementDefinition(); + clDefinition.setId(UUID.randomUUID()); + clDefinition.setControlLoopElementToscaServiceTemplate(toscaServiceTemplate); + Map<String, String> commonPropertiesMap = Map.of("Prop1", "PropValue"); + clDefinition.setCommonPropertiesMap(commonPropertiesMap); + + Map<UUID, ControlLoopElementDefinition> controlLoopElementDefinitionMap = + Map.of(UUID.randomUUID(), clDefinition); + + Map<ToscaConceptIdentifier, Map<UUID, ControlLoopElementDefinition>> + participantDefinitionUpdateMap = Map.of(getParticipantId(), controlLoopElementDefinitionMap); + participantUpdateMsg.setParticipantDefinitionUpdateMap(participantDefinitionUpdateMap); + + synchronized (lockit) { + ParticipantUpdatePublisher clUpdatePublisher = new ParticipantUpdatePublisher(commissioningProvider); + clUpdatePublisher.active(Collections.singletonList(Mockito.mock(TopicSink.class))); + clUpdatePublisher.send(participantUpdateMsg); + } + } + + @Test + void testReceiveParticipantUpdateAckMessage() throws Exception { + final ParticipantUpdateAck participantUpdateAckMsg = new ParticipantUpdateAck(); + participantUpdateAckMsg.setMessage("ParticipantUpdateAck message"); + participantUpdateAckMsg.setResponseTo(UUID.randomUUID()); + participantUpdateAckMsg.setResult(true); + + synchronized (lockit) { + ParticipantUpdateAckListener participantUpdateAckListener = + new ParticipantUpdateAckListener(supervisionHandler); + participantUpdateAckListener.onTopicEvent(INFRA, TOPIC, null, participantUpdateAckMsg); + } + } + + private ToscaConceptIdentifier getParticipantId() { + return new ToscaConceptIdentifier("org.onap.PM_Policy", "1.0.0"); + } + + private ToscaConceptIdentifier getParticipantType() { + return new ToscaConceptIdentifier("org.onap.policy.controlloop.PolicyControlLoopParticipant", "2.3.1"); + } +} diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/util/CommonTestData.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/util/CommonTestData.java index 464c14354..300c662ce 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/util/CommonTestData.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/util/CommonTestData.java @@ -38,19 +38,18 @@ import org.onap.policy.models.provider.PolicyModelsProviderParameters; * */ public class CommonTestData { - private static final Coder coder = new StandardCoder(); + private static final Coder CODER = new StandardCoder(); /** * Gets the standard Control Loop parameters. * - * @param port port to be inserted into the parameters * @param dbName the database name * @return the standard Control Loop parameters * @throws ControlLoopRuntimeException on errors reading the control loop parameters */ - public static ClRuntimeParameterGroup geParameterGroup(final int port, final String dbName) { + public static ClRuntimeParameterGroup geParameterGroup(final String dbName) { try { - return coder.decode(getParameterGroupAsString(port, dbName), ClRuntimeParameterGroup.class); + return CODER.convert(getParameterGroupAsString(dbName), ClRuntimeParameterGroup.class); } catch (CoderException e) { throw new ControlLoopRuntimeException(Status.NOT_ACCEPTABLE, "cannot read Control Loop parameters", e); @@ -60,13 +59,12 @@ public class CommonTestData { /** * Gets the standard Control Loop parameters, as a String. * - * @param port port to be inserted into the parameters * @param dbName the database name * @return the standard Control Loop parameters as string */ - public static String getParameterGroupAsString(final int port, final String dbName) { - return ResourceUtils.getResourceAsString("src/test/resources/parameters/InstantiationConfigParametersStd.json") - .replace("${port}", String.valueOf(port)).replace("${dbName}", "jdbc:h2:mem:" + dbName); + public static String getParameterGroupAsString(final String dbName) { + return ResourceUtils.getResourceAsString("src/test/resources/parameters/TestParameters.json") + .replace("${dbName}", "jdbc:h2:mem:" + dbName); } /** diff --git a/runtime-controlloop/src/test/resources/application_test.properties b/runtime-controlloop/src/test/resources/application_test.properties index fc24ea290..ad2a4b12c 100644 --- a/runtime-controlloop/src/test/resources/application_test.properties +++ b/runtime-controlloop/src/test/resources/application_test.properties @@ -6,4 +6,25 @@ server.port=6969 server.servlet.context-path=/onap/controlloop server.error.path=/error -runtime.file=src/test/resources/parameters/TestParameters.json +runtime.supervisionScannerIntervalSec=1000 +runtime.participantClUpdateIntervalSec=1000 +runtime.participantClStateChangeIntervalSec=1000 +runtime.participantParameters.heartBeatMs=120000 +runtime.participantParameters.updateParameters.maxRetryCount=1 +runtime.participantParameters.updateParameters.maxWaitMs=30000 +runtime.participantParameters.stateChangeParameters.maxRetryCount=1 +runtime.participantParameters.stateChangeParameters.maxWaitMs=30000 +runtime.databaseProviderParameters.name=PolicyProviderParameterGroup +runtime.databaseProviderParameters.implementation=org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl +runtime.databaseProviderParameters.databaseDriver=org.h2.Driver +runtime.databaseProviderParameters.databaseUrl=jdbc:h2:mem:testdb +runtime.databaseProviderParameters.databaseUser=policy +runtime.databaseProviderParameters.databasePassword=P01icY +runtime.databaseProviderParameters.persistenceUnit=ToscaConceptTest +runtime.topicParameterGroup.topicSources[0].topic=POLICY-CLRUNTIME-PARTICIPANT +runtime.topicParameterGroup.topicSources[0].servers[0]=localhost +runtime.topicParameterGroup.topicSources[0].topicCommInfrastructure=dmaap +runtime.topicParameterGroup.topicSources[0].fetchTimeout=15000 +runtime.topicParameterGroup.topicSinks[0].topic=POLICY-CLRUNTIME-PARTICIPANT +runtime.topicParameterGroup.topicSinks[0].servers[0]=localhost +runtime.topicParameterGroup.topicSinks[0].topicCommInfrastructure=dmaap diff --git a/runtime-controlloop/src/test/resources/parameters/CommissioningConfig.json b/runtime-controlloop/src/test/resources/parameters/CommissioningConfig.json deleted file mode 100644 index 762e3f793..000000000 --- a/runtime-controlloop/src/test/resources/parameters/CommissioningConfig.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "CommissioningGroup", - "supervisionScannerIntervalSec" : 1000, - "participantStateChangeIntervalSec" : 1000, - "participantClUpdateIntervalSec" : 1000, - "participantClStateChangeIntervalSec" : 1000, - "restServerParameters": { - "host": "127.0.0.1", - "port": 6969, - "userName": "admin", - "password": "password", - "https": false, - "aaf": false - }, - "databaseProviderParameters": { - "name": "CommissioningProviderParameterGroup", - "implementation": "org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl", - "databaseDriver": "org.h2.Driver", - "databaseUrl": "jdbc:h2:mem:testdb", - "databaseUser": "controlloop", - "databasePassword": "C0ntr0lL00p", - "persistenceUnit": "ToscaConceptTest" - } -} diff --git a/runtime-controlloop/src/test/resources/parameters/EmptyParameters.json b/runtime-controlloop/src/test/resources/parameters/EmptyParameters.json deleted file mode 100644 index e69de29bb..000000000 --- a/runtime-controlloop/src/test/resources/parameters/EmptyParameters.json +++ /dev/null diff --git a/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParametersStd.json b/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParametersStd.json deleted file mode 100644 index 06f4370e8..000000000 --- a/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParametersStd.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "name": "ControlLoopRuntimeGroup", - "supervisionScannerIntervalSec": 1000, - "participantStateChangeIntervalSec": 1000, - "participantClUpdateIntervalSec": 1000, - "participantClStateChangeIntervalSec": 1000, - "restServerParameters": { - "host": "0.0.0.0", - "port": ${port}, - "userName": "healthcheck", - "password": "zb!XztG34", - "https": false, - "aaf": false - }, - "participantParameters": { - "heartBeatMs": 120000, - "updateParameters": { - "maxRetryCount": 1, - "maxWaitMs": 30000 - }, - "stateChangeParameters": { - "maxRetryCount": 1, - "maxWaitMs": 30000 - } - }, - "databaseProviderParameters": { - "name": "PolicyProviderParameterGroup", - "implementation": "org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl", - "databaseDriver": "org.h2.Driver", - "databaseUrl": "${dbName}", - "databaseUser": "policy", - "databasePassword": "P01icY", - "persistenceUnit": "InstantiationTests" - }, - "topicParameterGroup": { - "topicSources": [ - { - "topic": "POLICY-CLRUNTIME-PARTICIPANT", - "servers": [ - "localhost" - ], - "topicCommInfrastructure": "dmaap", - "fetchTimeout": 15000 - } - ], - "topicSinks": [ - { - "topic": "POLICY-CLRUNTIME-PARTICIPANT", - "servers": [ - "localhost" - ], - "topicCommInfrastructure": "dmaap" - }, - { - "topic": "POLICY-NOTIFICATION", - "servers": [ - "localhost" - ], - "topicCommInfrastructure": "dmaap" - } - ] - } -} diff --git a/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParameters_InvalidName.json b/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParameters_InvalidName.json deleted file mode 100644 index 944bc770d..000000000 --- a/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParameters_InvalidName.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": " ", - "supervisionScannerIntervalSec": 1000, - "participantStateChangeIntervalSec": 1000, - "participantClUpdateIntervalSec": 1000, - "participantClStateChangeIntervalSec": 1000, - "restServerParameters": { - "host": "127.0.0.1", - "port": 6969, - "userName": "admin", - "password": "password", - "https": false, - "aaf": false - }, - "pdpParameters": { - "heartBeatMs": 1, - "updateParameters": { - "maxRetryCount": 1, - "maxWaitMs": 1 - }, - "stateChangeParameters": { - "maxRetryCount": 1, - "maxWaitMs": 1 - } - }, - "databaseProviderParameters": { - "name": "PolicyProviderParameterGroup", - "implementation": "org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl", - "databaseDriver": "org.h2.Driver", - "databaseUrl": "jdbc:h2:mem:testdb", - "databaseUser": "policy", - "databasePassword": "P01icY", - "persistenceUnit": "PdpGroupTest" - } -} diff --git a/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParameters_sim.json b/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParameters_sim.json deleted file mode 100644 index 47cb74838..000000000 --- a/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParameters_sim.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "Instantiation", - "supervisionScannerIntervalSec": 1000, - "participantStateChangeIntervalSec": 1000, - "participantClUpdateIntervalSec": 1000, - "participantClStateChangeIntervalSec": 1000, - "restServerParameters": { - "host": "127.0.0.1", - "port": 6969, - "userName": "admin", - "password": "password", - "https": false, - "aaf": false - }, - "pdpParameters": { - "heartBeatMs": 10, - "updateParameters": { - "maxRetryCount": 1, - "maxWaitMs": 30000 - }, - "stateChangeParameters": { - "maxRetryCount": 1, - "maxWaitMs": 30000 - } - }, - "databaseProviderParameters": { - "name": "PolicyProviderParameterGroup", - "implementation": "org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl", - "databaseDriver": "org.mariadb.jdbc.Driver", - "databaseUrl": "jdbc:mariadb://localhost:3306/policyadmin", - "databaseUser": "policy", - "databasePassword": "UDAxaWNZ", - "persistenceUnit": "PolicyMariaDb" - }, - "topicParameterGroup": { - "topicSources": [ - { - "topic": "INSTANTIATION", - "servers": [ - "localhost:6845" - ], - "topicCommInfrastructure": "dmaap" - } - ], - "topicSinks": [ - { - "topic": "INSTANTIATION", - "servers": [ - "localhost:6845" - ], - "topicCommInfrastructure": "dmaap" - } - ] - } -} diff --git a/runtime-controlloop/src/test/resources/parameters/InvalidParameters.json b/runtime-controlloop/src/test/resources/parameters/InvalidParameters.json deleted file mode 100644 index 976ec2937..000000000 --- a/runtime-controlloop/src/test/resources/parameters/InvalidParameters.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "" -} diff --git a/runtime-controlloop/src/test/resources/parameters/MinimumParametersH2.json b/runtime-controlloop/src/test/resources/parameters/MinimumParametersH2.json deleted file mode 100644 index 2be642943..000000000 --- a/runtime-controlloop/src/test/resources/parameters/MinimumParametersH2.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "PapGroup", - "supervisionScannerIntervalSec": 1000, - "participantStateChangeIntervalSec": 1000, - "participantClUpdateIntervalSec": 1000, - "participantClStateChangeIntervalSec": 1000, - "restServerParameters": { - "host": "0.0.0.0", - "port": 6969, - "userName": "healthcheck", - "password": "zb!XztG34" - }, - "pdpParameters": { - "heartBeatMs": 1, - "updateParameters": { - "maxRetryCount": 1, - "maxWaitMs": 1 - }, - "stateChangeParameters": { - "maxRetryCount": 1, - "maxWaitMs": 1 - } - }, - "databaseProviderParameters": { - "name": "PolicyProviderParameterGroup", - "implementation": "org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl", - "databaseDriver": "org.h2.Driver", - "databaseUrl": "jdbc:h2:mem:testdb", - "databaseUser": "policy", - "databasePassword": "P01icY", - "persistenceUnit": "PdpGroupTest" - }, - "topicParameterGroup": { - "topicSources": [ - { - "topic": "POLICY-PDP-PAP", - "servers": [ - "message-router" - ], - "topicCommInfrastructure": "dmaap" - } - ], - "topicSinks": [ - { - "topic": "POLICY-PDP-PAP", - "servers": [ - "message-router" - ], - "topicCommInfrastructure": "dmaap" - } - ] - } -} diff --git a/runtime-controlloop/src/test/resources/parameters/NoParameters.json b/runtime-controlloop/src/test/resources/parameters/NoParameters.json deleted file mode 100644 index 2c63c0851..000000000 --- a/runtime-controlloop/src/test/resources/parameters/NoParameters.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/runtime-controlloop/src/test/resources/parameters/TestParameters.json b/runtime-controlloop/src/test/resources/parameters/TestParameters.json index 680e070f2..99fc43d21 100644 --- a/runtime-controlloop/src/test/resources/parameters/TestParameters.json +++ b/runtime-controlloop/src/test/resources/parameters/TestParameters.json @@ -1,17 +1,8 @@ { "name": "ControlLoopRuntimeGroup", "supervisionScannerIntervalSec": 1000, - "participantStateChangeIntervalSec": 1000, "participantClUpdateIntervalSec": 1000, "participantClStateChangeIntervalSec": 1000, - "restServerParameters": { - "host": "0.0.0.0", - "port": 6969, - "userName": "healthcheck", - "password": "zb!XztG34", - "https": false, - "aaf": false - }, "participantParameters": { "heartBeatMs": 120000, "updateParameters": { @@ -27,10 +18,10 @@ "name": "PolicyProviderParameterGroup", "implementation": "org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl", "databaseDriver": "org.h2.Driver", - "databaseUrl": "jdbc:h2:mem:testdb", + "databaseUrl": "${dbName}", "databaseUser": "policy", "databasePassword": "P01icY", - "persistenceUnit": "ToscaConceptTest" + "persistenceUnit": "InstantiationTests" }, "topicParameterGroup": { "topicSources": [ diff --git a/runtime-controlloop/src/test/resources/parameters/Unreadable.json b/runtime-controlloop/src/test/resources/parameters/Unreadable.json deleted file mode 100644 index 0ea56eb5d..000000000 --- a/runtime-controlloop/src/test/resources/parameters/Unreadable.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "ControlLoopRuntimeGroup", - "supervisionScannerIntervalSec": 1000, - "participantStateChangeIntervalSec": 1000, - "participantClUpdateIntervalSec": 1000, - "participantClStateChangeIntervalSec": 1000, - "restServerParameters": { - "host": "0.0.0.0", - "port": 6969, - "userName": "healthcheck", - "password": "zb!XztG34", - "https": false, - "aaf": false - }, - "participantParameters": { - "heartBeatMs": 120000, - "updateParameters": { - "maxRetryCount": 1, - "maxWaitMs": 30000 - }, - "stateChangeParameters": { - "maxRetryCount": 1, - "maxWaitMs": 30000 - } - }, - "databaseProviderParameters": { - "name": "PolicyProviderParameterGroup", - "implementation": "org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl", - "databaseDriver": "org.h2.Driver", - "databaseUrl": "jdbc:h2:mem:testdb", - "databaseUser": "policy", - "databasePassword": "P01icY", - "persistenceUnit": "ToscaConceptTest" - }, - "topicParameterGroup": { - "topicSources": [ - { - "topic": "POLICY-CLRUNTIME-PARTICIPANT", - "servers": [ - "localhost" - ], - "topicCommInfrastructure": "dmaap", - "fetchTimeout": 15000 - } - ], - "topicSinks": [ - { - "topic": "POLICY-CLRUNTIME-PARTICIPANT", - "servers": [ - "localhost" - ], - "topicCommInfrastructure": "dmaap" - }, - { - "topic": "POLICY-NOTIFICATION", - "servers": [ - "localhost" - ], - "topicCommInfrastructure": "dmaap" - } - ] - } |