1 # Licensed under the Apache License, Version 2.0 (the "License"); you may
2 # not use this file except in compliance with the License. You may obtain
3 # a copy of the License at
5 # http://www.apache.org/licenses/LICENSE-2.0
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 # License for the specific language governing permissions and limitations
16 from toscaparser.common import exception
17 from toscaparser.dataentity import DataEntity
18 from toscaparser import functions
19 from toscaparser.groups import Group
20 from toscaparser.nodetemplate import NodeTemplate
21 from toscaparser.parameters import Input
22 from toscaparser.parameters import Output
23 from toscaparser.policy import Policy
24 from toscaparser.relationship_template import RelationshipTemplate
25 from toscaparser.substitution_mappings import Substitution_mappings
26 from toscaparser.tpl_relationship_graph import ToscaGraph
27 from toscaparser.utils.gettextutils import _
30 # Topology template key names
31 SECTIONS = (DESCRIPTION, INPUTS, NODE_TEMPLATES,
32 RELATIONSHIP_TEMPLATES, OUTPUTS, GROUPS,
33 SUBSTITUION_MAPPINGS, POLICIES) = \
34 ('description', 'inputs', 'node_templates',
35 'relationship_templates', 'outputs', 'groups',
36 'substitution_mappings', 'policies')
38 log = logging.getLogger("tosca.model")
41 class TopologyTemplate(object):
43 '''Load the template data.'''
44 def __init__(self, template, custom_defs,
45 rel_types=None, parsed_params=None,
46 sub_mapped_node_template=None):
48 self.sub_mapped_node_template = sub_mapped_node_template
50 self.custom_defs = custom_defs
51 self.rel_types = rel_types
52 self.parsed_params = parsed_params
53 self._validate_field()
54 self.description = self._tpl_description()
55 self.inputs = self._inputs()
56 self.relationship_templates = self._relationship_templates()
57 self.nodetemplates = self._nodetemplates()
58 self.outputs = self._outputs()
59 if hasattr(self, 'nodetemplates'):
60 self.graph = ToscaGraph(self.nodetemplates)
61 self.groups = self._groups()
62 self.policies = self._policies()
63 self._process_intrinsic_functions()
64 self.substitution_mappings = self._substitution_mappings()
68 for name, attrs in self._tpl_inputs().items():
69 input = Input(name, attrs)
70 if self.parsed_params and name in self.parsed_params:
71 input.validate(self.parsed_params[name])
73 default = input.default
75 input.validate(default)
79 def _nodetemplates(self):
81 tpls = self._tpl_nodetemplates()
84 tpl = NodeTemplate(name, tpls, self.custom_defs,
85 self.relationship_templates,
87 if (tpl.type_definition and
88 (tpl.type in tpl.type_definition.TOSCA_DEF or
89 (tpl.type not in tpl.type_definition.TOSCA_DEF and
90 bool(tpl.custom_def)))):
92 nodetemplates.append(tpl)
95 def _relationship_templates(self):
97 tpls = self._tpl_relationship_templates()
99 tpl = RelationshipTemplate(tpls[name], name, self.custom_defs)
100 rel_templates.append(tpl)
105 for name, attrs in self._tpl_outputs().items():
106 output = Output(name, attrs)
108 outputs.append(output)
111 def _substitution_mappings(self):
112 tpl_substitution_mapping = self._tpl_substitution_mappings()
113 if tpl_substitution_mapping and self.sub_mapped_node_template:
114 return Substitution_mappings(tpl_substitution_mapping,
118 self.sub_mapped_node_template,
123 for policy in self._tpl_policies():
124 for policy_name, policy_tpl in policy.items():
125 target_list = policy_tpl.get('targets')
126 if target_list and len(target_list) >= 1:
128 targets_type = "groups"
129 target_objects = self._get_policy_groups(target_list)
130 if not target_objects:
131 targets_type = "node_templates"
132 target_objects = self._get_group_members(target_list)
133 policyObj = Policy(policy_name, policy_tpl,
134 target_objects, targets_type,
136 policies.append(policyObj)
142 for group_name, group_tpl in self._tpl_groups().items():
143 member_names = group_tpl.get('members')
144 if member_names is not None:
145 DataEntity.validate_datatype('list', member_names)
146 if len(member_names) < 1 or \
147 len(member_names) != len(set(member_names)):
148 exception.ExceptionCollector.appendException(
149 exception.InvalidGroupTargetException(
150 message=_('Member nodes "%s" should be >= 1 '
151 'and not repeated') % member_names))
153 member_nodes = self._get_group_members(member_names)
154 group = Group(group_name, group_tpl,
160 def _get_group_members(self, member_names):
162 self._validate_group_members(member_names)
163 for member in member_names:
164 for node in self.nodetemplates:
165 if node.name == member:
166 member_nodes.append(node)
169 def _get_policy_groups(self, member_names):
171 for member in member_names:
172 for group in self.groups:
173 if group.name == member:
174 member_groups.append(group)
177 def _validate_group_members(self, members):
179 for node in self.nodetemplates:
180 node_names.append(node.name)
181 for member in members:
182 if member not in node_names:
183 exception.ExceptionCollector.appendException(
184 exception.InvalidGroupTargetException(
185 message=_('Target member "%s" is not found in '
186 'node_templates') % member))
188 # topology template can act like node template
189 # it is exposed by substitution_mappings.
191 return (self.substitution_mappings.node_type
192 if self.substitution_mappings else None)
194 def capabilities(self):
195 return (self.substitution_mappings.capabilities
196 if self.substitution_mappings else None)
198 def requirements(self):
199 return (self.substitution_mappings.requirements
200 if self.substitution_mappings else None)
202 def _tpl_description(self):
203 description = self.tpl.get(DESCRIPTION)
205 return description.rstrip()
207 def _tpl_inputs(self):
208 return self.tpl.get(INPUTS) or {}
210 def _tpl_nodetemplates(self):
211 return self.tpl.get(NODE_TEMPLATES)
213 def _tpl_relationship_templates(self):
214 return self.tpl.get(RELATIONSHIP_TEMPLATES) or {}
216 def _tpl_outputs(self):
217 return self.tpl.get(OUTPUTS) or {}
219 def _tpl_substitution_mappings(self):
220 return self.tpl.get(SUBSTITUION_MAPPINGS) or {}
222 def _tpl_groups(self):
223 return self.tpl.get(GROUPS) or {}
225 def _tpl_policies(self):
226 return self.tpl.get(POLICIES) or {}
228 def _validate_field(self):
229 for name in self.tpl:
230 if name not in SECTIONS:
231 exception.ExceptionCollector.appendException(
232 exception.UnknownFieldError(what='Template', field=name))
234 def _process_intrinsic_functions(self):
235 """Process intrinsic functions
237 Current implementation processes functions within node template
238 properties, requirements, interfaces inputs and template outputs.
240 if hasattr(self, 'nodetemplates'):
241 for node_template in self.nodetemplates:
242 for prop in node_template.get_properties_objects():
243 prop.value = functions.get_function(self,
246 for interface in node_template.interfaces:
248 for name, value in interface.inputs.items():
249 interface.inputs[name] = functions.get_function(
253 if node_template.requirements:
254 for req in node_template.requirements:
256 for req_name, req_item in req.items():
257 if isinstance(req_item, dict):
258 rel = req_item.get('relationship')
260 if rel and 'properties' in rel:
261 for key, value in rel['properties'].items():
262 rel['properties'][key] = \
263 functions.get_function(self,
266 if node_template.get_capabilities_objects():
267 for cap in node_template.get_capabilities_objects():
268 if cap.get_properties_objects():
269 for prop in cap.get_properties_objects():
270 propvalue = functions.get_function(
274 if isinstance(propvalue, functions.GetInput):
275 propvalue = propvalue.result()
276 for p, v in cap._properties.items():
278 cap._properties[p] = propvalue
279 for rel, node in node_template.relationships.items():
280 rel_tpls = node.relationship_tpl
282 for rel_tpl in rel_tpls:
283 for interface in rel_tpl.interfaces:
286 interface.inputs.items():
287 interface.inputs[name] = \
288 functions.get_function(self,
291 for output in self.outputs:
292 func = functions.get_function(self, self.outputs, output.value)
293 if isinstance(func, functions.GetAttribute):
294 output.attrs[output.VALUE] = func
297 def get_sub_mapping_node_type(cls, topology_tpl):
298 if topology_tpl and isinstance(topology_tpl, dict):
299 submap_tpl = topology_tpl.get(SUBSTITUION_MAPPINGS)
300 return Substitution_mappings.get_node_type(submap_tpl)