2 # Licensed under the Apache License, Version 2.0 (the "License"); you may
3 # not use this file except in compliance with the License. You may obtain
4 # a copy of the License at
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11 # License for the specific language governing permissions and limitations
14 from collections import defaultdict
16 from translator.hot.syntax.hot_resource import HotResource
17 # Name used to dynamically load appropriate map class.
18 TARGET_CLASS_NAME = 'ToscaClusterAutoscaling'
20 SCALE_POLICY = 'senlin.policy.scaling-1.0'
21 SERVER_TYPE = 'os.nova.server-1.0'
22 SCALE_TYPE = {'SCALE_IN': 'CLUSTER_SCALE_IN',
23 'SCALE_OUT': 'CLUSTER_SCALE_OUT'}
25 ALARM_METER_NAME = {'utilization': 'cpu_util'}
26 ALARM_COMPARISON_OPERATOR = {'greater_than': 'gt', 'gerater_equal': 'ge',
27 'less_than': 'lt', 'less_equal': 'le',
28 'equal': 'eq', 'not_equal': 'ne'}
29 ALARM_STATISTIC = {'average': 'avg'}
32 class ToscaClusterAutoscaling(HotResource):
33 '''Translate TOSCA node type tosca.policies.Scaling.Cluster'''
35 toscatype = 'tosca.policies.Scaling.Cluster'
37 def __init__(self, policy, csar_dir=None):
38 hot_type = "OS::Senlin::Policy"
39 super(ToscaClusterAutoscaling, self).__init__(policy,
44 def _generate_scale_properties(self,
51 properties["type"] = SCALE_POLICY
52 for cluster_node in target_cluster_nodes:
53 bindings.append({'cluster': cluster_node})
54 properties["bindings"] = bindings
55 policy_res["event"] = cluster_scale_type
56 adjustment["type"] = "CHANGE_IN_CAPACITY"
57 adjustment["number"] = self.\
58 policy.entity_tpl["properties"]["increment"]
59 policy_res["adjustment"] = adjustment
60 properties["properties"] = policy_res
63 def handle_expansion(self):
65 trigger_receivers = defaultdict(list)
66 for node in self.policy.targets:
67 for trigger in self.policy.entity_tpl['triggers']:
68 for action in self.policy.\
69 entity_tpl['triggers'][trigger]['action']:
71 action_sample = self.policy.\
72 entity_tpl['triggers'][trigger]['action'][action]
73 scale_type = action_sample['type']
74 scale_implement = action_sample['implementation']
75 (entity, method) = scale_implement.split('.')
77 receiver_prop['cluster'] = {
78 "get_resource": "%s_cluster" % node
80 receiver_prop['action'] = SCALE_TYPE[scale_type]
81 receiver_prop['type'] = method
82 receiver_name = node + '_' + scale_name + '_receiver'
83 trigger_receivers[trigger].append(receiver_name)
84 receiver_resources = HotResource(self.nodetemplate,
85 type='OS::Senlin::Receiver',
87 properties=receiver_prop)
88 hot_resources.append(receiver_resources)
90 for trigger in self.policy.entity_tpl['triggers']:
91 sample = self.policy.\
92 entity_tpl['triggers'][trigger]['condition']
93 (meter_name, comparison_operator, threshold) = \
94 sample["constraint"].split()
95 threshold = threshold.strip("%")
97 alarm_prop["description"] = self.policy.entity_tpl['description']
98 alarm_prop["meter_name"] = self.policy.\
99 entity_tpl['triggers'][trigger]['event_type']['metrics']
100 alarm_prop["statistic"] = ALARM_STATISTIC[sample['method']]
101 alarm_prop["period"] = sample["period"]
102 alarm_prop["evaluation_periods"] = sample["evaluations"]
103 alarm_prop["threshold"] = threshold
104 alarm_prop["comparison_operator"] = \
105 ALARM_COMPARISON_OPERATOR[comparison_operator]
106 alarm_prop["repeat_actions"] = "True"
107 alarm_prop["alarm_actions"] = []
108 for index in range(len(trigger_receivers[trigger])):
109 alarm_prop["alarm_actions"].\
110 append({'get_attr': [trigger_receivers[trigger][index],
113 ceilometer_resources = HotResource(self.nodetemplate,
114 type='OS::Aodh::Alarm',
115 name=trigger + '_alarm',
116 properties=alarm_prop)
117 hot_resources.append(ceilometer_resources)
120 def handle_properties(self, resources):
121 remove_resources = []
122 networks = defaultdict(list)
123 for index, resource in enumerate(resources):
124 if resource.type == 'OS::Neutron::Port':
125 for hot_resource in resource.depends_on_nodes:
126 if hot_resource.type != 'OS::Neutron::Net':
127 networks[hot_resource.name].\
129 {'network': '%s' % resource.properties['network']}
131 remove_resources.append(resource)
132 elif resource.type == 'OS::Neutron::Net':
133 remove_resources.append(resource)
134 elif resource.name in self.policy.targets and \
135 resource.type != 'OS::Senlin::Policy':
137 del resource.properties['user_data_format']
138 del resource.properties['networks']
139 props['type'] = SERVER_TYPE
140 props['properties'] = resource.properties
141 profile_resources = \
142 HotResource(resource,
143 type='OS::Senlin::Profile',
147 resources.insert(index, profile_resources)
148 for remove_resource in remove_resources:
149 resources.remove(remove_resource)
151 for index, resource in enumerate(resources):
152 if resource.name in self.policy.targets:
153 resource.properties['properties']['networks'] = \
154 networks[resource.name]
156 for node in self.policy.targets:
158 props["profile"] = {'get_resource': '%s' % node}
159 temp = self.policy.entity_tpl["properties"]
160 props["min_size"] = temp["min_instances"]
161 props["max_size"] = temp["max_instances"]
162 props["desired_capacity"] = temp["default_instances"]
163 self.cluster_name = '%s_cluster' % node
164 cluster_resources = \
165 HotResource(self.nodetemplate,
166 type='OS::Senlin::Cluster',
167 name=self.cluster_name,
169 resources.append(cluster_resources)
171 trigger_num = len(self.policy.entity_tpl['triggers'])
172 for num, trigger in enumerate(self.policy.entity_tpl['triggers']):
173 target_cluster_nodes = []
174 for action in self.policy.\
175 entity_tpl['triggers'][trigger]['action']:
176 scale_type = self.policy.\
177 entity_tpl['triggers'][trigger]['action'][action]['type']
178 for node in self.policy.targets:
179 target_cluster_nodes.\
180 append({"get_resource": "%s_cluster" % node})
181 cluster_scale_type = SCALE_TYPE[scale_type]
183 self._generate_scale_properties(target_cluster_nodes,
185 if num == trigger_num - 1:
186 self.name = self.name + '_' + trigger
187 self.properties = scale_in_props
190 HotResource(self.nodetemplate,
191 type='OS::Senlin::Policy',
192 name=self.name + '_' + trigger,
193 properties=scale_in_props)
194 resources.append(policy_resources)