d314e00ae245b0b4194d3b5d3e24c0882d67b06a
[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                                         self.meta_data)
153
154     def _policies(self):
155         policies = []
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:
160                     target_objects = []
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,
168                                        self.custom_defs)
169                     policies.append(policyObj)
170         return policies
171
172     def _groups(self):
173         groups = []
174         member_nodes = None
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))
185                 else:
186                     member_nodes = self._get_group_members(member_names)
187             group = Group(group_name, group_tpl,
188                           member_nodes,
189                           self.custom_defs)
190             groups.append(group)
191         return groups
192
193     def _get_group_members(self, member_names):
194         member_nodes = []
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)
200         return member_nodes
201
202     def _get_policy_groups(self, member_names):
203         member_groups = []
204         for member in member_names:
205             for group in self.groups:
206                 if group.name == member:
207                     member_groups.append(group)
208         return member_groups
209
210     def _validate_group_members(self, members):
211         node_names = []
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))
220
221     # topology template can act like node template
222     # it is exposed by substitution_mappings.
223     def nodetype(self):
224         return self.substitution_mappings.node_type \
225             if self.substitution_mappings else None
226
227     def capabilities(self):
228         return self.substitution_mappings.capabilities \
229             if self.substitution_mappings else None
230
231     def requirements(self):
232         return self.substitution_mappings.requirements \
233             if self.substitution_mappings else None
234
235     def _tpl_description(self):
236         description = self.tpl.get(DESCRIPTION)
237         if description:
238             return description.rstrip()
239
240     def _tpl_inputs(self):
241         return self.tpl.get(INPUTS) or {}
242
243     def _tpl_nodetemplates(self):
244         return self.tpl.get(NODE_TEMPLATES)
245
246     def _tpl_relationship_templates(self):
247         return self.tpl.get(RELATIONSHIP_TEMPLATES) or {}
248
249     def _tpl_outputs(self):
250         return self.tpl.get(OUTPUTS) or {}
251
252     def _tpl_substitution_mappings(self):
253         return self.tpl.get(SUBSTITUION_MAPPINGS) or {}
254
255     def _tpl_groups(self):
256         return self.tpl.get(GROUPS) or {}
257
258     def _tpl_policies(self):
259         return self.tpl.get(POLICIES) or {}
260
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))
266
267     def _process_intrinsic_functions(self):
268         """Process intrinsic functions
269
270         Current implementation processes functions within node template
271         properties, requirements, interfaces inputs and template outputs.
272         """
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,
277                                                         node_template,
278                                                         prop.value)
279                 for interface in node_template.interfaces:
280                     if interface.inputs:
281                         for name, value in interface.inputs.items():
282                             interface.inputs[name] = functions.get_function(
283                                 self,
284                                 node_template,
285                                 value)
286                 if node_template.requirements and \
287                    isinstance(node_template.requirements, list):
288                     for req in node_template.requirements:
289                         rel = req
290                         for req_name, req_item in req.items():
291                             if isinstance(req_item, dict):
292                                 rel = req_item.get('relationship')
293                                 break
294                         if rel and 'properties' in rel:
295                             for key, value in rel['properties'].items():
296                                 rel['properties'][key] = \
297                                     functions.get_function(self,
298                                                            req,
299                                                            value)
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(
305                                     self,
306                                     node_template,
307                                     prop.value)
308                                 if isinstance(propvalue, functions.GetInput):
309                                     propvalue = propvalue.result()
310                                     for p, v in cap._properties.items():
311                                         if p == prop.name:
312                                             cap._properties[p] = propvalue
313                 for rel, node in node_template.relationships.items():
314                     rel_tpls = node.relationship_tpl
315                     if rel_tpls:
316                         for rel_tpl in rel_tpls:
317                             for interface in rel_tpl.interfaces:
318                                 if interface.inputs:
319                                     for name, value in \
320                                             interface.inputs.items():
321                                         interface.inputs[name] = \
322                                             functions.get_function(self,
323                                                                    rel_tpl,
324                                                                    value)
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
329
330     @classmethod
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)