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,
149 self.sub_mapped_node_template,
154 for policy in self._tpl_policies():
155 for policy_name, policy_tpl in policy.items():
156 target_list = policy_tpl.get('targets')
157 if target_list and len(target_list) >= 1:
159 targets_type = "groups"
160 target_objects = self._get_policy_groups(target_list)
161 if not target_objects:
162 targets_type = "node_templates"
163 target_objects = self._get_group_members(target_list)
164 policyObj = Policy(policy_name, policy_tpl,
165 target_objects, targets_type,
167 policies.append(policyObj)
173 for group_name, group_tpl in self._tpl_groups().items():
174 member_names = group_tpl.get('members')
175 if member_names is not None:
176 DataEntity.validate_datatype('list', member_names)
177 if len(member_names) < 1 or \
178 len(member_names) != len(set(member_names)):
179 exception.ExceptionCollector.appendException(
180 exception.InvalidGroupTargetException(
181 message=_('Member nodes "%s" should be >= 1 '
182 'and not repeated') % member_names))
184 member_nodes = self._get_group_members(member_names)
185 group = Group(group_name, group_tpl,
191 def _get_group_members(self, member_names):
193 self._validate_group_members(member_names)
194 for member in member_names:
195 for node in self.nodetemplates:
196 if node.name == member:
197 member_nodes.append(node)
200 def _get_policy_groups(self, member_names):
202 for member in member_names:
203 for group in self.groups:
204 if group.name == member:
205 member_groups.append(group)
208 def _validate_group_members(self, members):
210 for node in self.nodetemplates:
211 node_names.append(node.name)
212 for member in members:
213 if member not in node_names:
214 exception.ExceptionCollector.appendException(
215 exception.InvalidGroupTargetException(
216 message=_('Target member "%s" is not found in '
217 'node_templates') % member))
219 # topology template can act like node template
220 # it is exposed by substitution_mappings.
222 return self.substitution_mappings.node_type \
223 if self.substitution_mappings else None
225 def capabilities(self):
226 return self.substitution_mappings.capabilities \
227 if self.substitution_mappings else None
229 def requirements(self):
230 return self.substitution_mappings.requirements \
231 if self.substitution_mappings else None
233 def _tpl_description(self):
234 description = self.tpl.get(DESCRIPTION)
236 return description.rstrip()
238 def _tpl_inputs(self):
239 return self.tpl.get(INPUTS) or {}
241 def _tpl_nodetemplates(self):
242 return self.tpl.get(NODE_TEMPLATES)
244 def _tpl_relationship_templates(self):
245 return self.tpl.get(RELATIONSHIP_TEMPLATES) or {}
247 def _tpl_outputs(self):
248 return self.tpl.get(OUTPUTS) or {}
250 def _tpl_substitution_mappings(self):
251 return self.tpl.get(SUBSTITUION_MAPPINGS) or {}
253 def _tpl_groups(self):
254 return self.tpl.get(GROUPS) or {}
256 def _tpl_policies(self):
257 return self.tpl.get(POLICIES) or {}
259 def _validate_field(self):
260 for name in self.tpl:
261 if name not in SECTIONS:
262 exception.ExceptionCollector.appendException(
263 exception.UnknownFieldError(what='Template', field=name))
265 def _process_intrinsic_functions(self):
266 """Process intrinsic functions
268 Current implementation processes functions within node template
269 properties, requirements, interfaces inputs and template outputs.
271 if hasattr(self, 'nodetemplates'):
272 for node_template in self.nodetemplates:
273 for prop in node_template.get_properties_objects():
274 prop.value = functions.get_function(self,
277 for interface in node_template.interfaces:
279 for name, value in interface.inputs.items():
280 interface.inputs[name] = functions.get_function(
284 if node_template.requirements and \
285 isinstance(node_template.requirements, list):
286 for req in node_template.requirements:
288 for req_name, req_item in req.items():
289 if isinstance(req_item, dict):
290 rel = req_item.get('relationship')
292 if rel and 'properties' in rel:
293 for key, value in rel['properties'].items():
294 rel['properties'][key] = \
295 functions.get_function(self,
298 if node_template.get_capabilities_objects():
299 for cap in node_template.get_capabilities_objects():
300 if cap.get_properties_objects():
301 for prop in cap.get_properties_objects():
302 propvalue = functions.get_function(
306 if isinstance(propvalue, functions.GetInput):
307 propvalue = propvalue.result()
308 for p, v in cap._properties.items():
310 cap._properties[p] = propvalue
311 for rel, node in node_template.relationships.items():
312 rel_tpls = node.relationship_tpl
314 for rel_tpl in rel_tpls:
315 for interface in rel_tpl.interfaces:
318 interface.inputs.items():
319 interface.inputs[name] = \
320 functions.get_function(self,
323 for output in self.outputs:
324 func = functions.get_function(self, self.outputs, output.value)
325 if isinstance(func, functions.GetAttribute):
326 output.attrs[output.VALUE] = func
329 def get_sub_mapping_node_type(cls, topology_tpl):
330 if topology_tpl and isinstance(topology_tpl, dict):
331 submap_tpl = topology_tpl.get(SUBSTITUION_MAPPINGS)
332 return SubstitutionMappings.get_node_type(submap_tpl)