summaryrefslogtreecommitdiffstats
path: root/tosca2heat/heat-translator/translator/hot/tosca/tosca_cluster_policies_scaling.py
diff options
context:
space:
mode:
Diffstat (limited to 'tosca2heat/heat-translator/translator/hot/tosca/tosca_cluster_policies_scaling.py')
-rw-r--r--tosca2heat/heat-translator/translator/hot/tosca/tosca_cluster_policies_scaling.py195
1 files changed, 195 insertions, 0 deletions
diff --git a/tosca2heat/heat-translator/translator/hot/tosca/tosca_cluster_policies_scaling.py b/tosca2heat/heat-translator/translator/hot/tosca/tosca_cluster_policies_scaling.py
new file mode 100644
index 0000000..1de0158
--- /dev/null
+++ b/tosca2heat/heat-translator/translator/hot/tosca/tosca_cluster_policies_scaling.py
@@ -0,0 +1,195 @@
+#
+# 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 collections import defaultdict
+
+from translator.hot.syntax.hot_resource import HotResource
+# Name used to dynamically load appropriate map class.
+TARGET_CLASS_NAME = 'ToscaClusterAutoscaling'
+
+SCALE_POLICY = 'senlin.policy.scaling-1.0'
+SERVER_TYPE = 'os.nova.server-1.0'
+SCALE_TYPE = {'SCALE_IN': 'CLUSTER_SCALE_IN',
+ 'SCALE_OUT': 'CLUSTER_SCALE_OUT'}
+
+ALARM_METER_NAME = {'utilization': 'cpu_util'}
+ALARM_COMPARISON_OPERATOR = {'greater_than': 'gt', 'gerater_equal': 'ge',
+ 'less_than': 'lt', 'less_equal': 'le',
+ 'equal': 'eq', 'not_equal': 'ne'}
+ALARM_STATISTIC = {'average': 'avg'}
+
+
+class ToscaClusterAutoscaling(HotResource):
+ '''Translate TOSCA node type tosca.policies.Scaling.Cluster'''
+
+ toscatype = 'tosca.policies.Scaling.Cluster'
+
+ def __init__(self, policy, csar_dir=None):
+ hot_type = "OS::Senlin::Policy"
+ super(ToscaClusterAutoscaling, self).__init__(policy,
+ type=hot_type,
+ csar_dir=csar_dir)
+ self.policy = policy
+
+ def _generate_scale_properties(self,
+ target_cluster_nodes,
+ cluster_scale_type):
+ properties = {}
+ bindings = []
+ policy_res = {}
+ adjustment = {}
+ properties["type"] = SCALE_POLICY
+ for cluster_node in target_cluster_nodes:
+ bindings.append({'cluster': cluster_node})
+ properties["bindings"] = bindings
+ policy_res["event"] = cluster_scale_type
+ adjustment["type"] = "CHANGE_IN_CAPACITY"
+ adjustment["number"] = self.\
+ policy.entity_tpl["properties"]["increment"]
+ policy_res["adjustment"] = adjustment
+ properties["properties"] = policy_res
+ return properties
+
+ def handle_expansion(self):
+ hot_resources = []
+ trigger_receivers = defaultdict(list)
+ for node in self.policy.targets:
+ for trigger in self.policy.entity_tpl['triggers']:
+ for action in self.policy.\
+ entity_tpl['triggers'][trigger]['action']:
+ scale_name = action
+ action_sample = self.policy.\
+ entity_tpl['triggers'][trigger]['action'][action]
+ scale_type = action_sample['type']
+ scale_implement = action_sample['implementation']
+ (entity, method) = scale_implement.split('.')
+ receiver_prop = {}
+ receiver_prop['cluster'] = {
+ "get_resource": "%s_cluster" % node
+ }
+ receiver_prop['action'] = SCALE_TYPE[scale_type]
+ receiver_prop['type'] = method
+ receiver_name = node + '_' + scale_name + '_receiver'
+ trigger_receivers[trigger].append(receiver_name)
+ receiver_resources = HotResource(self.nodetemplate,
+ type='OS::Senlin::Receiver',
+ name=receiver_name,
+ properties=receiver_prop)
+ hot_resources.append(receiver_resources)
+
+ for trigger in self.policy.entity_tpl['triggers']:
+ sample = self.policy.\
+ entity_tpl['triggers'][trigger]['condition']
+ (meter_name, comparison_operator, threshold) = \
+ sample["constraint"].split()
+ threshold = threshold.strip("%")
+ alarm_prop = {}
+ alarm_prop["description"] = self.policy.entity_tpl['description']
+ alarm_prop["meter_name"] = self.policy.\
+ entity_tpl['triggers'][trigger]['event_type']['metrics']
+ alarm_prop["statistic"] = ALARM_STATISTIC[sample['method']]
+ alarm_prop["period"] = sample["period"]
+ alarm_prop["evaluation_periods"] = sample["evaluations"]
+ alarm_prop["threshold"] = threshold
+ alarm_prop["comparison_operator"] = \
+ ALARM_COMPARISON_OPERATOR[comparison_operator]
+ alarm_prop["repeat_actions"] = "True"
+ alarm_prop["alarm_actions"] = []
+ for index in range(len(trigger_receivers[trigger])):
+ alarm_prop["alarm_actions"].\
+ append({'get_attr': [trigger_receivers[trigger][index],
+ 'channel',
+ 'alarm_url']})
+ ceilometer_resources = HotResource(self.nodetemplate,
+ type='OS::Aodh::Alarm',
+ name=trigger + '_alarm',
+ properties=alarm_prop)
+ hot_resources.append(ceilometer_resources)
+ return hot_resources
+
+ def handle_properties(self, resources):
+ remove_resources = []
+ networks = defaultdict(list)
+ for index, resource in enumerate(resources):
+ if resource.type == 'OS::Neutron::Port':
+ for hot_resource in resource.depends_on_nodes:
+ if hot_resource.type != 'OS::Neutron::Net':
+ networks[hot_resource.name].\
+ append(
+ {'network': '%s' % resource.properties['network']}
+ )
+ remove_resources.append(resource)
+ elif resource.type == 'OS::Neutron::Net':
+ remove_resources.append(resource)
+ elif resource.name in self.policy.targets and \
+ resource.type != 'OS::Senlin::Policy':
+ props = {}
+ del resource.properties['user_data_format']
+ del resource.properties['networks']
+ props['type'] = SERVER_TYPE
+ props['properties'] = resource.properties
+ profile_resources = \
+ HotResource(resource,
+ type='OS::Senlin::Profile',
+ name=resource.name,
+ properties=props)
+ resources.pop(index)
+ resources.insert(index, profile_resources)
+ for remove_resource in remove_resources:
+ resources.remove(remove_resource)
+
+ for index, resource in enumerate(resources):
+ if resource.name in self.policy.targets:
+ resource.properties['properties']['networks'] = \
+ networks[resource.name]
+
+ for node in self.policy.targets:
+ props = {}
+ props["profile"] = {'get_resource': '%s' % node}
+ temp = self.policy.entity_tpl["properties"]
+ props["min_size"] = temp["min_instances"]
+ props["max_size"] = temp["max_instances"]
+ props["desired_capacity"] = temp["default_instances"]
+ self.cluster_name = '%s_cluster' % node
+ cluster_resources = \
+ HotResource(self.nodetemplate,
+ type='OS::Senlin::Cluster',
+ name=self.cluster_name,
+ properties=props)
+ resources.append(cluster_resources)
+
+ trigger_num = len(self.policy.entity_tpl['triggers'])
+ for num, trigger in enumerate(self.policy.entity_tpl['triggers']):
+ target_cluster_nodes = []
+ for action in self.policy.\
+ entity_tpl['triggers'][trigger]['action']:
+ scale_type = self.policy.\
+ entity_tpl['triggers'][trigger]['action'][action]['type']
+ for node in self.policy.targets:
+ target_cluster_nodes.\
+ append({"get_resource": "%s_cluster" % node})
+ cluster_scale_type = SCALE_TYPE[scale_type]
+ scale_in_props = \
+ self._generate_scale_properties(target_cluster_nodes,
+ cluster_scale_type)
+ if num == trigger_num - 1:
+ self.name = self.name + '_' + trigger
+ self.properties = scale_in_props
+ break
+ policy_resources = \
+ HotResource(self.nodetemplate,
+ type='OS::Senlin::Policy',
+ name=self.name + '_' + trigger,
+ properties=scale_in_props)
+ resources.append(policy_resources)
+ return resources