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