23f544a7a3140e6d024787db5eb7ea365b0b9ce4
[sdc/sdc-distribution-client.git] /
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
4 #
5 #         http://www.apache.org/licenses/LICENSE-2.0
6 #
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
11 #    under the License.
12
13
14 import logging
15
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 org.openecomp.sdc.toscaparser.jython import JyTopologyTemplate
29
30
31 # Topology template key names
32 SECTIONS = (DESCRIPTION, INPUTS, NODE_TEMPLATES,
33             RELATIONSHIP_TEMPLATES, OUTPUTS, GROUPS,
34             SUBSTITUION_MAPPINGS, POLICIES) = \
35            ('description', 'inputs', 'node_templates',
36             'relationship_templates', 'outputs', 'groups',
37             'substitution_mappings', 'policies')
38
39 log = logging.getLogger("tosca.model")
40
41
42 class TopologyTemplate(JyTopologyTemplate):
43
44     '''Load the template data.'''
45     def __init__(self, template, custom_defs,
46                  rel_types=None, parsed_params=None,
47                  sub_mapped_node_template=None):
48         self.tpl = template
49         self.sub_mapped_node_template = sub_mapped_node_template
50         if self.tpl:
51             self.custom_defs = custom_defs
52             self.rel_types = rel_types
53             self.parsed_params = parsed_params
54             self._validate_field()
55             self.description = self._tpl_description()
56             self.inputs = self._inputs()
57             self.relationship_templates = self._relationship_templates()
58             self.nodetemplates = self._nodetemplates()
59             self.outputs = self._outputs()
60             if hasattr(self, 'nodetemplates'):
61                 self.graph = ToscaGraph(self.nodetemplates)
62             self.groups = self._groups()
63             self.policies = self._policies()
64             self._process_intrinsic_functions()
65             self.substitution_mappings = self._substitution_mappings()
66             
67     def getJyDescription(self):
68         return self.description  
69             
70     def getJyNodeTemplates(self):
71         return self.nodetemplates       
72             
73     def getJyInputs(self):
74         return self.inputs       
75             
76     def getJyGroups(self):
77         return self.groups       
78             
79     def getJySubstitutionMappings(self):
80         return self.substitution_mappings       
81
82     def _inputs(self):
83         inputs = []
84         for name, attrs in self._tpl_inputs().items():
85             input = Input(name, attrs)
86             if self.parsed_params and name in self.parsed_params:
87                 input.validate(self.parsed_params[name])
88             else:
89                 default = input.default
90                 if default:
91                     input.validate(default)
92             if (self.parsed_params and input.name not in self.parsed_params
93                 or self.parsed_params is None) and input.required \
94                     and input.default is None:
95                 log.warning(_('The required parameter %s '
96                               'is not provided') % input.name)
97
98             inputs.append(input)
99         return inputs
100
101     def _nodetemplates(self):
102         nodetemplates = []
103         tpls = self._tpl_nodetemplates()
104         if tpls:
105             for name in tpls:
106                 tpl = NodeTemplate(name, tpls, self.custom_defs,
107                                    self.relationship_templates,
108                                    self.rel_types)
109                 if (tpl.type_definition and
110                     (tpl.type in tpl.type_definition.TOSCA_DEF or
111                      (tpl.type not in tpl.type_definition.TOSCA_DEF and
112                       bool(tpl.custom_def)))):
113                     tpl.validate(self)
114                     nodetemplates.append(tpl)
115         return nodetemplates
116
117     def _relationship_templates(self):
118         rel_templates = []
119         tpls = self._tpl_relationship_templates()
120         for name in tpls:
121             tpl = RelationshipTemplate(tpls[name], name, self.custom_defs)
122             rel_templates.append(tpl)
123         return rel_templates
124
125     def _outputs(self):
126         outputs = []
127         for name, attrs in self._tpl_outputs().items():
128             output = Output(name, attrs)
129             output.validate()
130             outputs.append(output)
131         return outputs
132
133     def _substitution_mappings(self):
134         tpl_substitution_mapping = self._tpl_substitution_mappings()
135         # if tpl_substitution_mapping and self.sub_mapped_node_template:
136         if tpl_substitution_mapping:
137             return SubstitutionMappings(tpl_substitution_mapping,
138                                         self.nodetemplates,
139                                         self.inputs,
140                                         self.outputs,
141                                         self.sub_mapped_node_template,
142                                         self.custom_defs)
143
144     def _policies(self):
145         policies = []
146         for policy in self._tpl_policies():
147             for policy_name, policy_tpl in policy.items():
148                 target_list = policy_tpl.get('targets')
149                 if target_list and len(target_list) >= 1:
150                     target_objects = []
151                     targets_type = "groups"
152                     target_objects = self._get_policy_groups(target_list)
153                     if not target_objects:
154                         targets_type = "node_templates"
155                         target_objects = self._get_group_members(target_list)
156                     policyObj = Policy(policy_name, policy_tpl,
157                                        target_objects, targets_type,
158                                        self.custom_defs)
159                     policies.append(policyObj)
160         return policies
161
162     def _groups(self):
163         groups = []
164         member_nodes = None
165         for group_name, group_tpl in self._tpl_groups().items():
166             member_names = group_tpl.get('members')
167             if member_names is not None:
168                 DataEntity.validate_datatype('list', member_names)
169                 if len(member_names) < 1 or \
170                         len(member_names) != len(set(member_names)):
171                     exception.ExceptionCollector.appendException(
172                         exception.InvalidGroupTargetException(
173                             message=_('Member nodes "%s" should be >= 1 '
174                                       'and not repeated') % member_names))
175                 else:
176                     member_nodes = self._get_group_members(member_names)
177             group = Group(group_name, group_tpl,
178                           member_nodes,
179                           self.custom_defs)
180             groups.append(group)
181         return groups
182
183     def _get_group_members(self, member_names):
184         member_nodes = []
185         self._validate_group_members(member_names)
186         for member in member_names:
187             for node in self.nodetemplates:
188                 if node.name == member:
189                     member_nodes.append(node)
190         return member_nodes
191
192     def _get_policy_groups(self, member_names):
193         member_groups = []
194         for member in member_names:
195             for group in self.groups:
196                 if group.name == member:
197                     member_groups.append(group)
198         return member_groups
199
200     def _validate_group_members(self, members):
201         node_names = []
202         for node in self.nodetemplates:
203             node_names.append(node.name)
204         for member in members:
205             if member not in node_names:
206                 exception.ExceptionCollector.appendException(
207                     exception.InvalidGroupTargetException(
208                         message=_('Target member "%s" is not found in '
209                                   'node_templates') % member))
210
211     # topology template can act like node template
212     # it is exposed by substitution_mappings.
213     def nodetype(self):
214         return self.substitution_mappings.node_type \
215             if self.substitution_mappings else None
216
217     def capabilities(self):
218         return self.substitution_mappings.capabilities \
219             if self.substitution_mappings else None
220
221     def requirements(self):
222         return self.substitution_mappings.requirements \
223             if self.substitution_mappings else None
224
225     def _tpl_description(self):
226         description = self.tpl.get(DESCRIPTION)
227         if description:
228             return description.rstrip()
229
230     def _tpl_inputs(self):
231         return self.tpl.get(INPUTS) or {}
232
233     def _tpl_nodetemplates(self):
234         return self.tpl.get(NODE_TEMPLATES)
235
236     def _tpl_relationship_templates(self):
237         return self.tpl.get(RELATIONSHIP_TEMPLATES) or {}
238
239     def _tpl_outputs(self):
240         return self.tpl.get(OUTPUTS) or {}
241
242     def _tpl_substitution_mappings(self):
243         return self.tpl.get(SUBSTITUION_MAPPINGS) or {}
244
245     def _tpl_groups(self):
246         return self.tpl.get(GROUPS) or {}
247
248     def _tpl_policies(self):
249         return self.tpl.get(POLICIES) or {}
250
251     def _validate_field(self):
252         for name in self.tpl:
253             if name not in SECTIONS:
254                 exception.ExceptionCollector.appendException(
255                     exception.UnknownFieldError(what='Template', field=name))
256
257     def _process_intrinsic_functions(self):
258         """Process intrinsic functions
259
260         Current implementation processes functions within node template
261         properties, requirements, interfaces inputs and template outputs.
262         """
263         if hasattr(self, 'nodetemplates'):
264             for node_template in self.nodetemplates:
265                 for prop in node_template.get_properties_objects():
266                     prop.value = functions.get_function(self,
267                                                         node_template,
268                                                         prop.value)
269                 for interface in node_template.interfaces:
270                     if interface.inputs:
271                         for name, value in interface.inputs.items():
272                             interface.inputs[name] = functions.get_function(
273                                 self,
274                                 node_template,
275                                 value)
276                 if node_template.requirements and \
277                    isinstance(node_template.requirements, list):
278                     for req in node_template.requirements:
279                         rel = req
280                         for req_name, req_item in req.items():
281                             if isinstance(req_item, dict):
282                                 rel = req_item.get('relationship')
283                                 break
284                         if rel and 'properties' in rel:
285                             for key, value in rel['properties'].items():
286                                 rel['properties'][key] = \
287                                     functions.get_function(self,
288                                                            req,
289                                                            value)
290                 if node_template.get_capabilities_objects():
291                     for cap in node_template.get_capabilities_objects():
292                         if cap.get_properties_objects():
293                             for prop in cap.get_properties_objects():
294                                 propvalue = functions.get_function(
295                                     self,
296                                     node_template,
297                                     prop.value)
298                                 if isinstance(propvalue, functions.GetInput):
299                                     propvalue = propvalue.result()
300                                     for p, v in cap._properties.items():
301                                         if p == prop.name:
302                                             cap._properties[p] = propvalue
303                 for rel, node in node_template.relationships.items():
304                     rel_tpls = node.relationship_tpl
305                     if rel_tpls:
306                         for rel_tpl in rel_tpls:
307                             for interface in rel_tpl.interfaces:
308                                 if interface.inputs:
309                                     for name, value in \
310                                             interface.inputs.items():
311                                         interface.inputs[name] = \
312                                             functions.get_function(self,
313                                                                    rel_tpl,
314                                                                    value)
315         for output in self.outputs:
316             func = functions.get_function(self, self.outputs, output.value)
317             if isinstance(func, functions.GetAttribute):
318                 output.attrs[output.VALUE] = func
319
320     @classmethod
321     def get_sub_mapping_node_type(cls, topology_tpl):
322         if topology_tpl and isinstance(topology_tpl, dict):
323             submap_tpl = topology_tpl.get(SUBSTITUION_MAPPINGS)
324             return SubstitutionMappings.get_node_type(submap_tpl)