From cb4883a5512bc9b897e64f270ca6507a883df05f Mon Sep 17 00:00:00 2001 From: doantungbk Date: Sun, 5 Feb 2017 04:15:44 -0800 Subject: [PATCH] Implement monitoring policy in HT Currently, monitoring policy have not been added to Heat Translator yet. The current implementation of scaling policy in Heat Translator showed the couple between scaling and monitoring policies. But actually monitoring policy shows that it could have other very good use cases so that it can stand alone. This patch will implement monitoring policy in HT. Implements bp: #monitoring-policy Change-Id: Ibc412c409846919a8edb581c7cf56e6dcd0cc01f Depends-On: Idd5268b7ff0a19b57ea927f23c76db24220c462d --- translator/hot/syntax/hot_resource.py | 3 +- .../hot/tosca/tosca_policies_monitoring.py | 82 +++++++++++++++++++ translator/hot/translate_node_templates.py | 8 +- .../data/hot_output/monitoring/asg_res.yaml | 9 ++ .../monitoring/hot_monitoring_scaling.yaml | 50 +++++++++++ .../monitoring/tosca_monitoring_scaling.yaml | 59 +++++++++++++ .../tests/test_tosca_hot_translation.py | 9 ++ 7 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 translator/hot/tosca/tosca_policies_monitoring.py create mode 100644 translator/tests/data/hot_output/monitoring/asg_res.yaml create mode 100644 translator/tests/data/hot_output/monitoring/hot_monitoring_scaling.yaml create mode 100644 translator/tests/data/monitoring/tosca_monitoring_scaling.yaml diff --git a/translator/hot/syntax/hot_resource.py b/translator/hot/syntax/hot_resource.py index 73fbd245..0f285ad8 100644 --- a/translator/hot/syntax/hot_resource.py +++ b/translator/hot/syntax/hot_resource.py @@ -29,7 +29,8 @@ SECTIONS = (TYPE, PROPERTIES, MEDADATA, DEPENDS_ON, UPDATE_POLICY, policy_type = ['tosca.policies.Placement', 'tosca.policies.Scaling', - 'tosca.policies.Scaling.Cluster'] + 'tosca.policies.Scaling.Cluster', + 'tosca.policies.Monitoring'] log = logging.getLogger('heat-translator') diff --git a/translator/hot/tosca/tosca_policies_monitoring.py b/translator/hot/tosca/tosca_policies_monitoring.py new file mode 100644 index 00000000..7aac1c72 --- /dev/null +++ b/translator/hot/tosca/tosca_policies_monitoring.py @@ -0,0 +1,82 @@ +# +# 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 logging +from toscaparser.common.exception import InvalidPropertyValueError +from translator.hot.syntax.hot_resource import HotResource + +# Name used to dynamically load appropriate map class. +TARGET_CLASS_NAME = 'ToscaMonitoring' + +log = logging.getLogger('heat-translator') + +ALARM_STATISTIC = {'average': 'avg', 'summary': 'sum', + 'maximum': 'max', 'minimum': 'min'} + + +class ToscaMonitoring(HotResource): + '''Translate TOSCA node type tosca.policies.Monitoring''' + + toscatype = 'tosca.policies.Monitoring' + + def __init__(self, policy, csar_dir=None): + hot_type = "OS::Aodh::Alarm" + super(ToscaMonitoring, self).__init__(policy, + type=hot_type, + csar_dir=csar_dir) + self.policy = policy + self.filter = list() + + def handle_expansion(self): + '''handle monitoring resources in case of multiple triggers''' + extra_resources = list() + extra_triggers = self.policy.entity_tpl["triggers"] + for trigger_name, trigger_dict in extra_triggers.items(): + if trigger_name not in self.filter: + self.filter.append(trigger_name) + prop = self._get_monitoring_prop(trigger_dict) + mon_resources = HotResource(self.nodetemplate, + type='OS::Aodh::Alarm', + name=trigger_name, + properties=prop) + extra_resources.append(mon_resources) + return extra_resources + + def handle_properties(self): + self.properties = {} + if self.policy.entity_tpl.get('triggers'): + triggers = self.policy.entity_tpl["triggers"] + trigger_name, trigger_dict = list(triggers.items())[0] + self.filter.append(trigger_name) + self.properties = self._get_monitoring_prop(trigger_dict) + self.name = trigger_name + return self.properties + + def _get_monitoring_prop(self, trigger): + sample = trigger.get('condition') + prop = dict() + prop["description"] = sample.get('constraint') + prop["meter_name"] = trigger.get('meter_name') + if sample.get('method') not in ALARM_STATISTIC: + msg = _('method should be one of given statistics') + log.error(msg) + raise InvalidPropertyValueError(what=msg) + prop["statistic"] = ALARM_STATISTIC[sample["method"]] + prop["period"] = sample.get("period") + prop["threshold"] = sample.get("threshold") + prop["comparison_operator"] = sample.get('comparison_operator') + prop['evaluation_periods'] = sample.get('evaluations') + return prop + + def embed_substack_templates(self, hot_template_version): + pass diff --git a/translator/hot/translate_node_templates.py b/translator/hot/translate_node_templates.py index 0bb375ba..78ab1c45 100644 --- a/translator/hot/translate_node_templates.py +++ b/translator/hot/translate_node_templates.py @@ -270,8 +270,12 @@ class TranslateNodeTemplates(object): policy_type.type != 'tosca.policies.Scaling.Cluster': TOSCA_TO_HOT_TYPE[policy_type.type] = \ TOSCA_TO_HOT_TYPE['tosca.policies.Scaling'] - if not policy.is_derived_from('tosca.policies.Scaling') and \ - policy_type.type not in TOSCA_TO_HOT_TYPE: + if policy.is_derived_from('tosca.policies.Monitoring'): + TOSCA_TO_HOT_TYPE[policy_type.type] = \ + TOSCA_TO_HOT_TYPE['tosca.policies.Monitoring'] + if not policy.is_derived_from('tosca.policies.Monitoring') and \ + not policy.is_derived_from('tosca.policies.Scaling') and \ + policy_type.type not in TOSCA_TO_HOT_TYPE: raise UnsupportedTypeError(type=_('%s') % policy_type.type) elif policy_type.type == 'tosca.policies.Scaling.Cluster': self.hot_template_version = '2016-04-08' diff --git a/translator/tests/data/hot_output/monitoring/asg_res.yaml b/translator/tests/data/hot_output/monitoring/asg_res.yaml new file mode 100644 index 00000000..b2a2b2ab --- /dev/null +++ b/translator/tests/data/hot_output/monitoring/asg_res.yaml @@ -0,0 +1,9 @@ +heat_template_version: 2013-05-23 +description: Tacker Scaling template +resources: + my_server_1: + type: OS::Nova::Server + properties: + flavor: m1.medium + user_data_format: SOFTWARE_CONFIG + image: rhel-6.5-test-image diff --git a/translator/tests/data/hot_output/monitoring/hot_monitoring_scaling.yaml b/translator/tests/data/hot_output/monitoring/hot_monitoring_scaling.yaml new file mode 100644 index 00000000..8aaacba1 --- /dev/null +++ b/translator/tests/data/hot_output/monitoring/hot_monitoring_scaling.yaml @@ -0,0 +1,50 @@ +heat_template_version: 2013-05-23 + +description: > + Template for deploying servers based on policies. + +parameters: {} +resources: + asg_scale_out: + type: OS::Heat::ScalingPolicy + properties: + auto_scaling_group_id: + get_resource: asg_group + adjustment_type: change_in_capacity + scaling_adjustment: 1 + low_cpu_usage: + type: OS::Aodh::Alarm + properties: + meter_name: cpu_util + description: utilization less_than 20% + evaluation_periods: 1 + period: 600 + statistic: avg + threshold: 20 + comparison_operator: gt + asg_group: + type: OS::Heat::AutoScalingGroup + properties: + min_size: 2 + desired_capacity: 3 + resource: + type: asg_res.yaml + max_size: 10 + asg_scale_in: + type: OS::Heat::ScalingPolicy + properties: + auto_scaling_group_id: + get_resource: asg_group + adjustment_type: change_in_capacity + scaling_adjustment: -1 + high_cpu_usage: + type: OS::Aodh::Alarm + properties: + meter_name: cpu_util + description: utilization greater_than 60% + evaluation_periods: 1 + period: 600 + statistic: avg + threshold: 60 + comparison_operator: gt +outputs: {} diff --git a/translator/tests/data/monitoring/tosca_monitoring_scaling.yaml b/translator/tests/data/monitoring/tosca_monitoring_scaling.yaml new file mode 100644 index 00000000..eb812048 --- /dev/null +++ b/translator/tests/data/monitoring/tosca_monitoring_scaling.yaml @@ -0,0 +1,59 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +description: > + Template for deploying servers based on policies. + +topology_template: + node_templates: + my_server_1: + type: tosca.nodes.Compute + capabilities: + host: + properties: + num_cpus: 2 + disk_size: 10 GB + mem_size: 512 MB + os: + properties: + # host Operating System image properties + architecture: x86_64 + type: Linux + distribution: RHEL + version: 6.5 + policies: + - asg: + type: tosca.policies.Scaling + description: Simple node autoscaling + targets: [my_server_1] + properties: + min_instances: 2 + max_instances: 10 + default_instances: 3 + increment: 1 + + - cpu_monitoring: + type: tosca.policies.Monitoring + description: Simple node monitoring + targets: [my_server_1] + triggers: + high_cpu_usage: + description: trigger + meter_name: cpu_util + condition: + constraint: utilization greater_than 60% + threshold: 60 + period: 600 + evaluations: 1 + method: average + comparison_operator: gt + + low_cpu_usage: + description: trigger + meter_name: cpu_util + condition: + constraint: utilization less_than 20% + threshold: 20 + period: 600 + evaluations: 1 + method: average + comparison_operator: gt \ No newline at end of file diff --git a/translator/tests/test_tosca_hot_translation.py b/translator/tests/test_tosca_hot_translation.py index c1240b56..f67c86c6 100644 --- a/translator/tests/test_tosca_hot_translation.py +++ b/translator/tests/test_tosca_hot_translation.py @@ -555,3 +555,12 @@ class ToscaHotTranslationTest(TestCase): ] params = {} self._test_successful_translation(tosca_file, hot_files, params) + + def test_hot_translate_mon_scaling_policy(self): + tosca_file = '../tests/data/monitoring/tosca_monitoring_scaling.yaml' + hot_files = [ + '../tests/data/hot_output/monitoring/hot_monitoring_scaling.yaml', + '../tests/data/hot_output/monitoring/asg_res.yaml', + ] + params = {} + self._test_successful_translation(tosca_file, hot_files, params)