def properties(self): props = [] properties = self.node_type.get_value(PROPERTIES, self.node_template) requiredprop = [] for p in self.node_type.properties_def: if p.required: requiredprop.append(p.name) if properties: #make sure it's not missing any property required by a node type missingprop = [] for r in requiredprop: if r not in properties.keys(): missingprop.append(r) if missingprop: raise ValueError(_("Node template %(tpl)s is missing " "one or more required properties %(prop)s") % {'tpl': self.name, 'prop': missingprop}) for name, value in properties.items(): for p in self.node_type.properties_def: if p.name == name: prop = Property(name, value, p.schema) props.append(prop) else: if requiredprop: raise ValueError(_("Node template %(tpl)s is missing" "one or more required properties %(prop)s") % {'tpl': self.name, 'prop': requiredprop}) return props
def _get_capability_property(self, node_template, capability_name, property_name): """Gets a node template capability property.""" caps = node_template.get_capabilities() if caps and capability_name in caps.keys(): cap = caps[capability_name] property = None props = cap.get_properties() if props and property_name in props.keys(): property = props[property_name].value if not property: raise KeyError(_( "Property '{0}' not found in capability '{1}' of node" " template '{2}' referenced from node template" " '{3}'.").format(property_name, capability_name, node_template.name, self.context.name)) return property msg = _("Requirement/Capability '{0}' referenced from '{1}' node " "template not found in '{2}' node template.").format( capability_name, self.context.name, node_template.name) raise KeyError(msg)
def validate_scalar_unit(self): regex = re.compile('([0-9.]+)\s*(\w+)') try: result = regex.match(str(self.value)).groups() validateutils.str_to_num(result[0]) except Exception: raise ValueError(_('"%s" is not a valid scalar-unit') % self.value) if result[1].upper() in self.SCALAR_UNIT_DICT.keys(): return self.value raise ValueError(_('"%s" is not a valid scalar-unit') % self.value)
def __init__(self, property_name, property_type, constraint): super(InRange, self).__init__(property_name, property_type, constraint) if not isinstance(self.constraint_value, collections.Sequence) or (len(constraint[self.IN_RANGE]) != 2): raise InvalidSchemaError(message=_("in_range must be a list.")) for value in self.constraint_value: if not isinstance(value, self.valid_types): raise InvalidSchemaError(_("in_range value must " "be comparable.")) self.min = self.constraint_value[0] self.max = self.constraint_value[1]
def __init__(self, property_name, property_type, constraint): super(InRange, self).__init__(property_name, property_type, constraint) if(not isinstance(self.constraint_value, collections.Sequence) or (len(constraint[self.IN_RANGE]) != 2)): raise InvalidSchemaError(message=_('in_range must be a list.')) for value in self.constraint_value: if not isinstance(value, self.valid_types): raise InvalidSchemaError(_('in_range value must ' 'be comparable.')) self.min = self.constraint_value[0] self.max = self.constraint_value[1]
def __new__(cls, property_name, property_type, constraint): if cls is not Constraint: return super(Constraint, cls).__new__(cls) if not isinstance(constraint, collections.Mapping) or len(constraint) != 1: raise InvalidSchemaError(message=_("Invalid constraint schema.")) for type in constraint.keys(): ConstraintClass = get_constraint_class(type) if not ConstraintClass: msg = _('Invalid constraint type "%s".') % type raise InvalidSchemaError(message=msg) return ConstraintClass(property_name, property_type, constraint)
def __init__(self, name, schema_dict): self.name = name if not isinstance(schema_dict, collections.Mapping): msg = _("Schema %(pname)s must be a dict.") % dict(pname=name) raise InvalidSchemaError(message=msg) try: schema_dict['type'] except KeyError: msg = _("Schema %(pname)s must have type.") % dict(pname=name) raise InvalidSchemaError(message=msg) self.schema = schema_dict self._len = None self.constraints_list = []
def __new__(cls, property_name, property_type, constraint): if cls is not Constraint: return super(Constraint, cls).__new__(cls) if(not isinstance(constraint, collections.Mapping) or len(constraint) != 1): raise InvalidSchemaError(message=_('Invalid constraint schema.')) for type in constraint.keys(): ConstraintClass = get_constraint_class(type) if not ConstraintClass: msg = _('Invalid constraint type "%s".') % type raise InvalidSchemaError(message=msg) return ConstraintClass(property_name, property_type, constraint)
def __init__(self, name, schema_dict): self.name = name if not isinstance(schema_dict, collections.Mapping): msg = _("Schema %(pname)s must be a dict.") % dict(pname=name) raise InvalidSchemaError(message=msg) try: schema_dict["type"] except KeyError: msg = _("Schema %(pname)s must have type.") % dict(pname=name) raise InvalidSchemaError(message=msg) self.schema = schema_dict self._len = None self.constraints_list = []
class TOSCAException(Exception): '''Base exception class for TOSCA To correctly use this class, inherit from it and define a 'msg_fmt' property. ''' _FATAL_EXCEPTION_FORMAT_ERRORS = False message = _('An unknown exception occurred.') def __init__(self, **kwargs): try: self.message = self.msg_fmt % kwargs except KeyError: exc_info = sys.exc_info() log.exception( _('Exception in string format operation: %s') % exc_info[1]) if TOSCAException._FATAL_EXCEPTION_FORMAT_ERRORS: raise exc_info[0] def __str__(self): return self.message @staticmethod def set_fatal_format_exception(flag): if isinstance(flag, bool): TOSCAException._FATAL_EXCEPTION_FORMAT_ERRORS = flag
def _err_msg(self, value): return _("%(pname)s: %(pvalue)s is out of range " "(min:%(vmin)s, max:%(vmax)s).") % dict( pname=self.property_name, pvalue=self.value_msg, vmin=self.constraint_value_msg[0], vmax=self.constraint_value_msg[1], )
def _err_msg(self, value): allowed = '[%s]' % ', '.join(str(a) for a in self.constraint_value) return (_('%(pname)s: %(pvalue)s is not an valid ' 'value "%(cvalue)s".') % dict(pname=self.property_name, pvalue=value, cvalue=allowed))
def _err_msg(self, value): return (_('%(pname)s: %(pvalue)s is out of range ' '(min:%(vmin)s, max:%(vmax)s).') % dict(pname=self.property_name, pvalue=self.value_msg, vmin=self.constraint_value_msg[0], vmax=self.constraint_value_msg[1]))
def get_scalarunit_value(type, value, unit=None): if type in ScalarUnit.SCALAR_UNIT_TYPES: ScalarUnit_Class = get_scalarunit_class(type) return (ScalarUnit_Class(value). get_num_from_scalar_unit(unit)) else: raise TypeError(_('"%s" is not a valid scalar-unit type') % type)
def _translate_inputs(self): hot_inputs = [] hot_default = None for input in self.inputs: hot_input_type = TOSCA_TO_HOT_INPUT_TYPES[input.type] if input.name in self.parsed_params: DataEntity.validate_datatype(hot_input_type, self.parsed_params[input.name]) hot_default = self.parsed_params[input.name] elif input.default is not None: hot_default = input.default else: raise Exception( _("Need to specify a value " "for input {0}").format(input.name)) hot_constraints = [] if input.constraints: for constraint in input.constraints: constraint.validate( int(hot_default) if hot_input_type == "number" else hot_default) hc, hvalue = self._translate_constraints( constraint.constraint_key, constraint.constraint_value) hot_constraints.append({hc: hvalue}) hot_inputs.append( HotParameter(name=input.name, type=hot_input_type, description=input.description, default=hot_default, constraints=hot_constraints)) return hot_inputs
def _translate_inputs(self): hot_inputs = [] hot_default = None for input in self.inputs: hot_input_type = TOSCA_TO_HOT_INPUT_TYPES[input.type] if input.name in self.parsed_params: DataEntity.validate_datatype(hot_input_type, self.parsed_params[input.name]) hot_default = self.parsed_params[input.name] elif input.default is not None: hot_default = input.default else: raise Exception(_("Need to specify a value " "for input {0}").format(input.name)) hot_constraints = [] if input.constraints: for constraint in input.constraints: constraint.validate( int(hot_default) if hot_input_type == "number" else hot_default) hc, hvalue = self._translate_constraints( constraint.constraint_key, constraint.constraint_value) hot_constraints.append({hc: hvalue}) hot_inputs.append(HotParameter(name=input.name, type=hot_input_type, description=input.description, default=hot_default, constraints=hot_constraints)) return hot_inputs
def _find_node_template(self, node_template_name): if node_template_name == SELF: return self.context for node_template in self.tosca_tpl.nodetemplates: if node_template.name == node_template_name: return node_template raise KeyError(_( 'No such node template: {0}.').format(node_template_name))
def validate_scalar_unit_size(value): regex = re.compile('(\d*)\s*(\w*)') result = regex.match(str(value)).groups() if result[0] and ((not result[1]) or (result[1].upper() in Schema.SCALAR_UNIT_SIZE_DICT. keys())): return value raise ValueError(_('"%s" is not a valid scalar-unit') % value)
def validate(self): if len(self.args) != 1: raise ValueError(_( 'Expected one argument for get_input function but received: ' '{0}.').format(self.args)) inputs = [input.name for input in self.tosca_tpl.inputs] if self.args[0] not in inputs: raise UnknownInputError(input_name=self.args[0])
def __init__(self, ntype): super(NodeType, self).__init__() if ntype not in list(self.TOSCA_DEF.keys()): raise ValueError(_('Node type %(ntype)s is not a valid type.') % {'ntype': ntype}) self.defs = self.TOSCA_DEF[ntype] self.type = ntype self.related = {}
def validate(self): if len(self.args) < 2 or len(self.args) > 3: raise ValueError(_( 'Expected arguments: [node-template-name, req-or-cap ' '(optional), property name.')) if len(self.args) == 2: prop = self._find_property(self.args[1]).value if not isinstance(prop, Function): get_function(self.tosca_tpl, self.context, prop) elif len(self.args) == 3: get_function(self.tosca_tpl, self.context, self._find_req_or_cap_property(self.args[1], self.args[2])) else: raise NotImplementedError(_( 'Nested properties are not supported.'))
def validate_boolean(value): if isinstance(value, bool): return value if isinstance(value, str): normalised = value.lower() if normalised in ["true", "false"]: return normalised == "true" raise ValueError(_('"%s" is not a boolean') % value)
def validate_boolean(value): if isinstance(value, bool): return value if isinstance(value, str): normalised = value.lower() if normalised in ['true', 'false']: return normalised == 'true' raise ValueError(_('"%s" is not a boolean') % value)
def _find_property(self, property_name): node_tpl = self._find_node_template(self.args[0]) props = node_tpl.get_properties() found = [props[property_name]] if property_name in props else [] if len(found) == 0: raise KeyError(_( "Property: '{0}' not found in node template: {1}.").format( property_name, node_tpl.name)) return found[0]
def __init__(self, **kwargs): try: self.message = self.msg_fmt % kwargs except KeyError: exc_info = sys.exc_info() log.exception(_('Exception in string format operation: %s') % exc_info[1]) if TOSCAException._FATAL_EXCEPTION_FORMAT_ERRORS: raise exc_info[0]
def __init__(self, **kwargs): try: self.message = self.msg_fmt % kwargs except KeyError: exc_info = sys.exc_info() log.exception( _('Exception in string format operation: %s') % exc_info[1]) if TOSCAException._FATAL_EXCEPTION_FORMAT_ERRORS: raise exc_info[0]
def parse_parameters(parameter_list): parsed_inputs = {} if parameter_list.startswith('--parameters'): inputs = parameter_list.split('--parameters=')[1].\ replace('"', '').split(';') for param in inputs: keyvalue = param.split('=') parsed_inputs[keyvalue[0]] = keyvalue[1] else: raise ValueError(_("%(param) is not a valid parameter.") % parameter_list) return parsed_inputs
def handle_hosting(self): # handle hosting server for the OS:HEAT::SoftwareDeployment # from the TOSCA nodetemplate, traverse the relationship chain # down to the server if self.type == "OS::Heat::SoftwareDeployment": # skip if already have hosting # If type is NodeTemplate, look up corresponding HotResrouce host_server = self.properties.get("server") if host_server is None or not host_server["get_resource"]: raise Exception(_("Internal Error: expecting host " "in software deployment")) elif isinstance(host_server["get_resource"], NodeTemplate): self.properties["server"]["get_resource"] = host_server["get_resource"].name
def main(): if len(sys.argv) < 3: msg = _("The program requires minimum two arguments. " "Please refer to the usage documentation.") raise ValueError(msg) if "--template-file=" not in sys.argv[1]: msg = _("The program expects --template-file as first argument. " "Please refer to the usage documentation.") raise ValueError(msg) if "--template-type=" not in sys.argv[2]: msg = _("The program expects --template-type as second argument. " "Please refer to the usage documentation.") raise ValueError(msg) path = sys.argv[1].split('--template-file=')[1] # e.g. --template_file=translator/toscalib/tests/data/tosca_helloworld.yaml template_type = sys.argv[2].split('--template-type=')[1] # e.g. --template_type=tosca supported_types = ['tosca'] if not template_type: raise ValueError(_("Template type is needed. For example, 'tosca'")) elif template_type not in supported_types: raise ValueError(_("%(value)s is not a valid template type.") % {'value': template_type}) parsed_params = {} if len(sys.argv) > 3: parsed_params = parse_parameters(sys.argv[3]) if os.path.isfile(path): heat_tpl = translate(template_type, path, parsed_params) if heat_tpl: write_output(heat_tpl) else: raise ValueError(_("%(path)s is not a valid file.") % {'path': path})
def _find_node_template_containing_attribute(self): if self.node_template_name == HOST: # Currently this is the only way to tell whether the function # is used within the outputs section of the TOSCA template. if isinstance(self.context, list): raise ValueError(_( "get_attribute HOST keyword is not allowed within the " "outputs section of the TOSCA template")) node_tpl = self._find_host_containing_attribute() if not node_tpl: raise ValueError(_( "get_attribute HOST keyword is used in '{0}' node " "template but {1} was not found " "in relationship chain").format(self.context.name, HOSTED_ON)) else: node_tpl = self._find_node_template(self.args[0]) if not self._attribute_exists_in_type(node_tpl.type_definition): raise KeyError(_( "Attribute '{0}' not found in node template: {1}.").format( self.attribute_name, node_tpl.name)) return node_tpl
def __init__(self, property_name, property_type, constraint): self.property_name = property_name self.property_type = property_type self.constraint_value = constraint[self.constraint_key] self.constraint_value_msg = self.constraint_value if self.property_type in scalarunit.ScalarUnit.SCALAR_UNIT_TYPES: self.constraint_value = self._get_scalarunit_constraint_value() # check if constraint is valid for property type if property_type not in self.valid_prop_types: msg = _('Constraint type "%(ctype)s" is not valid ' 'for data type "%(dtype)s".') % dict( ctype=self.constraint_key, dtype=property_type) raise InvalidSchemaError(message=msg)
def handle_hosting(self): # handle hosting server for the OS:HEAT::SoftwareDeployment # from the TOSCA nodetemplate, traverse the relationship chain # down to the server if self.type == 'OS::Heat::SoftwareDeployment': # skip if already have hosting # If type is NodeTemplate, look up corresponding HotResrouce host_server = self.properties.get('server') if host_server is None or not host_server['get_resource']: raise Exception( _("Internal Error: expecting host " "in software deployment")) elif isinstance(host_server['get_resource'], NodeTemplate): self.properties['server']['get_resource'] = \ host_server['get_resource'].name
def _tosca_compute_test(self, tpl_snippet, expectedprops): nodetemplates = (translator.toscalib.utils.yamlparser. simple_parse(tpl_snippet)['node_templates']) name = list(nodetemplates.keys())[0] try: nodetemplate = NodeTemplate(name, nodetemplates) toscacompute = ToscaCompute(nodetemplate) toscacompute.handle_properties() if not self._compare_properties(toscacompute.properties, expectedprops): raise Exception(_("Hot Properties are not" " same as expected properties")) except Exception: # for time being rethrowing. Will be handled future based # on new development in Glance and Graffiti raise
def __init__(self, property_name, property_type, constraint): self.property_name = property_name self.property_type = property_type self.constraint_value = constraint[self.constraint_key] self.constraint_value_msg = self.constraint_value if self.property_type == Schema.SCALAR_UNIT_SIZE: if isinstance(self.constraint_value, list): self.constraint_value = [Constraint.get_num_from_scalar_unit_size(v) for v in self.constraint_value] else: self.constraint_value = Constraint.get_num_from_scalar_unit_size(self.constraint_value) # check if constraint is valid for property type if property_type not in self.valid_prop_types: msg = _('Constraint type "%(ctype)s" is not valid ' 'for data type "%(dtype)s".') % dict( ctype=self.constraint_key, dtype=property_type ) raise InvalidSchemaError(message=msg)
def get_num_from_scalar_unit(self, unit=None): if unit: if unit.upper() not in self.SCALAR_UNIT_DICT.keys(): raise ValueError(_('input unit "%s" is not a valid unit') % unit) else: unit = self.SCALAR_UNIT_DEFAULT self.validate_scalar_unit() regex = re.compile('([0-9.]+)\s*(\w+)') result = regex.match(str(self.value)).groups() converted = (float(validateutils.str_to_num(result[0])) * self.SCALAR_UNIT_DICT[result[1].upper()] / self.SCALAR_UNIT_DICT[unit.upper()]) if converted - int(converted) < 0.0000000000001: converted = int(converted) return converted
def _tosca_compute_test(self, tpl_snippet, expectedprops): nodetemplates = (translator.toscalib.utils.yamlparser.simple_parse( tpl_snippet)['node_templates']) name = list(nodetemplates.keys())[0] try: nodetemplate = NodeTemplate(name, nodetemplates) toscacompute = ToscaCompute(nodetemplate) toscacompute.handle_properties() if not self._compare_properties(toscacompute.properties, expectedprops): raise Exception( _("Hot Properties are not" " same as expected properties")) except Exception: # for time being rethrowing. Will be handled future based # on new development in Glance and Graffiti raise
def get_num_from_scalar_unit_size(value, unit=None): if unit: if unit.upper() not in Schema.SCALAR_UNIT_SIZE_DICT.keys(): raise ValueError(_('input unit "%s" is not a valid unit') % unit) else: unit = Schema.SCALAR_UNIT_SIZE_DEFAULT Constraint.validate_scalar_unit_size(value) regex = re.compile('(\d*)\s*(\w*)') result = regex.match(str(value)).groups() if not result[1]: converted = (Constraint.str_to_num(result[0])) if result[1].upper() in Schema.SCALAR_UNIT_SIZE_DICT.keys(): converted = int(Constraint.str_to_num(result[0]) * Schema.SCALAR_UNIT_SIZE_DICT[result[1].upper()] * math.pow(Schema.SCALAR_UNIT_SIZE_DICT [unit.upper()], -1)) return converted
def get_num_from_scalar_unit_size(value, unit=None): if unit: if unit.upper() not in Schema.SCALAR_UNIT_SIZE_DICT.keys(): raise ValueError(_('input unit "%s" is not a valid unit') % unit) else: unit = Schema.SCALAR_UNIT_SIZE_DEFAULT Constraint.validate_scalar_unit_size(value) regex = re.compile("(\d*)\s*(\w*)") result = regex.match(str(value)).groups() if not result[1]: converted = Constraint.str_to_num(result[0]) if result[1].upper() in Schema.SCALAR_UNIT_SIZE_DICT.keys(): converted = int( Constraint.str_to_num(result[0]) * Schema.SCALAR_UNIT_SIZE_DICT[result[1].upper()] * math.pow(Schema.SCALAR_UNIT_SIZE_DICT[unit.upper()], -1) ) return converted
def __init__(self, property_name, property_type, constraint): self.property_name = property_name self.property_type = property_type self.constraint_value = constraint[self.constraint_key] self.constraint_value_msg = self.constraint_value if self.property_type == Schema.SCALAR_UNIT_SIZE: if isinstance(self.constraint_value, list): self.constraint_value = [Constraint. get_num_from_scalar_unit_size(v) for v in self.constraint_value] else: self.constraint_value = (Constraint. get_num_from_scalar_unit_size (self.constraint_value)) # check if constraint is valid for property type if property_type not in self.valid_prop_types: msg = _('Constraint type "%(ctype)s" is not valid ' 'for data type "%(dtype)s".') % dict( ctype=self.constraint_key, dtype=property_type) raise InvalidSchemaError(message=msg)
def _get_explicit_relationship(self, req, value): """Handle explicit relationship For example, - req: node: DBMS relationship: tosca.relationships.HostedOn """ explicit_relation = {} node = value.get('node') if node: #TODO(spzala) implement look up once Glance meta data is available #to find a matching TOSCA node using the TOSCA types msg = _('Lookup by TOSCA types are not supported. ' 'Requirement for %s can not be full-filled.') % self.name if (node in list(self.type_definition.TOSCA_DEF.keys()) or node in self.custom_def): raise NotImplementedError(msg) related_tpl = NodeTemplate(node, self.templates, self.custom_def) relationship = value.get('relationship') if relationship: found_relationship_tpl = False #apply available relationship templates if found for tpl in self.available_rel_tpls: if tpl.name == relationship: rtype = RelationshipType(tpl.type) explicit_relation[rtype] = related_tpl self.relationship_tpl.append(tpl) found_relationship_tpl = True #create relationship template object. if not found_relationship_tpl: if isinstance(relationship, dict): relationship = relationship.get('type') for rtype in self.type_definition.relationship.keys(): if rtype.type == relationship: explicit_relation[rtype] = related_tpl related_tpl._add_relationship_template( req, rtype.type) return explicit_relation
def _get_explicit_relationship(self, req, value): """Handle explicit relationship For example, - req: node: DBMS relationship: tosca.relationships.HostedOn """ explicit_relation = {} node = value.get('node') if node: #TODO(spzala) implement look up once Glance meta data is available #to find a matching TOSCA node using the TOSCA types msg = _('Lookup by TOSCA types are not supported. ' 'Requirement for %s can not be full-filled.') % self.name if (node in list(self.type_definition.TOSCA_DEF.keys()) or node in self.custom_def): raise NotImplementedError(msg) related_tpl = NodeTemplate(node, self.templates, self.custom_def) relationship = value.get('relationship') if relationship: found_relationship_tpl = False #apply available relationship templates if found for tpl in self.available_rel_tpls: if tpl.name == relationship: rtype = RelationshipType(tpl.type) explicit_relation[rtype] = related_tpl self.relationship_tpl.append(tpl) found_relationship_tpl = True #create relationship template object. if not found_relationship_tpl: if isinstance(relationship, dict): relationship = relationship.get('type') for rtype in self.type_definition.relationship.keys(): if rtype.type == relationship: explicit_relation[rtype] = related_tpl related_tpl._add_relationship_template(req, rtype.type) return explicit_relation
class InvalidSchemaError(TOSCAException): msg_fmt = _("%(message)s")
def get_hot_attribute(self, attribute, args): # this is a place holder and should be implemented by the subclass # if translation is needed for the particular attribute raise Exception( _("No translation in TOSCA type {0} for attribute " "{1}").format(self.nodetemplate.type, attribute))
def get_hot_attribute(self, attribute, args): # this is a place holder and should be implemented by the subclass # if translation is needed for the particular attribute raise Exception( _("No translation in TOSCA type {0} for attribute " "{1}").format(self.nodetemplate.type, attribute) )
class TypeMismatchError(TOSCAException): msg_fmt = _('%(what)s must be of type: "%(type)s".')
class InvalidTypeError(TOSCAException): msg_fmt = _('Type "%(what)s" is not a valid type.')
class ValidationError(TOSCAException): msg_fmt = _("%(message)s")
class UnknownInputError(TOSCAException): msg_fmt = _('Unknown input: %(input_name)s')
def validate(self): if len(self.args) != 2: raise ValueError(_( 'Illegal arguments for {0} function. Expected arguments: ' 'node-template-name, attribute-name').format(GET_ATTRIBUTE)) self._find_node_template_containing_attribute()
class InvalidPropertyValueError(TOSCAException): msg_fmt = _('Value of property "%(what)s" is invalid.')
class InvalidTemplateVersion(TOSCAException): msg_fmt = _('The template version "%(what)s" is invalid. ' 'The valid versions are: "%(valid_versions)s"')
def _err_msg(self, value): return _('%(pname)s: "%(pvalue)s" does not match ' 'pattern "%(cvalue)s".') % dict( pname=self.property_name, pvalue=value, cvalue=self.constraint_value )