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 SubstitutionMappings
26 from toscaparser.tpl_relationship_graph import ToscaGraph
27 from toscaparser.utils.gettextutils import _
28 from toscaparser.utils import validateutils
29 from org.openecomp.sdc.toscaparser.jython import JyTopologyTemplate
32 # Topology template key names
33 SECTIONS = (DESCRIPTION, INPUTS, NODE_TEMPLATES,
34 RELATIONSHIP_TEMPLATES, OUTPUTS, GROUPS,
35 SUBSTITUION_MAPPINGS, POLICIES, METADATA) = \
36 ('description', 'inputs', 'node_templates',
37 'relationship_templates', 'outputs', 'groups',
38 'substitution_mappings', 'policies', 'metadata')
40 log = logging.getLogger("tosca.model")
43 class TopologyTemplate(JyTopologyTemplate):
45 '''Load the template data.'''
46 def __init__(self, template, custom_defs,
47 rel_types=None, parsed_params=None,
48 sub_mapped_node_template=None):
50 self.sub_mapped_node_template = sub_mapped_node_template
53 if METADATA in self.tpl:
54 self.meta_data = self.tpl.get(METADATA)
55 validateutils.validate_map(self.meta_data)
56 self.custom_defs = custom_defs
57 self.rel_types = rel_types
58 self.parsed_params = parsed_params
59 self._validate_field()
60 self.description = self._tpl_description()
61 self.inputs = self._inputs()
62 self.relationship_templates = self._relationship_templates()
63 self.nodetemplates = self._nodetemplates()
64 self.outputs = self._outputs()
65 if hasattr(self, 'nodetemplates'):
66 self.graph = ToscaGraph(self.nodetemplates)
67 self.groups = self._groups()
68 self.policies = self._policies()
69 self._process_intrinsic_functions()
70 self.substitution_mappings = self._substitution_mappings()
72 def getJyDescription(self):
73 return self.description
75 def getJyNodeTemplates(self):
76 return self.nodetemplates
78 def getJyInputs(self):
81 def getJyGroups(self):
84 def getJySubstitutionMappings(self):
85 return self.substitution_mappings
87 def getJyMetadata(self):
92 for name, attrs in self._tpl_inputs().items():
93 input = Input(name, attrs)
94 if self.parsed_params and name in self.parsed_params:
95 input.validate(self.parsed_params[name])
97 default = input.default
99 input.validate(default)
100 if (self.parsed_params and input.name not in self.parsed_params
101 or self.parsed_params is None) and input.required \
102 and input.default is None:
103 log.warning(_('The required parameter %s '
104 'is not provided') % input.name)
109 def _nodetemplates(self):
111 tpls = self._tpl_nodetemplates()
114 tpl = NodeTemplate(name, tpls, self.custom_defs,
115 self.relationship_templates,
117 if (tpl.type_definition and
118 (tpl.type in tpl.type_definition.TOSCA_DEF or
119 (tpl.type not in tpl.type_definition.TOSCA_DEF and
120 bool(tpl.custom_def)))):
122 nodetemplates.append(tpl)
125 def _relationship_templates(self):
127 tpls = self._tpl_relationship_templates()
129 tpl = RelationshipTemplate(tpls[name], name, self.custom_defs)
130 rel_templates.append(tpl)
135 for name, attrs in self._tpl_outputs().items():
136 output = Output(name, attrs)
138 outputs.append(output)
141 def _substitution_mappings(self):
142 tpl_substitution_mapping = self._tpl_substitution_mappings()
143 # if tpl_substitution_mapping and self.sub_mapped_node_template:
144 if tpl_substitution_mapping:
145 return SubstitutionMappings(tpl_substitution_mapping,
150 self.sub_mapped_node_template,
156 for policy in self._tpl_policies():
157 for policy_name, policy_tpl in policy.items():
158 target_list = policy_tpl.get('targets')
159 if target_list and len(target_list) >= 1:
161 targets_type = "groups"
162 target_objects = self._get_policy_groups(target_list)
163 if not target_objects:
164 targets_type = "node_templates"
165 target_objects = self._get_group_members(target_list)
166 policyObj = Policy(policy_name, policy_tpl,
167 target_objects, targets_type,
169 policies.append(policyObj)
175 for group_name, group_tpl in self._tpl_groups().items():
176 member_names = group_tpl.get('members')
177 if member_names is not None:
178 DataEntity.validate_datatype('list', member_names)
179 if len(member_names) < 1 or \
180 len(member_names) != len(set(member_names)):
181 exception.ExceptionCollector.appendException(
182 exception.InvalidGroupTargetException(
183 message=_('Member nodes "%s" should be >= 1 '
184 'and not repeated') % member_names))
186 member_nodes = self._get_group_members(member_names)
187 group = Group(group_name, group_tpl,
193 def _get_group_members(self, member_names):
195 self._validate_group_members(member_names)
196 for member in member_names:
197 for node in self.nodetemplates:
198 if node.name == member:
199 member_nodes.append(node)
202 def _get_policy_groups(self, member_names):
204 for member in member_names:
205 for group in self.groups:
206 if group.name == member:
207 member_groups.append(group)
210 def _validate_group_members(self, members):
212 for node in self.nodetemplates:
213 node_names.append(node.name)
214 for member in members:
215 if member not in node_names:
216 exception.ExceptionCollector.appendException(
217 exception.InvalidGroupTargetException(
218 message=_('Target member "%s" is not found in '
219 'node_templates') % member))
221 # topology template can act like node template
222 # it is exposed by substitution_mappings.
224 return self.substitution_mappings.node_type \
225 if self.substitution_mappings else None
227 def capabilities(self):
228 return self.substitution_mappings.capabilities \
229 if self.substitution_mappings else None
231 def requirements(self):
232 return self.substitution_mappings.requirements \
233 if self.substitution_mappings else None
235 def _tpl_description(self):
236 description = self.tpl.get(DESCRIPTION)
238 return description.rstrip()
240 def _tpl_inputs(self):
241 return self.tpl.get(INPUTS) or {}
243 def _tpl_nodetemplates(self):
244 return self.tpl.get(NODE_TEMPLATES)
246 def _tpl_relationship_templates(self):
247 return self.tpl.get(RELATIONSHIP_TEMPLATES) or {}
249 def _tpl_outputs(self):
250 return self.tpl.get(OUTPUTS) or {}
252 def _tpl_substitution_mappings(self):
253 return self.tpl.get(SUBSTITUION_MAPPINGS) or {}
255 def _tpl_groups(self):
256 return self.tpl.get(GROUPS) or {}
258 def _tpl_policies(self):
259 return self.tpl.get(POLICIES) or {}
261 def _validate_field(self):
262 for name in self.tpl:
263 if name not in SECTIONS:
264 exception.ExceptionCollector.appendException(
265 exception.UnknownFieldError(what='Template', field=name))
267 def _process_intrinsic_functions(self):
268 """Process intrinsic functions
270 Current implementation processes functions within node template
271 properties, requirements, interfaces inputs and template outputs.
273 if hasattr(self, 'nodetemplates'):
274 for node_template in self.nodetemplates:
275 for prop in node_template.get_properties_objects():
276 prop.value = functions.get_function(self,
279 for interface in node_template.interfaces:
281 for name, value in interface.inputs.items():
282 interface.inputs[name] = functions.get_function(
286 if node_template.requirements and \
287 isinstance(node_template.requirements, list):
288 for req in node_template.requirements:
290 for req_name, req_item in req.items():
291 if isinstance(req_item, dict):
292 rel = req_item.get('relationship')
294 if rel and 'properties' in rel:
295 for key, value in rel['properties'].items():
296 rel['properties'][key] = \
297 functions.get_function(self,
300 if node_template.get_capabilities_objects():
301 for cap in node_template.get_capabilities_objects():
302 if cap.get_properties_objects():
303 for prop in cap.get_properties_objects():
304 propvalue = functions.get_function(
308 if isinstance(propvalue, functions.GetInput):
309 propvalue = propvalue.result()
310 for p, v in cap._properties.items():
312 cap._properties[p] = propvalue
313 for rel, node in node_template.relationships.items():
314 rel_tpls = node.relationship_tpl
316 for rel_tpl in rel_tpls:
317 for interface in rel_tpl.interfaces:
320 interface.inputs.items():
321 interface.inputs[name] = \
322 functions.get_function(self,
325 for output in self.outputs:
326 func = functions.get_function(self, self.outputs, output.value)
327 if isinstance(func, functions.GetAttribute):
328 output.attrs[output.VALUE] = func
331 def get_sub_mapping_node_type(cls, topology_tpl):
332 if topology_tpl and isinstance(topology_tpl, dict):
333 submap_tpl = topology_tpl.get(SUBSTITUION_MAPPINGS)
334 return SubstitutionMappings.get_node_type(submap_tpl)