Support python3 uploaded to pypi websit
[parser.git] / tosca2heat / heat-translator / translator / hot / translate_inputs.py
1 #
2 # Licensed under the Apache License, Version 2.0 (the "License"); you may
3 # not use this file except in compliance with the License. You may obtain
4 # a copy of the License at
5 #
6 # http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11 # License for the specific language governing permissions and limitations
12 # under the License.
13
14 import logging
15 from toscaparser.dataentity import DataEntity
16 from toscaparser.elements.scalarunit import ScalarUnit_Size
17 from toscaparser.parameters import Input
18 from toscaparser.utils.gettextutils import _
19 from toscaparser.utils.validateutils import TOSCAVersionProperty
20 from translator.hot.syntax.hot_parameter import HotParameter
21
22
23 INPUT_CONSTRAINTS = (CONSTRAINTS, DESCRIPTION, LENGTH, RANGE,
24                      MIN, MAX, ALLOWED_VALUES, ALLOWED_PATTERN) = \
25                     ('constraints', 'description', 'length', 'range',
26                      'min', 'max', 'allowed_values', 'allowed_pattern')
27
28 TOSCA_CONSTRAINT_OPERATORS = (EQUAL, GREATER_THAN, GREATER_OR_EQUAL, LESS_THAN,
29                               LESS_OR_EQUAL, IN_RANGE, VALID_VALUES, LENGTH,
30                               MIN_LENGTH, MAX_LENGTH, PATTERN) = \
31                              ('equal', 'greater_than', 'greater_or_equal',
32                               'less_than', 'less_or_equal', 'in_range',
33                               'valid_values', 'length', 'min_length',
34                               'max_length', 'pattern')
35
36 TOSCA_TO_HOT_CONSTRAINTS_ATTRS = {'equal': 'allowed_values',
37                                   'greater_than': 'range',
38                                   'greater_or_equal': 'range',
39                                   'less_than': 'range',
40                                   'less_or_equal': 'range',
41                                   'in_range': 'range',
42                                   'valid_values': 'allowed_values',
43                                   'length': 'length',
44                                   'min_length': 'length',
45                                   'max_length': 'length',
46                                   'pattern': 'allowed_pattern'}
47
48 TOSCA_TO_HOT_INPUT_TYPES = {'string': 'string',
49                             'integer': 'number',
50                             'float': 'number',
51                             'boolean': 'boolean',
52                             'timestamp': 'string',
53                             'scalar-unit.size': 'number',
54                             'version': 'string',
55                             'null': 'string',
56                             'PortDef': 'number'}
57
58 log = logging.getLogger('heat-translator')
59
60
61 class TranslateInputs(object):
62
63     '''Translate TOSCA Inputs to Heat Parameters.'''
64
65     def __init__(self, inputs, parsed_params, deploy=None):
66         self.inputs = inputs
67         self.parsed_params = parsed_params
68         self.deploy = deploy
69
70     def translate(self):
71         return self._translate_inputs()
72
73     def _translate_inputs(self):
74         hot_inputs = []
75         if 'key_name' in self.parsed_params and 'key_name' not in self.inputs:
76             name = 'key_name'
77             type = 'string'
78             default = self.parsed_params[name]
79             schema_dict = {'type': type, 'default': default}
80             input = Input(name, schema_dict)
81             self.inputs.append(input)
82
83         log.info(_('Translating TOSCA input type to HOT input type.'))
84         for input in self.inputs:
85             hot_default = None
86             hot_input_type = TOSCA_TO_HOT_INPUT_TYPES[input.type]
87
88             if input.name in self.parsed_params:
89                 hot_default = DataEntity.validate_datatype(
90                     input.type, self.parsed_params[input.name])
91             elif input.default is not None:
92                 hot_default = DataEntity.validate_datatype(input.type,
93                                                            input.default)
94             else:
95                 if self.deploy:
96                     msg = _("Need to specify a value "
97                             "for input {0}.").format(input.name)
98                     log.error(msg)
99                     raise Exception(msg)
100             if input.type == "scalar-unit.size":
101                 # Assumption here is to use this scalar-unit.size for size of
102                 # cinder volume in heat templates and will be in GB.
103                 # should add logic to support other types if needed.
104                 input_value = hot_default
105                 hot_default = (ScalarUnit_Size(hot_default).
106                                get_num_from_scalar_unit('GiB'))
107                 if hot_default == 0:
108                     msg = _('Unit value should be > 0.')
109                     log.error(msg)
110                     raise Exception(msg)
111                 elif int(hot_default) < hot_default:
112                     hot_default = int(hot_default) + 1
113                     log.warning(_("Cinder unit value should be in multiples"
114                                   " of GBs. So corrected %(input_value)s "
115                                   "to %(hot_default)s GB.")
116                                 % {'input_value': input_value,
117                                    'hot_default': hot_default})
118             if input.type == 'version':
119                 hot_default = TOSCAVersionProperty(hot_default).get_version()
120
121             hot_constraints = []
122             if input.constraints:
123                 for constraint in input.constraints:
124                     if hot_default:
125                         constraint.validate(hot_default)
126                     hc, hvalue = self._translate_constraints(
127                         constraint.constraint_key, constraint.constraint_value)
128                     hot_constraints.append({hc: hvalue})
129
130             hot_inputs.append(HotParameter(name=input.name,
131                                            type=hot_input_type,
132                                            description=input.description,
133                                            default=hot_default,
134                                            constraints=hot_constraints))
135         return hot_inputs
136
137     def _translate_constraints(self, name, value):
138         hot_constraint = TOSCA_TO_HOT_CONSTRAINTS_ATTRS[name]
139
140         # Offset used to support less_than and greater_than.
141         # TODO(anyone):  when parser supports float, verify this works
142         offset = 1
143
144         if name == EQUAL:
145             hot_value = [value]
146         elif name == GREATER_THAN:
147             hot_value = {"min": value + offset}
148         elif name == GREATER_OR_EQUAL:
149             hot_value = {"min": value}
150         elif name == LESS_THAN:
151             hot_value = {"max": value - offset}
152         elif name == LESS_OR_EQUAL:
153             hot_value = {"max": value}
154         elif name == IN_RANGE:
155             # value is list type here
156             min_value = min(value)
157             max_value = max(value)
158             hot_value = {"min": min_value, "max": max_value}
159         elif name == LENGTH:
160             hot_value = {"min": value, "max": value}
161         elif name == MIN_LENGTH:
162             hot_value = {"min": value}
163         elif name == MAX_LENGTH:
164             hot_value = {"max": value}
165         else:
166             hot_value = value
167         return hot_constraint, hot_value