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,
155 for policy in self._tpl_policies():
156 for policy_name, policy_tpl in policy.items():
157 target_list = policy_tpl.get('targets')
158 if target_list and len(target_list) >= 1:
160 targets_type = "groups"
161 target_objects = self._get_policy_groups(target_list)
162 if not target_objects:
163 targets_type = "node_templates"
164 target_objects = self._get_group_members(target_list)
165 policyObj = Policy(policy_name, policy_tpl,
166 target_objects, targets_type,
168 policies.append(policyObj)
174 for group_name, group_tpl in self._tpl_groups().items():
175 member_names = group_tpl.get('members')
176 if member_names is not None:
177 DataEntity.validate_datatype('list', member_names)
178 if len(member_names) < 1 or \
179 len(member_names) != len(set(member_names)):
180 exception.ExceptionCollector.appendException(
181 exception.InvalidGroupTargetException(
182 message=_('Member nodes "%s" should be >= 1 '
183 'and not repeated') % member_names))
185 member_nodes = self._get_group_members(member_names)
186 group = Group(group_name, group_tpl,
192 def _get_group_members(self, member_names):
194 self._validate_group_members(member_names)
195 for member in member_names:
196 for node in self.nodetemplates:
197 if node.name == member:
198 member_nodes.append(node)
201 def _get_policy_groups(self, member_names):
203 for member in member_names:
204 for group in self.groups:
205 if group.name == member:
206 member_groups.append(group)
209 def _validate_group_members(self, members):
211 for node in self.nodetemplates:
212 node_names.append(node.name)
213 for member in members:
214 if member not in node_names:
215 exception.ExceptionCollector.appendException(
216 exception.InvalidGroupTargetException(
217 message=_('Target member "%s" is not found in '
218 'node_templates') % member))
220 # topology template can act like node template
221 # it is exposed by substitution_mappings.
223 return self.substitution_mappings.node_type \
224 if self.substitution_mappings else None
226 def capabilities(self):
227 return self.substitution_mappings.capabilities \
228 if self.substitution_mappings else None
230 def requirements(self):
231 return self.substitution_mappings.requirements \
232 if self.substitution_mappings else None
234 def _tpl_description(self):
235 description = self.tpl.get(DESCRIPTION)
237 return description.rstrip()
239 def _tpl_inputs(self):
240 return self.tpl.get(INPUTS) or {}
242 def _tpl_nodetemplates(self):
243 return self.tpl.get(NODE_TEMPLATES)
245 def _tpl_relationship_templates(self):
246 return self.tpl.get(RELATIONSHIP_TEMPLATES) or {}
248 def _tpl_outputs(self):
249 return self.tpl.get(OUTPUTS) or {}
251 def _tpl_substitution_mappings(self):
252 return self.tpl.get(SUBSTITUION_MAPPINGS) or {}
254 def _tpl_groups(self):
255 return self.tpl.get(GROUPS) or {}
257 def _tpl_policies(self):
258 return self.tpl.get(POLICIES) or {}
260 def _validate_field(self):
261 for name in self.tpl:
262 if name not in SECTIONS:
263 exception.ExceptionCollector.appendException(
264 exception.UnknownFieldError(what='Template', field=name))
266 def _process_intrinsic_functions(self):
267 """Process intrinsic functions
269 Current implementation processes functions within node template
270 properties, requirements, interfaces inputs and template outputs.
272 if hasattr(self, 'nodetemplates'):
273 for node_template in self.nodetemplates:
274 for prop in node_template.get_properties_objects():
275 prop.value = functions.get_function(self,
278 for interface in node_template.interfaces:
280 for name, value in interface.inputs.items():
281 interface.inputs[name] = functions.get_function(
285 if node_template.requirements and \
286 isinstance(node_template.requirements, list):
287 for req in node_template.requirements:
289 for req_name, req_item in req.items():
290 if isinstance(req_item, dict):
291 rel = req_item.get('relationship')
293 if rel and 'properties' in rel:
294 for key, value in rel['properties'].items():
295 rel['properties'][key] = \
296 functions.get_function(self,
299 if node_template.get_capabilities_objects():
300 for cap in node_template.get_capabilities_objects():
301 if cap.get_properties_objects():
302 for prop in cap.get_properties_objects():
303 propvalue = functions.get_function(
307 if isinstance(propvalue, functions.GetInput):
308 propvalue = propvalue.result()
309 for p, v in cap._properties.items():
311 cap._properties[p] = propvalue
312 for rel, node in node_template.relationships.items():
313 rel_tpls = node.relationship_tpl
315 for rel_tpl in rel_tpls:
316 for interface in rel_tpl.interfaces:
319 interface.inputs.items():
320 interface.inputs[name] = \
321 functions.get_function(self,
324 for output in self.outputs:
325 func = functions.get_function(self, self.outputs, output.value)
326 if isinstance(func, functions.GetAttribute):
327 output.attrs[output.VALUE] = func
330 def get_sub_mapping_node_type(cls, topology_tpl):
331 if topology_tpl and isinstance(topology_tpl, dict):
332 submap_tpl = topology_tpl.get(SUBSTITUION_MAPPINGS)
333 return SubstitutionMappings.get_node_type(submap_tpl)