diff options
Diffstat (limited to 'src/onapsdk/clamp')
-rw-r--r-- | src/onapsdk/clamp/__init__.py | 14 | ||||
-rw-r--r-- | src/onapsdk/clamp/clamp_element.py | 79 | ||||
-rw-r--r-- | src/onapsdk/clamp/loop_instance.py | 349 | ||||
-rw-r--r-- | src/onapsdk/clamp/schema_details.json | 138 | ||||
-rw-r--r-- | src/onapsdk/clamp/templates/clamp_MinMax_config.json.j2 | 94 | ||||
-rw-r--r-- | src/onapsdk/clamp/templates/clamp_add_drools_policy.json.j2 | 325 | ||||
-rw-r--r-- | src/onapsdk/clamp/templates/clamp_add_frequency.json.j2 | 102 | ||||
-rw-r--r-- | src/onapsdk/clamp/templates/clamp_add_tca_config.json.j2 | 30 |
8 files changed, 1131 insertions, 0 deletions
diff --git a/src/onapsdk/clamp/__init__.py b/src/onapsdk/clamp/__init__.py new file mode 100644 index 0000000..621adc9 --- /dev/null +++ b/src/onapsdk/clamp/__init__.py @@ -0,0 +1,14 @@ +"""ONAP SDK CLAMP package.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# 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. diff --git a/src/onapsdk/clamp/clamp_element.py b/src/onapsdk/clamp/clamp_element.py new file mode 100644 index 0000000..843db42 --- /dev/null +++ b/src/onapsdk/clamp/clamp_element.py @@ -0,0 +1,79 @@ +"""Clamp module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# 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. +from onapsdk.configuration import settings +from onapsdk.onap_service import OnapService as Onap +from onapsdk.sdc.service import Service +from onapsdk.exceptions import ResourceNotFound +from onapsdk.utils.headers_creator import headers_clamp_creator + + +class Clamp(Onap): + """Mother Class of all CLAMP elements.""" + + #class variable + _base_url = settings.CLAMP_URL + name: str = "CLAMP" + headers = headers_clamp_creator(Onap.headers) + + @classmethod + def base_url(cls) -> str: + """Give back the base url of Clamp.""" + return f"{cls._base_url}/restservices/clds/v2" + + @classmethod + def check_loop_template(cls, service: Service) -> str: + """ + Return loop template name if exists. + + Args: + service (Service): the distributed sdc service with tca blueprint artifact + + Raises: + ResourceNotFound: Template not found. + + Returns: + if required template exists in CLAMP or not + + """ + url = f"{cls.base_url()}/templates/" + for template in cls.send_message_json('GET', + 'Get Loop Templates', + url): + if template["modelService"]["serviceDetails"]["name"] == service.name: + return template["name"] + raise ResourceNotFound("Template not found.") + + @classmethod + def check_policies(cls, policy_name: str, req_policies: int = 30) -> bool: + """ + Ensure that a policy is stored in CLAMP. + + Args: + policy_name (str): policy acronym + req_policies (int): number of required policies in CLAMP + + Returns: + if required policy exists in CLAMP or not + + """ + url = f"{cls.base_url()}/policyToscaModels/" + policies = cls.send_message_json('GET', + 'Get stocked policies', + url) + exist_policy = False + for policy in policies: + if policy["policyAcronym"] == policy_name: + exist_policy = True + return (len(policies) >= req_policies) and exist_policy diff --git a/src/onapsdk/clamp/loop_instance.py b/src/onapsdk/clamp/loop_instance.py new file mode 100644 index 0000000..a72f9d1 --- /dev/null +++ b/src/onapsdk/clamp/loop_instance.py @@ -0,0 +1,349 @@ +"""Control Loop module.""" +# Copyright 2022 Orange, Deutsche Telekom AG +# +# 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. +import json +from pathlib import Path +from jsonschema import validate, ValidationError + +from onapsdk.clamp.clamp_element import Clamp +from onapsdk.utils.jinja import jinja_env +from onapsdk.exceptions import ParameterError + +CLAMP_UPDDATE_REFRESH_TIMER = 60 + +class LoopInstance(Clamp): + """Control Loop instantiation class.""" + + # class variable + _loop_schema = None + operational_policies = "" + + def __init__(self, template: str, name: str, details: dict) -> None: + """ + Initialize loop instance object. + + Args: + template (str): template from which we build the loop + name (str) : loop creation name + details (dict) : dictionnary containing all loop details + + """ + super().__init__() + self.template = template + self.name = "LOOP_" + name + self._details = details + + @property + def details(self) -> dict: + """Return and lazy load the details.""" + if not self._details: + self._update_loop_details() + return self._details + + @details.setter + def details(self, details: dict) -> None: + """Set value for details.""" + self._details = details + + def _update_loop_details(self) -> dict: + """ + Update loop details. + + Returns: + the dictionnary of loop details + + """ + url = f"{self.base_url()}/loop/{self.name}" + loop_details = self.send_message_json('GET', + 'Get loop details', + url) + return loop_details + + def refresh_status(self) -> None: + """Reshresh loop status.""" + url = f"{self.base_url()}/loop/getstatus/{self.name}" + loop_details = self.send_message_json('GET', + 'Get loop status', + url) + + self.details = loop_details + + @property + def loop_schema(self) -> dict: + """ + Return and lazy load the details schema. + + Returns: + schema to be respected to accede to loop details + + """ + if not self._loop_schema: + schema_file = Path.cwd() / 'src' / 'onapsdk' / 'clamp' / 'schema_details.json' + with open(schema_file, "rb") as plan: + self._loop_schema = json.load(plan) + return self._loop_schema + + def validate_details(self) -> bool: + """ + Validate Loop Instance details. + + Returns: + schema validation status (True, False) + + """ + try: + validate(self.details, self.loop_schema) + except ValidationError as error: + self._logger.error(error) + self._logger.error("---------") + self._logger.error(error.absolute_path) + self._logger.error("---------") + self._logger.error(error.absolute_schema_path) + return False + return True + + def create(self) -> None: + """Create instance and load loop details.""" + url = f"{self.base_url()}/loop/create/{self.name}?templateName={self.template}" + instance_details = self.send_message_json('POST', + 'Create Loop Instance', + url) + self.details = instance_details + + def add_operational_policy(self, policy_type: str, policy_version: str) -> None: + """ + Add operational policy to the loop instance. + + Args: + policy_type (str): the full policy model type + policy_version (str): policy version + + Raises: + ParameterError : Corrupt response or a key in a dictionary not found. + It will also be raised when the response contains more operational + policies than there are currently. + + """ + url = (f"{self.base_url()}/loop/addOperationaPolicy/{self.name}/" + f"policyModel/{policy_type}/{policy_version}") + add_response = self.send_message_json('PUT', + 'Create Operational Policy', + url) + + key = "operationalPolicies" + + try: + if self.details[key] is None: + self.details[key] = [] + + response_policies = add_response[key] + current_policies = self.details[key] + except KeyError as exc: + msg = 'Corrupt response, current loop details. Key not found.' + raise ParameterError(msg) from exc + + if len(response_policies) > len(current_policies): + self.details = add_response + else: + raise ParameterError("Couldn't add the operational policy.") + + def remove_operational_policy(self, policy_type: str, policy_version: str) -> None: + """ + Remove operational policy from the loop instance. + + Args: + policy_type (str): the full policy model type + policy_version (str): policy version + + """ + url = (f"{self.base_url()}/loop/removeOperationaPolicy/" + f"{self.name}/policyModel/{policy_type}/{policy_version}") + self.details = self.send_message_json('PUT', + 'Remove Operational Policy', + url) + + def update_microservice_policy(self) -> None: + """ + Update microservice policy configuration. + + Update microservice policy configuration using payload data. + + """ + url = f"{self.base_url()}/loop/updateMicroservicePolicy/{self.name}" + template = jinja_env().get_template("clamp_add_tca_config.json.j2") + microservice_name = self.details["globalPropertiesJson"]["dcaeDeployParameters"]\ + ["uniqueBlueprintParameters"]["policy_id"] + data = template.render(name=microservice_name, + LOOP_name=self.name) + + self.send_message('POST', + 'ADD TCA config', + url, + data=data) + + def extract_operational_policy_name(self, policy_type: str) -> str: + """ + Return operational policy name for a closed loop and a given policy. + + Args: + policy_type (str): the policy acronym. + + Raises: + ParameterError : Couldn't load the operational policy name. + + Returns: + Operational policy name in the loop details after adding a policy. + + """ + for policy in filter(lambda x: x["policyModel"]["policyAcronym"] == policy_type, + self.details["operationalPolicies"]): + return policy["name"] + + raise ParameterError("Couldn't load the operational policy name.") + + def add_drools_conf(self) -> dict: + """Add drools configuration.""" + self.validate_details() + vfmodule_dicts = self.details["modelService"]["resourceDetails"]["VFModule"] + entity_ids = {} + #Get the vf module details + for vfmodule in vfmodule_dicts.values(): + entity_ids["resourceID"] = vfmodule["vfModuleModelName"] + entity_ids["modelInvariantId"] = vfmodule["vfModuleModelInvariantUUID"] + entity_ids["modelVersionId"] = vfmodule["vfModuleModelUUID"] + entity_ids["modelName"] = vfmodule["vfModuleModelName"] + entity_ids["modelVersion"] = vfmodule["vfModuleModelVersion"] + entity_ids["modelCustomizationId"] = vfmodule["vfModuleModelCustomizationUUID"] + template = jinja_env().get_template("clamp_add_drools_policy.json.j2") + data = template.render(name=self.extract_operational_policy_name("Drools"), + resourceID=entity_ids["resourceID"], + modelInvariantId=entity_ids["modelInvariantId"], + modelVersionId=entity_ids["modelVersionId"], + modelName=entity_ids["modelName"], + modelVersion=entity_ids["modelVersion"], + modelCustomizationId=entity_ids["modelCustomizationId"], + LOOP_name=self.name) + return data + + def add_minmax_config(self) -> None: + """Add MinMax operational policy config.""" + #must configure start/end time and min/max instances in json file + template = jinja_env().get_template("clamp_MinMax_config.json.j2") + return template.render(name=self.extract_operational_policy_name("MinMax")) + + def add_frequency_limiter(self, limit: int = 1) -> None: + """Add frequency limiter config.""" + template = jinja_env().get_template("clamp_add_frequency.json.j2") + return template.render(name=self.extract_operational_policy_name("FrequencyLimiter"), + LOOP_name=self.name, + limit=limit) + + def add_op_policy_config(self, func, **kwargs) -> None: + """ + Add operational policy configuration. + + Add operation policy configuration using payload data. + + Args: + func (function): policy configuration function in (add_drools_conf, + add_minmax_config, + add_frequency_limiter) + + """ + data = func(**kwargs) + if not data: + raise ParameterError("Payload data from configuration is None.") + if self.operational_policies: + self.operational_policies = self.operational_policies[:-1] + "," + data = data[1:] + self.operational_policies += data + url = f"{self.base_url()}/loop/updateOperationalPolicies/{self.name}" + self.send_message('POST', + 'ADD operational policy config', + url, + data=self.operational_policies) + + self._logger.info(("Files for op policy config %s have been uploaded to loop's" + "Op policy"), self.name) + + def submit(self): + """Submit policies to policy engine.""" + state = self.details["components"]["POLICY"]["componentState"]["stateName"] + return state == "SENT_AND_DEPLOYED" + + def stop(self): + """Undeploy Policies from policy engine.""" + state = self.details["components"]["POLICY"]["componentState"]["stateName"] + return state == "SENT" + + def restart(self): + """Redeploy policies to policy engine.""" + state = self.details["components"]["POLICY"]["componentState"]["stateName"] + return state == "SENT_AND_DEPLOYED" + + def act_on_loop_policy(self, func) -> bool: + """ + Act on loop's policy. + + Args: + func (function): function of action to be done (submit, stop, restart) + + Returns: + action state : failed or done + + """ + url = f"{self.base_url()}/loop/{func.__name__}/{self.name}" + self.send_message('PUT', + f'{func.__name__} policy', + url) + self.refresh_status() + self.validate_details() + return func() + + def deploy_microservice_to_dcae(self) -> bool: + """ + Execute the deploy operation on the loop instance. + + Returns: + loop deploy on DCAE status (True, False) + + """ + url = f"{self.base_url()}/loop/deploy/{self.name}" + self.send_message('PUT', + 'Deploy microservice to DCAE', + url) + self.validate_details() + state = self.details["components"]["DCAE"]["componentState"]["stateName"] + failure = "MICROSERVICE_INSTALLATION_FAILED" + success = "MICROSERVICE_INSTALLED_SUCCESSFULLY" + while state not in (success, failure): + self.refresh_status() + self.validate_details() + state = self.details["components"]["DCAE"]["componentState"]["stateName"] + return state == success + + def undeploy_microservice_from_dcae(self) -> None: + """Stop the deploy operation.""" + url = f"{self.base_url()}/loop/undeploy/{self.name}" + self.send_message('PUT', + 'Undeploy microservice from DCAE', + url) + + def delete(self) -> None: + """Delete the loop instance.""" + self._logger.debug("Delete %s loop instance", self.name) + url = "{}/loop/delete/{}".format(self.base_url(), self.name) + self.send_message('PUT', + 'Delete loop instance', + url) diff --git a/src/onapsdk/clamp/schema_details.json b/src/onapsdk/clamp/schema_details.json new file mode 100644 index 0000000..3caea6c --- /dev/null +++ b/src/onapsdk/clamp/schema_details.json @@ -0,0 +1,138 @@ +{ + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "components": { + "type": "object", + "properties": { + "POLICY": { + "type": "object", + "properties": { + "componentState": { + "type": "object", + "properties": { + "stateName": { + "type": "string" + } + }, + "required": [ + "stateName" + ] + } + }, + "required": [ + "componentState" + ] + }, + "DCAE": { + "type": "object", + "properties": { + "componentState": { + "type": "object", + "properties": { + "stateName": { + "type": "string" + } + }, + "required": [ + "stateName" + ] + } + }, + "required": [ + "componentState" + ] + } + }, + "required": [ + "POLICY", + "DCAE" + ] + }, + "modelService": { + "type": "object", + "properties": { + "resourceDetails": { + "type": "object", + "properties": { + "VFModule": { + "type": "object", + "properties": { + "resourceID": { + "type": "object", + "properties": { + "vfModuleModelName": { + "type": "string" + }, + "vfModuleModelInvariantUUID": { + "type": "string" + }, + "vfModuleModelUUID": { + "type": "string" + }, + "vfModuleModelVersion": { + "type": "string" + }, + "vfModuleModelCustomizationUUID": { + "type": "string" + } + }, + "required": [ + "vfModuleModelName", + "vfModuleModelInvariantUUID", + "vfModuleModelUUID", + "vfModuleModelVersion", + "vfModuleModelCustomizationUUID" + ] + } + } + } + }, + "required": [ + "VFModule" + ] + } + }, + "required": [ + "resourceDetails" + ] + }, + "operationalPolicies": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + }, + "microServicePolicies": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + }, + "required": [ + "name", + "components", + "modelService", + "operationalPolicies", + "microServicePolicies" + ] + }
\ No newline at end of file diff --git a/src/onapsdk/clamp/templates/clamp_MinMax_config.json.j2 b/src/onapsdk/clamp/templates/clamp_MinMax_config.json.j2 new file mode 100644 index 0000000..2402ace --- /dev/null +++ b/src/onapsdk/clamp/templates/clamp_MinMax_config.json.j2 @@ -0,0 +1,94 @@ +[ + { + "name": "{{ name }}", + "jsonRepresentation": { + "title": "onap.policies.controlloop.guard.common.MinMax", + "type": "object", + "description": "Supports Min/Max number of entity for scaling operations. Although min and max fields are marked as not\nrequired, you need to have at least one or the other.\n", + "required": [ + "actor", + "operation", + "target" + ], + "properties": { + "id": { + "type": "string", + "description": "The Control Loop id this applies to." + }, + "actor": { + "type": "string", + "description": "Specifies the Actor the guard applies to." + }, + "operation": { + "type": "string", + "description": "Specified the operation that the actor is performing the guard applies to." + }, + "timeRange": { + "title": "tosca.datatypes.TimeInterval", + "type": "object", + "required": [ + "start_time", + "end_time" + ], + "properties": { + "start_time": { + "type": "string", + "format": "date-time" + }, + "end_time": { + "type": "string", + "format": "date-time" + } + } + }, + "min": { + "type": "integer", + "description": "The minimum instances of this entity" + }, + "max": { + "type": "integer", + "description": "The maximum instances of this entity" + }, + "target": { + "type": "string", + "description": "The target entity that has scaling restricted" + } + } + }, + "configurationsJson": { + "actor": "test", + "operation": "test", + "target": "test", + "timeRange": { + "start_time": "00:00:00", + "end_time": "01:00:00" + }, + "min": 1, + "max": 10 + }, + "policyModel": { + "policyModelType": "onap.policies.controlloop.guard.common.MinMax", + "version": "1.0.0", + "policyAcronym": "MinMax", + "policyPdpGroup": { + "supportedPdpGroups": [ + { + "defaultGroup": [ + "xacml" + ] + } + ] + }, + "createdDate": "2020-07-22T01:37:35.861060Z", + "updatedDate": "2020-07-22T01:37:51.719018Z", + "updatedBy": "Not found", + "createdBy": "Not found" + }, + "createdDate": "2020-07-22T09:01:14.168344Z", + "updatedDate": "2020-07-22T09:01:14.168344Z", + "updatedBy": "clamp@clamp.onap.org", + "createdBy": "clamp@clamp.onap.org", + "pdpGroup": "defaultGroup", + "pdpSubgroup": "xacml" + } +]
\ No newline at end of file diff --git a/src/onapsdk/clamp/templates/clamp_add_drools_policy.json.j2 b/src/onapsdk/clamp/templates/clamp_add_drools_policy.json.j2 new file mode 100644 index 0000000..40ca7cd --- /dev/null +++ b/src/onapsdk/clamp/templates/clamp_add_drools_policy.json.j2 @@ -0,0 +1,325 @@ +[ + { + "name": "{{ name }}", + "jsonRepresentation": { + "title": "onap.policies.controlloop.operational.common.Drools", + "type": "object", + "description": "Operational policies for Drools PDP", + "required": [ + "abatement", + "operations", + "trigger", + "timeout", + "id" + ], + "properties": { + "abatement": { + "type": "boolean", + "description": "Whether an abatement event message will be expected for the control loop from DCAE.", + "default": "false" + }, + "operations": { + "type": "array", + "description": "List of operations to be performed when Control Loop is triggered.", + "items": { + "title": "onap.datatype.controlloop.Operation", + "type": "object", + "description": "An operation supported by an actor", + "required": [ + "id", + "operation", + "retries", + "timeout" + ], + "properties": { + "failure_retries": { + "type": "string", + "description": "Points to the operation to invoke when the current operation has exceeded its max retries.", + "default": "final_failure_retries" + }, + "id": { + "type": "string", + "description": "Unique identifier for the operation" + }, + "failure_timeout": { + "type": "string", + "description": "Points to the operation to invoke when the time out for the operation occurs.", + "default": "final_failure_timeout" + }, + "failure": { + "type": "string", + "description": "Points to the operation to invoke on Actor operation failure.", + "default": "final_failure" + }, + "operation": { + "title": "onap.datatype.controlloop.Actor", + "type": "object", + "description": "An actor/operation/target definition", + "required": [ + "target", + "actor", + "operation" + ], + "properties": { + "payload": { + "type": "object", + "description": "Name/value pairs of payload information passed by Policy to the actor", + "anyOf": [ + { + "title": "User defined", + "properties": { + + } + } + ] + }, + "target": { + "title": "onap.datatype.controlloop.Target", + "type": "object", + "description": "Definition for a entity in A&AI to perform a control loop operation on", + "required": [ + "targetType" + ], + "properties": { + "entityIds": { + "type": "object", + "description": "Map of values that identify the resource. If none are provided, it is assumed that the\nentity that generated the ONSET event will be the target.\n", + "anyOf": [ + { + "title": "User defined", + "properties": { + + } + }, + { + "title": "VNF-ubuntu18agent_VF 0", + "properties": { + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "6daf6e05-fc26-4aa3-9f0b-d47cf3f37ece", + "readOnly": "True" + } + } + }, + { + "title": "VFMODULE-Ubuntu18agentVf..base_ubuntu18..module-0", + "properties": { + "resourceID": { + "title": "Resource ID", + "type": "string", + "default": "Ubuntu18agentVf..base_ubuntu18..module-0", + "readOnly": "True" + }, + "modelInvariantId": { + "title": "Model Invariant Id (ModelInvariantUUID)", + "type": "string", + "default": "2556faee-75dd-448f-8d2f-d4201a957e7c", + "readOnly": "True" + }, + "modelVersionId": { + "title": "Model Version Id (ModelUUID)", + "type": "string", + "default": "98df9741-530a-486c-b156-b2cb62e6fc6c", + "readOnly": "True" + }, + "modelName": { + "title": "Model Name", + "type": "string", + "default": "Ubuntu18agentVf..base_ubuntu18..module-0", + "readOnly": "True" + }, + "modelVersion": { + "title": "Model Version", + "type": "string", + "default": "1", + "readOnly": "True" + }, + "modelCustomizationId": { + "title": "Customization ID", + "type": "string", + "default": "ba567b66-e46b-4521-8fdd-54185cb21a7f", + "readOnly": "True" + } + } + } + ] + }, + "targetType": { + "type": "string", + "description": "Category for the target type", + "enum": [ + "VNF", + "VM", + "VFMODULE", + "PNF" + ] + } + } + }, + "actor": { + "type": "string", + "description": "The actor performing the operation.", + "enum": [ + "SDNR", + "SDNC", + "VFC", + "SO", + "APPC", + "CDS" + ], + "options": { + "enum_titles": [ + "SDNR", + "SDNC", + "VFC", + "SO", + "APPC" + ] + } + }, + "operation": { + "type": "string", + "description": "The operation the actor is performing.", + "enum": [ + "BandwidthOnDemand", + "VF Module Delete", + "Reroute", + "VF Module Create", + "ModifyConfig", + "Rebuild", + "Restart", + "Migrate", + "Health-Check" + ], + "options": { + "enum_titles": [ + "BandwidthOnDemand (SDNC operation)", + "VF Module Delete (SO operation)", + "Reroute (SDNC operation)", + "VF Module Create (SO operation)", + "ModifyConfig (APPC/VFC operation)", + "Rebuild (APPC operation)", + "Restart (APPC operation)", + "Migrate (APPC operation)", + "Health-Check (APPC operation)" + ] + } + } + } + }, + "failure_guard": { + "type": "string", + "description": "Points to the operation to invoke when the current operation is blocked due to guard policy enforcement.", + "default": "final_failure_guard" + }, + "retries": { + "type": "integer", + "description": "The number of retries the actor should attempt to perform the operation.", + "default": "0" + }, + "timeout": { + "type": "integer", + "description": "The amount of time for the actor to perform the operation." + }, + "failure_exception": { + "type": "string", + "description": "Points to the operation to invoke when the current operation causes an exception.", + "default": "final_failure_exception" + }, + "description": { + "type": "string", + "description": "A user-friendly description of the intent for the operation" + }, + "success": { + "type": "string", + "description": "Points to the operation to invoke on success. A value of \"final_success\" indicates and end to the operation.", + "default": "final_success" + } + } + }, + "format": "tabs-top" + }, + "trigger": { + "type": "string", + "description": "Initial operation to execute upon receiving an Onset event message for the Control Loop." + }, + "timeout": { + "type": "integer", + "description": "Overall timeout for executing all the operations. This timeout should equal or exceed the total\ntimeout for each operation listed.\n" + }, + "id": { + "type": "string", + "description": "The unique control loop id." + }, + "controllerName": { + "type": "string", + "description": "Drools controller properties" + } + } + }, + "configurationsJson": { + "abatement": false, + "operations": [ + { + "failure_retries": "final_failure_retries", + "id": "policy-1-vfmodule-create", + "failure_timeout": "final_failure_timeout", + "failure": "final_failure", + "operation": { + "payload": { + "requestParameters": "{\"usePreload\":false,\"userParams\":[]}", + "configurationParameters": "[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[16].value\",\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[30].value\"}]" + }, + "target": { + "entityIds": { + "resourceID": "{{ resourceID }}", + "modelInvariantId": "{{ modelInvariantId }}", + "modelVersionId": "{{ modelVersionId }}", + "modelName": "{{ modelName }}", + "modelVersion": "{{ modelVersion }}", + "modelCustomizationId": "{{ modelCustomizationId }}" + }, + "targetType": "VFMODULE" + }, + "actor": "SO", + "operation": "VF Module Create" + }, + "failure_guard": "final_failure_guard", + "retries": 1, + "timeout": 300, + "failure_exception": "final_failure_exception", + "description": "test", + "success": "final_success" + } + ], + "trigger": "policy-1-vfmodule-create", + "timeout": 650, + "id": "{{ LOOP_name }}" + }, + "policyModel": { + "policyModelType": "onap.policies.controlloop.operational.common.Drools", + "version": "1.0.0", + "policyAcronym": "Drools", + "policyPdpGroup": { + "supportedPdpGroups": [ + { + "defaultGroup": [ + "drools" + ] + } + ] + }, + "createdDate": "2020-07-22T01:37:38.528901Z", + "updatedDate": "2020-07-22T01:37:51.752302Z", + "updatedBy": "Not found", + "createdBy": "Not found" + }, + "createdDate": "2020-07-22T07:50:00.076714Z", + "updatedDate": "2020-07-22T07:50:00.076714Z", + "updatedBy": "clamp@clamp.onap.org", + "createdBy": "clamp@clamp.onap.org", + "pdpGroup": "defaultGroup", + "pdpSubgroup": "drools" + } +]
\ No newline at end of file diff --git a/src/onapsdk/clamp/templates/clamp_add_frequency.json.j2 b/src/onapsdk/clamp/templates/clamp_add_frequency.json.j2 new file mode 100644 index 0000000..fabf9e6 --- /dev/null +++ b/src/onapsdk/clamp/templates/clamp_add_frequency.json.j2 @@ -0,0 +1,102 @@ +[ + { + "name": "{{ name }}", + "jsonRepresentation": { + "title": "onap.policies.controlloop.guard.common.FrequencyLimiter", + "type": "object", + "description": "Supports limiting the frequency of actions being taken by a Actor.", + "required": [ + "actor", + "operation", + "limit", + "timeWindow", + "timeUnits" + ], + "properties": { + "id": { + "type": "string", + "description": "The Control Loop id this applies to." + }, + "actor": { + "type": "string", + "description": "Specifies the Actor the guard applies to." + }, + "operation": { + "type": "string", + "description": "Specified the operation that the actor is performing the guard applies to." + }, + "timeRange": { + "title": "tosca.datatypes.TimeInterval", + "type": "object", + "required": [ + "start_time", + "end_time" + ], + "properties": { + "start_time": { + "type": "string", + "format": "date-time" + }, + "end_time": { + "type": "string", + "format": "date-time" + } + } + }, + "limit": { + "type": "integer", + "description": "The limit", + "exclusiveMinimum": "0" + }, + "timeWindow": { + "type": "integer", + "description": "The time window to count the actions against." + }, + "timeUnits": { + "type": "string", + "description": "The units of time the window is counting.", + "enum": [ + "second", + "minute", + "hour", + "day", + "week", + "month", + "year" + ] + } + } + }, + "configurationsJson": { + "actor": "SO", + "operation": "VF Module Create", + "limit": {{ limit }}, + "timeWindow": 10, + "timeUnits": "minute" + }, + "policyModel": { + "policyModelType": "onap.policies.controlloop.guard.common.FrequencyLimiter", + "version": "1.0.0", + "policyAcronym": "FrequencyLimiter", + "policyPdpGroup": { + "supportedPdpGroups": [ + { + "defaultGroup": [ + "xacml" + ] + } + ] + }, + "createdDate": "2020-07-22T01:37:35.106757Z", + "updatedDate": "2020-07-22T01:37:51.709386Z", + "updatedBy": "Not found", + "createdBy": "Not found" + }, + "createdDate": "2020-07-22T08:27:34.576868Z", + "updatedDate": "2020-07-22T08:27:34.576868Z", + "updatedBy": "clamp@clamp.onap.org", + "createdBy": "clamp@clamp.onap.org", + "pdpGroup": "defaultGroup", + "pdpSubgroup": "xacml" + } +]
\ No newline at end of file diff --git a/src/onapsdk/clamp/templates/clamp_add_tca_config.json.j2 b/src/onapsdk/clamp/templates/clamp_add_tca_config.json.j2 new file mode 100644 index 0000000..0919a6b --- /dev/null +++ b/src/onapsdk/clamp/templates/clamp_add_tca_config.json.j2 @@ -0,0 +1,30 @@ +{ + "name": "{{ name }}", + "configurationsJson": { + "tca.policy": { + "domain": "measurementsForVfScaling", + "metricsPerEventName": [ + { + "policyScope": "DCAE", + "thresholds": [ + { + "version": "1.0.2", + "severity": "MAJOR", + "thresholdValue": 200, + "closedLoopEventStatus": "ONSET", + "closedLoopControlName": "{{ LOOP_name }}", + "direction": "LESS_OR_EQUAL", + "fieldPath": "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta" + } + ], + "eventName": "vLoadBalancer", + "policyVersion": "v0.0.1", + "controlLoopSchemaType": "VM", + "policyName": "DCAE.Config_tca-hi-lo" + } + ] + } + }, + "pdpGroup": "defaultGroup", + "pdpSubgroup": "xacml" +} |