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
15 from toscaparser.common.exception import ExceptionCollector
16 from toscaparser.common.exception import InvalidNodeTypeError
17 from toscaparser.common.exception import MissingDefaultValueError
18 from toscaparser.common.exception import MissingRequiredFieldError
19 from toscaparser.common.exception import MissingRequiredInputError
20 from toscaparser.common.exception import UnknownFieldError
21 from toscaparser.common.exception import UnknownOutputError
22 from toscaparser.elements.nodetype import NodeType
23 from toscaparser.utils.gettextutils import _
24 from org.openecomp.sdc.toscaparser.jython import JySubstitutionMappings
26 log = logging.getLogger('tosca')
29 class SubstitutionMappings(JySubstitutionMappings):
30 '''SubstitutionMappings class declaration
32 SubstitutionMappings exports the topology template as an
33 implementation of a Node type.
36 SECTIONS = (NODE_TYPE, REQUIREMENTS, CAPABILITIES) = \
37 ('node_type', 'requirements', 'capabilities')
39 OPTIONAL_OUTPUTS = ['tosca_id', 'tosca_name', 'state']
41 def __init__(self, sub_mapping_def, nodetemplates, inputs, outputs, groups, #ATT
42 sub_mapped_node_template, custom_defs):
43 self.nodetemplates = nodetemplates
44 self.sub_mapping_def = sub_mapping_def
45 self.inputs = inputs or []
46 self.outputs = outputs or []
47 self.groups = groups or [] #ATT
48 self.sub_mapped_node_template = sub_mapped_node_template
49 self.custom_defs = custom_defs or {}
52 self._capabilities = None
53 self._requirements = None
55 def getJyNodeTemplates(self):
56 return self.nodetemplates
58 def getJyInputs(self):
61 def getJyGroups(self): #ATT
64 def getJyNodeDefinition(self):
65 return self.node_definition
69 if self.sub_mapping_def:
70 return self.sub_mapping_def.get(self.NODE_TYPE)
73 def get_node_type(cls, sub_mapping_def):
74 if isinstance(sub_mapping_def, dict):
75 return sub_mapping_def.get(cls.NODE_TYPE)
79 return self.sub_mapping_def.get(self.NODE_TYPE)
82 def capabilities(self):
83 return self.sub_mapping_def.get(self.CAPABILITIES)
86 def requirements(self):
87 return self.sub_mapping_def.get(self.REQUIREMENTS)
90 def node_definition(self):
91 return NodeType(self.node_type, self.custom_defs)
98 # SubstitutionMapping class syntax validation
99 self._validate_inputs()
100 self._validate_capabilities()
101 self._validate_requirements()
102 self._validate_outputs()
104 def _validate_keys(self):
105 """validate the keys of substitution mappings."""
106 for key in self.sub_mapping_def.keys():
107 if key not in self.SECTIONS:
108 ExceptionCollector.appendException(
109 UnknownFieldError(what=_('SubstitutionMappings'),
112 def _validate_type(self):
113 """validate the node_type of substitution mappings."""
114 node_type = self.sub_mapping_def.get(self.NODE_TYPE)
116 ExceptionCollector.appendException(
117 MissingRequiredFieldError(
118 what=_('SubstitutionMappings used in topology_template'),
119 required=self.NODE_TYPE))
121 node_type_def = self.custom_defs.get(node_type)
122 if not node_type_def:
123 ExceptionCollector.appendException(
124 InvalidNodeTypeError(what=node_type))
126 def _validate_inputs(self):
127 """validate the inputs of substitution mappings.
129 The inputs defined by the topology template have to match the
130 properties of the node type or the substituted node. If there are
131 more inputs than the substituted node has properties, default values
132 must be defined for those inputs.
135 all_inputs = set([input.name for input in self.inputs])
136 required_properties = set([p.name for p in
137 self.node_definition.
138 get_properties_def_objects()
139 if p.required and p.default is None])
140 # Must provide inputs for required properties of node type.
141 for property in required_properties:
142 # Check property which is 'required' and has no 'default' value
143 if property not in all_inputs:
144 ExceptionCollector.appendException(
145 MissingRequiredInputError(
146 what=_('SubstitutionMappings with node_type ')
148 input_name=property))
150 # If the optional properties of node type need to be customized by
151 # substituted node, it also is necessary to define inputs for them,
152 # otherwise they are not mandatory to be defined.
153 customized_parameters = set(self.sub_mapped_node_template
154 .get_properties().keys()
155 if self.sub_mapped_node_template else [])
156 all_properties = set(self.node_definition.get_properties_def())
157 for parameter in customized_parameters - all_inputs:
158 if parameter in all_properties:
159 ExceptionCollector.appendException(
160 MissingRequiredInputError(
161 what=_('SubstitutionMappings with node_type ')
163 input_name=parameter))
165 # Additional inputs are not in the properties of node type must
166 # provide default values. Currently the scenario may not happen
167 # because of parameters validation in nodetemplate, here is a
169 for input in self.inputs:
170 if input.name in all_inputs - all_properties \
171 and input.default is None:
172 ExceptionCollector.appendException(
173 MissingDefaultValueError(
174 what=_('SubstitutionMappings with node_type ')
176 input_name=input.name))
178 def _validate_capabilities(self):
179 """validate the capabilities of substitution mappings."""
181 # The capabilites must be in node template wchich be mapped.
182 tpls_capabilities = self.sub_mapping_def.get(self.CAPABILITIES)
183 node_capabiliteys = self.sub_mapped_node_template.get_capabilities() \
184 if self.sub_mapped_node_template else None
185 for cap in node_capabiliteys.keys() if node_capabiliteys else []:
186 if (tpls_capabilities and
187 cap not in list(tpls_capabilities.keys())):
189 # ExceptionCollector.appendException(
190 # UnknownFieldError(what='SubstitutionMappings',
193 def _validate_requirements(self):
194 """validate the requirements of substitution mappings."""
196 # The requirements must be in node template wchich be mapped.
197 tpls_requirements = self.sub_mapping_def.get(self.REQUIREMENTS)
198 node_requirements = self.sub_mapped_node_template.requirements \
199 if self.sub_mapped_node_template else None
200 for req in node_requirements if node_requirements else []:
201 if (tpls_requirements and
202 req not in list(tpls_requirements.keys())):
204 # ExceptionCollector.appendException(
205 # UnknownFieldError(what='SubstitutionMappings',
208 def _validate_outputs(self):
209 """validate the outputs of substitution mappings.
211 The outputs defined by the topology template have to match the
212 attributes of the node type or the substituted node template,
213 and the observable attributes of the substituted node template
214 have to be defined as attributes of the node type or outputs in
215 the topology template.
218 # The outputs defined by the topology template have to match the
219 # attributes of the node type according to the specification, but
220 # it's reasonable that there are more inputs than the node type
221 # has properties, the specification will be amended?
222 for output in self.outputs:
223 if output.name not in self.node_definition.get_attributes_def():
224 ExceptionCollector.appendException(
226 where=_('SubstitutionMappings with node_type ')
228 output_name=output.name))