diff options
Diffstat (limited to 'runtime-controlloop/src/main/java')
26 files changed, 1087 insertions, 372 deletions
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..891d42072 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,10 +23,10 @@ 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; @@ -42,6 +42,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; @@ -181,6 +182,171 @@ 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,6 +361,30 @@ 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 Map<String, Object> 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()); + + return template; + } + + /** * Get the requested json schema. * * @param section section of the tosca service template to get schema for @@ -203,9 +393,9 @@ public class CommissioningProvider { * @throws JsonProcessingException on errors generating the schema */ public String getToscaServiceTemplateSchema(String section) throws PfModelException, JsonProcessingException { - ObjectMapper mapper = new ObjectMapper(); + var mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); - SchemaFactoryWrapper visitor = new SchemaFactoryWrapper(); + var visitor = new SchemaFactoryWrapper(); switch (section) { case "data_types": @@ -227,15 +417,14 @@ public class CommissioningProvider { mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaTopologyTemplate.class), visitor); break; case "node_templates": - mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaNodeTemplate.class), visitor); + mapper.acceptJsonFormatVisitor(mapper.getTypeFactory() + .constructCollectionType(List.class, ToscaNodeTemplate.class), visitor); break; default: mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaServiceTemplate.class), visitor); } - JsonSchema jsonSchema = visitor.finalSchema(); - String response = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema); - - return response; + var jsonSchema = visitor.finalSchema(); + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema); } } 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..8fe3c0c88 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 @@ -23,8 +23,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; @@ -64,6 +62,8 @@ 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; /** @@ -90,7 +90,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( @@ -160,7 +160,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( @@ -235,7 +235,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( @@ -304,7 +304,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( @@ -347,15 +347,24 @@ public class CommissioningController extends AbstractRestController { required = false) String version) { try { - return ResponseEntity.ok().body(provider.getToscaServiceTemplate(name, version)); + var mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + var response = mapper.writerWithDefaultPrettyPrinter() + .writeValueAsString(provider.getToscaServiceTemplateReduced(name, version)); + + return ResponseEntity.ok().body(response); } 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); + } catch (JsonProcessingException e) { + LOGGER.warn("Get of tosca service template failed", e); + var resp = new CommissioningResponse(); + resp.setErrorDetails(e.getMessage()); + return ResponseEntity.status(Status.BAD_REQUEST.getStatusCode()).body(resp); } - } /** @@ -372,7 +381,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( @@ -427,6 +436,79 @@ public class CommissioningController extends AbstractRestController { } /** + * 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 + */ + // @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<?> 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 = true) @RequestParam( + value = "version", + required = false) String version) { + try { + return ResponseEntity.ok().body(provider.getNodeTemplatesWithCommonOrInstanceProperties( + common, name, version)); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Get of common or instance properties failed", e); + var resp = new CommissioningResponse(); + resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + } + } + + /** * Queries the elements of a specific control loop. * * @param requestId request ID used in ONAP logging @@ -441,7 +523,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( 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..5a320e8dc 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 @@ -59,6 +59,8 @@ 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; @@ -86,7 +88,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( @@ -154,9 +156,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( @@ -220,9 +220,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( @@ -290,9 +288,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( @@ -362,9 +358,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( 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..7ac95003e 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 @@ -52,6 +52,7 @@ import org.springframework.web.bind.annotation.RestController; 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; /** @@ -80,9 +81,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( @@ -168,9 +167,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( @@ -235,9 +232,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( @@ -306,9 +301,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( 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..293b5d5da --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionAspect.java @@ -0,0 +1,71 @@ +/*- + * ============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.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)); + } + } + + @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..dadfe0de2 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 @@ -31,10 +31,16 @@ import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant; import org.onap.policy.clamp.controlloop.models.controlloop.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 +68,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 +111,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 +129,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 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..b360f6703 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,21 @@ 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.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import lombok.Getter; +import lombok.Setter; 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.persistence.provider.ControlLoopProvider; 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.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 +43,83 @@ 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; + @Getter + @Setter + static class HandleCounter { + private int maxRetryCount; + private long maxWaitMs; + private Map<ToscaConceptIdentifier, Integer> mapCounter = new HashMap<>(); + private Set<ToscaConceptIdentifier> mapFault = new HashSet<>(); + + public void clear(ToscaConceptIdentifier id) { + mapCounter.put(id, 0); + mapFault.remove(id); + } + + public void setFault(ToscaConceptIdentifier id) { + mapCounter.put(id, 0); + mapFault.add(id); + } + + public boolean count(ToscaConceptIdentifier id) { + int counter = mapCounter.getOrDefault(id, 0) + 1; + if (counter <= maxRetryCount) { + mapCounter.put(id, counter); + return true; + } + return false; + } + + public boolean isFault(ToscaConceptIdentifier id) { + return mapFault.contains(id); + } + + public int getCounter(ToscaConceptIdentifier id) { + return mapCounter.getOrDefault(id, 0); + } + } + + private HandleCounter stateChange = new HandleCounter(); + + private final ControlLoopProvider controlLoopProvider; + private final ControlLoopStateChangePublisher controlLoopStateChangePublisher; + private final ControlLoopUpdatePublisher controlLoopUpdatePublisher; /** * 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 ControlLoopStateChange Publisher + * @param clRuntimeParameterGroup the parameters for the control loop runtime */ public SupervisionScanner(final ControlLoopProvider controlLoopProvider, - ClRuntimeParameterGroup clRuntimeParameterGroup) { + final ControlLoopStateChangePublisher controlLoopStateChangePublisher, + ControlLoopUpdatePublisher controlLoopUpdatePublisher, + final ClRuntimeParameterGroup clRuntimeParameterGroup) { this.controlLoopProvider = controlLoopProvider; + this.controlLoopStateChangePublisher = controlLoopStateChangePublisher; + this.controlLoopUpdatePublisher = controlLoopUpdatePublisher; - // Kick off the timer - timerPool = makeTimerPool(); - timerPool.scheduleAtFixedRate(this, 0, clRuntimeParameterGroup.getSupervisionScannerIntervalSec(), - TimeUnit.SECONDS); + stateChange.setMaxRetryCount( + clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount()); + stateChange.setMaxWaitMs( + clRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxWaitMs()); } - @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 . . ."); 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 +128,65 @@ public class SupervisionScanner implements Runnable, Closeable { LOGGER.debug("Control loop scan complete . . ."); } - @Override - public void close() { - timerPool.shutdown(); - } - - private void scanControlLoop(final ControlLoop controlLoop) throws PfModelException { + 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) { + stateChange.clear(controlLoop.getKey().asIdentifier()); + } + + private void handleCounter(ControlLoop controlLoop) { + ToscaConceptIdentifier id = controlLoop.getKey().asIdentifier(); + if (stateChange.isFault(id)) { + LOGGER.debug("report ControlLoop fault"); + return; + } + + if (stateChange.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"); + stateChange.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/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); + } +} |