a64c56127d52265a65fc5f6dbe3eaefe6f3a01e0
[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 toscaparser.utils import validateutils
29 from org.openecomp.sdc.toscaparser.jython import JyTopologyTemplate
30
31
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')
39
40 log = logging.getLogger("tosca.model")
41
42
43 class TopologyTemplate(JyTopologyTemplate):
44
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):
49         self.tpl = template
50         self.sub_mapped_node_template = sub_mapped_node_template
51         if self.tpl:
52             self.meta_data = None
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()
71             
72     def getJyDescription(self):
73         return self.description  
74             
75     def getJyNodeTemplates(self):
76         return self.nodetemplates       
77             
78     def getJyInputs(self):
79         return self.inputs       
80             
81     def getJyGroups(self):
82         return self.groups       
83             
84     def getJySubstitutionMappings(self):
85         return self.substitution_mappings       
86             
87     def getJyMetadata(self):
88         return self.meta_data       
89
90     def _inputs(self):
91         inputs = []
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])
96             else:
97                 default = input.default
98                 if 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)
105
106             inputs.append(input)
107         return inputs
108
109     def _nodetemplates(self):
110         nodetemplates = []
111         tpls = self._tpl_nodetemplates()
112         if tpls:
113             for name in tpls:
114                 tpl = NodeTemplate(name, tpls, self.custom_defs,
115                                    self.relationship_templates,
116                                    self.rel_types)
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)))):
121                     tpl.validate(self)
122                     nodetemplates.append(tpl)
123         return nodetemplates
124
125     def _relationship_templates(self):
126         rel_templates = []
127         tpls = self._tpl_relationship_templates()
128         for name in tpls:
129             tpl = RelationshipTemplate(tpls[name], name, self.custom_defs)
130             rel_templates.append(tpl)
131         return rel_templates
132
133     def _outputs(self):
134         outputs = []
135         for name, attrs in self._tpl_outputs().items():
136             output = Output(name, attrs)
137             output.validate()
138             outputs.append(output)
139         return outputs
140
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,
146                                         self.nodetemplates,
147                                         self.inputs,
148                                         self.outputs,
149                                         self.groups, #ATT
150                                         self.sub_mapped_node_template,
151                                         self.custom_defs)
152
153     def _policies(self):
154         policies = []
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:
159                     target_objects = []
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,
167                                        self.custom_defs)
168                     policies.append(policyObj)
169         return policies
170
171     def _groups(self):
172         groups = []
173         member_nodes = None
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))
184                 else:
185                     member_nodes = self._get_group_members(member_names)
186             group = Group(group_name, group_tpl,
187                           member_nodes,
188                           self.custom_defs)
189             groups.append(group)
190         return groups
191
192     def _get_group_members(self, member_names):
193         member_nodes = []
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)
199         return member_nodes
200
201     def _get_policy_groups(self, member_names):
202         member_groups = []
203         for member in member_names:
204             for group in self.groups:
205                 if group.name == member:
206                     member_groups.append(group)
207         return member_groups
208
209     def _validate_group_members(self, members):
210         node_names = []
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))
219
220     # topology template can act like node template
221     # it is exposed by substitution_mappings.
222     def nodetype(self):
223         return self.substitution_mappings.node_type \
224             if self.substitution_mappings else None
225
226     def capabilities(self):
227         return self.substitution_mappings.capabilities \
228             if self.substitution_mappings else None
229
230     def requirements(self):
231         return self.substitution_mappings.requirements \
232             if self.substitution_mappings else None
233
234     def _tpl_description(self):
235         description = self.tpl.get(DESCRIPTION)
236         if description:
237             return description.rstrip()
238
239     def _tpl_inputs(self):
240         return self.tpl.get(INPUTS) or {}
241
242     def _tpl_nodetemplates(self):
243         return self.tpl.get(NODE_TEMPLATES)
244
245     def _tpl_relationship_templates(self):
246         return self.tpl.get(RELATIONSHIP_TEMPLATES) or {}
247
248     def _tpl_outputs(self):
249         return self.tpl.get(OUTPUTS) or {}
250
251     def _tpl_substitution_mappings(self):
252         return self.tpl.get(SUBSTITUION_MAPPINGS) or {}
253
254     def _tpl_groups(self):
255         return self.tpl.get(GROUPS) or {}
256
257     def _tpl_policies(self):
258         return self.tpl.get(POLICIES) or {}
259
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))
265
266     def _process_intrinsic_functions(self):
267         """Process intrinsic functions
268
269         Current implementation processes functions within node template
270         properties, requirements, interfaces inputs and template outputs.
271         """
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,
276                                                         node_template,
277                                                         prop.value)
278                 for interface in node_template.interfaces:
279                     if interface.inputs:
280                         for name, value in interface.inputs.items():
281                             interface.inputs[name] = functions.get_function(
282                                 self,
283                                 node_template,
284                                 value)
285                 if node_template.requirements and \
286                    isinstance(node_template.requirements, list):
287                     for req in node_template.requirements:
288                         rel = req
289                         for req_name, req_item in req.items():
290                             if isinstance(req_item, dict):
291                                 rel = req_item.get('relationship')
292                                 break
293                         if rel and 'properties' in rel:
294                             for key, value in rel['properties'].items():
295                                 rel['properties'][key] = \
296                                     functions.get_function(self,
297                                                            req,
298                                                            value)
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(
304                                     self,
305                                     node_template,
306                                     prop.value)
307                                 if isinstance(propvalue, functions.GetInput):
308                                     propvalue = propvalue.result()
309                                     for p, v in cap._properties.items():
310                                         if p == prop.name:
311                                             cap._properties[p] = propvalue
312                 for rel, node in node_template.relationships.items():
313                     rel_tpls = node.relationship_tpl
314                     if rel_tpls:
315                         for rel_tpl in rel_tpls:
316                             for interface in rel_tpl.interfaces:
317                                 if interface.inputs:
318                                     for name, value in \
319                                             interface.inputs.items():
320                                         interface.inputs[name] = \
321                                             functions.get_function(self,
322                                                                    rel_tpl,
323                                                                    value)
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
328
329     @classmethod
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)