vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / extensions / aria_extension_tosca / simple_v1_0 / modeling / capabilities.py
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements.  See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License.  You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 from aria.utils.collections import deepcopy_with_locators, OrderedDict
17 from aria.parser.validation import Issue
18
19 from .parameters import (convert_parameter_definitions_to_values, merge_raw_parameter_definitions,
20                          get_assigned_and_defined_parameter_values)
21
22
23 #
24 # CapabilityType
25 #
26
27 def get_inherited_valid_source_types(context, presentation):
28     """
29     If we haven't set the ``valid_source_types`` fields, uses that value from our parent, if we have
30     one (recursively).
31     """
32
33     valid_source_types = presentation.valid_source_types
34
35     if valid_source_types is None:
36         parent = presentation._get_parent(context)
37         valid_source_types = get_inherited_valid_source_types(context, parent) \
38             if parent is not None else None
39
40     return valid_source_types
41
42
43 #
44 # NodeType
45 #
46
47 def get_inherited_capability_definitions(context, presentation, for_presentation=None):
48     """
49     Returns our capability capability definitions added on top of those of our parent, if we have
50     one (recursively).
51
52     Allows overriding all aspects of parent capability properties except data type.
53     """
54
55     if for_presentation is None:
56         for_presentation = presentation
57
58     # Get capability definitions from parent
59     parent = presentation._get_parent(context)
60     capability_definitions = get_inherited_capability_definitions(
61         context, parent, for_presentation) if parent is not None else OrderedDict()
62
63     # Add/merge our capability definitions
64     our_capability_definitions = presentation.capabilities
65     if our_capability_definitions:
66         for capability_name, our_capability_definition in our_capability_definitions.iteritems():
67             if capability_name in capability_definitions:
68                 capability_definition = capability_definitions[capability_name]
69
70                 # Check if we changed the type
71                 type1 = capability_definition._get_type(context)
72                 type2 = our_capability_definition._get_type(context)
73
74                 if not type1._is_descendant(context, type2):
75                     context.validation.report(
76                         'capability definition type "{0}" is not a descendant of overridden '
77                         'capability definition type "{1}"' \
78                         .format(type1._name, type2._name),
79                         locator=our_capability_definition._locator, level=Issue.BETWEEN_TYPES)
80
81                 merge_capability_definition(context, presentation, capability_definition,
82                                             our_capability_definition)
83             else:
84                 capability_definition = our_capability_definition._clone(for_presentation)
85                 if isinstance(capability_definition._raw, basestring):
86                     # Make sure we have a dict
87                     the_type = capability_definition._raw
88                     capability_definition._raw = OrderedDict()
89                     capability_definition._raw['type'] = the_type
90                 capability_definitions[capability_name] = capability_definition
91
92             merge_capability_definition_from_type(context, presentation, capability_definition)
93
94     for capability_definition in capability_definitions.itervalues():
95         capability_definition._reset_method_cache()
96
97     return capability_definitions
98
99
100 #
101 # NodeTemplate
102 #
103
104 def get_template_capabilities(context, presentation):
105     """
106     Returns the node type's capabilities with our assignments to properties and attributes merged
107     in.
108
109     Capability properties' default values, if available, will be used if we did not assign them.
110
111     Makes sure that required properties indeed end up with a value.
112     """
113
114     capability_assignments = OrderedDict()
115
116     the_type = presentation._get_type(context) # NodeType
117     capability_definitions = the_type._get_capabilities(context) if the_type is not None else None
118
119     # Copy over capability definitions from the type (will initialize properties with default
120     # values)
121     if capability_definitions:
122         for capability_name, capability_definition in capability_definitions.iteritems():
123             capability_assignments[capability_name] = \
124                 convert_capability_from_definition_to_assignment(context, capability_definition,
125                                                                  presentation)
126
127     # Fill in our capability assignments
128     our_capability_assignments = presentation.capabilities
129     if our_capability_assignments:
130         for capability_name, our_capability_assignment in our_capability_assignments.iteritems():
131             if capability_name in capability_assignments:
132                 capability_assignment = capability_assignments[capability_name]
133
134                 # Assign properties
135                 values = get_assigned_and_defined_parameter_values(context,
136                                                                    our_capability_assignment,
137                                                                    'property')
138
139                 if values:
140                     capability_assignment._raw['properties'] = values
141                     capability_assignment._reset_method_cache()
142             else:
143                 context.validation.report(
144                     'capability "{0}" not declared at node type "{1}" in "{2}"'
145                     .format(capability_name, presentation.type, presentation._fullname),
146                     locator=our_capability_assignment._locator, level=Issue.BETWEEN_TYPES)
147
148     return capability_assignments
149
150
151 #
152 # Utils
153 #
154
155 def convert_capability_from_definition_to_assignment(context, presentation, container):
156     from ..assignments import CapabilityAssignment
157
158     raw = OrderedDict()
159
160     properties = presentation.properties
161     if properties is not None:
162         raw['properties'] = convert_parameter_definitions_to_values(context, properties)
163
164     # TODO attributes
165
166     return CapabilityAssignment(name=presentation._name, raw=raw, container=container)
167
168
169 def merge_capability_definition(context, presentation, capability_definition,
170                                 from_capability_definition):
171     raw_properties = OrderedDict()
172
173     capability_definition._raw['type'] = from_capability_definition.type
174
175     # Merge properties from type
176     from_property_defintions = from_capability_definition.properties
177     merge_raw_parameter_definitions(context, presentation, raw_properties, from_property_defintions,
178                                     'properties')
179
180     # Merge our properties
181     merge_raw_parameter_definitions(context, presentation, raw_properties,
182                                     capability_definition.properties, 'properties')
183
184     if raw_properties:
185         capability_definition._raw['properties'] = raw_properties
186         capability_definition._reset_method_cache()
187
188     # Merge occurrences
189     occurrences = from_capability_definition._raw.get('occurrences')
190     if (occurrences is not None) and (capability_definition._raw.get('occurrences') is None):
191         capability_definition._raw['occurrences'] = \
192             deepcopy_with_locators(occurrences)
193
194
195 def merge_capability_definition_from_type(context, presentation, capability_definition):
196     """
197     Merge ``properties`` and ``valid_source_types`` from the node type's capability definition
198     over those taken from the parent node type.
199     """
200     raw_properties = OrderedDict()
201
202     # Merge properties from parent
203     the_type = capability_definition._get_type(context)
204     type_property_defintions = the_type._get_properties(context)
205     merge_raw_parameter_definitions(context, presentation, raw_properties, type_property_defintions,
206                                     'properties')
207
208     # Merge our properties (might override definitions in parent)
209     merge_raw_parameter_definitions(context, presentation, raw_properties,
210                                     capability_definition.properties, 'properties')
211
212     if raw_properties:
213         capability_definition._raw['properties'] = raw_properties
214
215     # Override valid_source_types
216     if capability_definition._raw.get('valid_source_types') is None:
217         valid_source_types = the_type._get_valid_source_types(context)
218         if valid_source_types is not None:
219             capability_definition._raw['valid_source_types'] = \
220                 deepcopy_with_locators(valid_source_types)