예제 #1
0
def _parse_implementation(context, implementation):
    plugins = []

    for plugin in context.modeling.plugins:
        if implementation.startswith(plugin['name'] + '.'):
            plugins.append(plugin)

    length = len(plugins)
    if length > 1:
        raise InvalidValueError('ambiguous plugin name in implementation: %s' %
                                safe_repr(implementation),
                                level=Issue.BETWEEN_TYPES)
    elif length == 1:
        plugin = plugins[0]
        operation = implementation[len(plugin['name']) + 1:]
        if not operation:
            raise InvalidValueError('no operation name in implementation: %s' %
                                    safe_repr(implementation),
                                    level=Issue.BETWEEN_TYPES)
        return plugin, operation
    elif context.modeling.plugins:
        plugin = context.modeling.plugins[0]
        return plugin, implementation
    raise InvalidValueError('unknown plugin for implementation: %s' %
                            safe_repr(implementation),
                            level=Issue.BETWEEN_TYPES)
예제 #2
0
 def report(message, constraint):
     context.validation.report(
         'value %s %s per constraint in "%s": %s' %
         (message, safe_repr(constraint), presentation._name
          or presentation._container._name, safe_repr(value)),
         locator=presentation._locator,
         level=Issue.BETWEEN_FIELDS)
예제 #3
0
def get_property(value, nested_property_name_or_index, function_name):
    for name_or_index in nested_property_name_or_index:
        try:
            value = value[name_or_index]
        except KeyError as e:
            raise InvalidValueError(
                'function "%s" refers to an unknown nested property name: %s' %
                (function_name, safe_repr(name_or_index)),
                cause=e)
        except IndexError as e:
            raise InvalidValueError(
                'function "%s" refers to an unknown nested index: %s' %
                (function_name, safe_repr(name_or_index)),
                cause=e)
    return value
예제 #4
0
def get_node(context, modelable_entity_name, function_name):
    node = None

    def get_node(node_id):
        try:
            return context.get_node(node_id)
        except Exception as e:
            raise InvalidValueError(
                'function "%s" refers to an unknown node: %s' %
                (function_name, safe_repr(node_id)),
                cause=e)

    if modelable_entity_name == 'SELF':
        node = get_node(context.self_node_id)
    elif modelable_entity_name == 'SOURCE':
        node = get_node(context.source_node_id)
    elif modelable_entity_name == 'TARGET':
        node = get_node(context.target_node_id)
    else:
        try:
            nodes = context.get_nodes(modelable_entity_name)
            node = nodes[0]
        except Exception as e:
            raise InvalidValueError(
                'function "%s" refers to an unknown modelable entity: %s' %
                (function_name, safe_repr(modelable_entity_name)),
                cause=e)

    node_template = context.get_node_template(node['node_id'])

    return node, node_template
예제 #5
0
def parse_modelable_entity_name(context, presentation, name, index, value):
    value = parse_string_expression(context, presentation, name, index,
                                    'the modelable entity name', value)
    if value == 'SELF':
        the_self, _ = parse_self(presentation)
        if the_self is None:
            raise invalid_modelable_entity_name(
                name, index, value, presentation._locator,
                'a node template or a relationship template')
    elif value == 'HOST':
        _, self_variant = parse_self(presentation)
        if self_variant != 'node_template':
            raise invalid_modelable_entity_name(name, index, value,
                                                presentation._locator,
                                                'a node template')
    elif (value == 'SOURCE') or (value == 'TARGET'):
        _, self_variant = parse_self(presentation)
        if self_variant != 'relationship_template':
            raise invalid_modelable_entity_name(name, index, value,
                                                presentation._locator,
                                                'a relationship template')
    elif isinstance(value, basestring):
        node_templates = context.presentation.get(
            'service_template', 'topology_template', 'node_templates') or {}
        relationship_templates = context.presentation.get(
            'service_template', 'topology_template',
            'relationship_templates') or {}
        if (value not in node_templates) and (value
                                              not in relationship_templates):
            raise InvalidValueError(
                'function "%s" parameter %d is not a valid modelable entity name: %s'
                % (name, index + 1, safe_repr(value)),
                locator=presentation._locator,
                level=Issue.BETWEEN_TYPES)
    return value
예제 #6
0
    def validator(field, presentation, context):
        field.default_validate(presentation, context)

        value = getattr(presentation, field.name)
        if value is not None:
            # Test for circular definitions
            container_data_type = get_container_data_type(presentation)
            if (container_data_type is not None) and (container_data_type._name
                                                      == value):
                context.validation.report(
                    'type of property "%s" creates a circular value hierarchy: %s'
                    % (presentation._fullname, safe_repr(value)),
                    locator=presentation._get_child_locator('type'),
                    level=Issue.BETWEEN_TYPES)

            # Can be a complex data type
            if get_type_by_full_or_shorthand_name(context, value,
                                                  'data_types') is not None:
                return True

            # Can be a primitive data type
            if get_primitive_data_type(value) is None:
                report_issue_for_unknown_type(context, presentation, type_name,
                                              field.name)

        return False
예제 #7
0
def capability_definition_or_type_validator(field, presentation, context):
    """
    Makes sure refers to either a capability assignment name in the node template referred to by the
    :code:`node` field or a general capability type.

    If the value refers to a capability type, make sure the :code:`node` field was not assigned.

    Used with the :func:`field_validator` decorator for the :code:`capability` field in
    :class:`RequirementAssignment`.
    """

    field.default_validate(presentation, context)

    value = getattr(presentation, field.name)
    if value is not None:
        node, node_variant = presentation._get_node(context)
        if node_variant == 'node_template':
            capabilities = node._get_capabilities(context)
            if value in capabilities:
                return

        capability_types = context.presentation.get('service_template',
                                                    'capability_types')
        if (capability_types is not None) and (value in capability_types):
            if node is not None:
                context.validation.report(
                    '"%s" refers to a capability type even though "node" has a value in "%s"'
                    % (presentation._name, presentation._container._fullname),
                    locator=presentation._get_child_locator(field.name),
                    level=Issue.BETWEEN_FIELDS)
            return

        if node_variant == 'node_template':
            context.validation.report(
                'requirement "%s" refers to an unknown capability definition name or capability'
                ' type in "%s": %s' %
                (presentation._name, presentation._container._fullname,
                 safe_repr(value)),
                locator=presentation._get_child_locator(field.name),
                level=Issue.BETWEEN_TYPES)
        else:
            context.validation.report(
                'requirement "%s" refers to an unknown capability type in "%s": %s'
                % (presentation._name, presentation._container._fullname,
                   safe_repr(value)),
                locator=presentation._get_child_locator(field.name),
                level=Issue.BETWEEN_TYPES)
예제 #8
0
 def get_node(node_id):
     try:
         return context.get_node(node_id)
     except Exception as e:
         raise InvalidValueError(
             'function "%s" refers to an unknown node: %s' %
             (function_name, safe_repr(node_id)),
             cause=e)
예제 #9
0
def report_issue_for_bad_format(context, presentation, the_type, value, aspect, e):
    if aspect == 'default':
        aspect = '"default" value'
    elif aspect is not None:
        aspect = '"%s" aspect' % aspect

    if aspect is not None:
        context.validation.report('%s for field "%s" is not a valid "%s": %s'
                                  % (aspect, presentation._name or presentation._container._name,
                                     get_data_type_name(the_type), safe_repr(value)),
                                  locator=presentation._locator, level=Issue.BETWEEN_FIELDS,
                                  exception=e)
    else:
        context.validation.report('field "%s" is not a valid "%s": %s'
                                  % (presentation._name or presentation._container._name,
                                     get_data_type_name(the_type), safe_repr(value)),
                                  locator=presentation._locator, level=Issue.BETWEEN_FIELDS,
                                  exception=e)
예제 #10
0
def invalid_value(name, index, the_type, explanation, value, locator):
    return InvalidValueError(
        'function "%s" %s is not %s%s: %s' %
        (name, ('parameter %d' %
                (index + 1)) if index is not None else 'argument', the_type,
         (', %s' % explanation) if explanation is not None else '',
         safe_repr(value)),
        locator=locator,
        level=Issue.FIELD)
예제 #11
0
def constraint_clause_in_range_validator(field, presentation, context):
    """
    Makes sure that the value is a list with exactly two elements, that both lower bound contains a
    valid value for the container type, and that the upper bound is either "UNBOUNDED" or a valid
    value for the container type.

    Used with the :func:`field_validator` decorator for the :code:`in_range` field in
    :class:`ConstraintClause`.
    """

    field.default_validate(presentation, context)

    values = getattr(presentation, field.name)
    if isinstance(values, list):
        # Make sure list has exactly two elements
        if len(values) == 2:
            lower, upper = values
            the_type = presentation._get_type(context)

            # Lower bound must be coercible
            lower = coerce_value(context, presentation, the_type, None, None,
                                 lower, field.name)

            if upper != 'UNBOUNDED':
                # Upper bound be coercible
                upper = coerce_value(context, presentation, the_type, None,
                                     None, upper, field.name)

                # Second "in_range" value must be greater than first
                if (lower is not None) and (upper
                                            is not None) and (lower >= upper):
                    context.validation.report(
                        'upper bound of "in_range" constraint is not greater than the lower bound'
                        ' in "%s": %s <= %s' %
                        (presentation._container._fullname, safe_repr(lower),
                         safe_repr(upper)),
                        locator=presentation._locator,
                        level=Issue.FIELD)
        else:
            context.validation.report(
                'constraint "%s" is not a list of exactly 2 elements in "%s"' %
                (field.name, presentation._fullname),
                locator=presentation._get_child_locator(field.name),
                level=Issue.FIELD)
예제 #12
0
def get_node_template_scalable(context, presentation):
    scalable = Scalable()

    found = False
    capabilities = presentation.capabilities
    if capabilities:
        for key in capabilities.iterkeys():
            if key != 'scalable':
                context.validation.report(
                    'node template "%s" has unsupported capability: %s' %
                    (presentation._fullname, safe_repr(key)),
                    locator=presentation._get_child_locator(
                        'capabilities', key),
                    level=Issue.BETWEEN_FIELDS)

        capability = capabilities.get('scalable')
        if capability is not None:
            properties = capability.properties
            if properties:
                for key in properties.iterkeys():
                    if key not in ('default_instances', 'min_instances',
                                   'max_instances'):
                        context.validation.report(
                            '"scalable" capability in node template "%s" has unsupported property: %s'
                            % (presentation._fullname, safe_repr(key)),
                            locator=capability._get_child_locator(
                                'properties', key),
                            level=Issue.BETWEEN_FIELDS)

                default_instances = properties.get('default_instances')
                scalable.default_instances = default_instances.value if default_instances is not None else 1
                min_instances = properties.get('min_instances')
                scalable.min_instances = min_instances.value if min_instances is not None else 0
                max_instances = properties.get('max_instances')
                scalable.max_instances = max_instances.value if max_instances is not None else -1
                scalable.validate(context, presentation, capability._locator)
                found = True

    if not found:
        # Deprecated
        return _get_node_template_scalable(context, presentation)

    return scalable
예제 #13
0
def validate_data_type_name(context, presentation):
    """
    Makes sure the complex data type's name is not that of a built-in type.
    """

    name = presentation._name
    if get_primitive_data_type(name) is not None:
        context.validation.report('data type name is that of a built-in type: %s'
                                  % safe_repr(name),
                                  locator=presentation._locator, level=Issue.BETWEEN_TYPES)
예제 #14
0
 def evaluate(self, context):
     inputs = context.deployment_plan['inputs']
     if self.input_property_name not in inputs:
         raise InvalidValueError(
             'input does not exist for function "get_input": %s' %
             safe_repr(self.input_property_name),
             locator=self.locator)
     the_input = inputs[self.input_property_name]
     value = the_input.get('value', the_input.get('default'))
     return deepcopy_with_locators(value)
def validate_format(context, presentation, name):
    if (not isinstance(presentation._raw, list)) or (len(presentation._raw) != 2) \
        or (not isinstance(presentation._raw[0], basestring)) \
        or (not isinstance(presentation._raw[1], basestring)):
        context.validation.report(
            'substitution mappings %s "%s" is not a list of 2 strings: %s' %
            (name, presentation._name, safe_repr(presentation._raw)),
            locator=presentation._locator,
            level=Issue.FIELD)
        return False
    return True
예제 #16
0
 def getter(field, presentation, context=None):
     raw = field.default_get(presentation, context)
     if raw is not None:
         try:
             return cls(None, None, raw, None)
         except ValueError as e:
             raise InvalidValueError('%s is not a valid "%s" in "%s": %s' %
                                     (field.full_name, field.full_cls_name,
                                      presentation._name, safe_repr(raw)),
                                     cause=e,
                                     locator=field.get_locator(raw))
예제 #17
0
def policy_targets_validator(field, presentation, context):
    """
    Makes sure that the field's elements refer to either node templates or groups, and that
    they match the node types and group types declared in the policy type.

    Used with the :func:`field_validator` decorator for the :code:`targets` field in
    :class:`PolicyTemplate`.
    """

    field.default_validate(presentation, context)

    values = getattr(presentation, field.name)
    if values is not None:
        for value in values:
            node_templates = \
                context.presentation.get('service_template', 'topology_template',
                                         'node_templates') \
                or {}
            groups = context.presentation.get('service_template', 'topology_template', 'groups') \
                or {}
            if (value not in node_templates) and (value not in groups):
                report_issue_for_unknown_type(context, presentation,
                                              'node template or group',
                                              field.name, value)

            policy_type = presentation._get_type(context)
            if policy_type is None:
                break

            node_types, group_types = policy_type._get_targets(context)

            is_valid = False

            if value in node_templates:
                our_node_type = node_templates[value]._get_type(context)
                for node_type in node_types:
                    if node_type._is_descendant(context, our_node_type):
                        is_valid = True
                        break

            elif value in groups:
                our_group_type = groups[value]._get_type(context)
                for group_type in group_types:
                    if group_type._is_descendant(context, our_group_type):
                        is_valid = True
                        break

            if not is_valid:
                context.validation.report(
                    'policy definition target does not match either a node type or a group type'
                    ' declared in the policy type in "%s": %s' %
                    (presentation._name, safe_repr(value)),
                    locator=presentation._locator,
                    level=Issue.BETWEEN_TYPES)
예제 #18
0
    def __init__(self, entry_schema, constraints, value, aspect):
        if not isinstance(value, list):
            raise ValueError('range value is not a list: %s' %
                             safe_repr(value))
        if len(value) != 2:
            raise ValueError(
                'range value does not have exactly 2 elements: %s' %
                safe_repr(value))

        def is_int(v):
            return isinstance(v, int) and (not isinstance(v, bool)
                                           )  # In Python bool is an int

        if not is_int(value[0]):
            raise ValueError(
                'lower bound of range is not a valid integer: %s' %
                safe_repr(value[0]))

        if value[1] != 'UNBOUNDED':
            if not is_int(value[1]):
                raise ValueError(
                    'upper bound of range is not a valid integer or "UNBOUNDED": %s'
                    % safe_repr(value[0]))

            if value[0] >= value[1]:
                raise ValueError(
                    'upper bound of range is not greater than the lower bound: %s >= %s'
                    % (safe_repr(value[0]), safe_repr(value[1])))

        self.value = value
예제 #19
0
    def __init__(self, context, presentation, argument):
        self.locator = presentation._locator

        if (not isinstance(argument, list)) or (len(argument) < 2):
            raise InvalidValueError(
                'function "get_attribute" argument must be a list of at least 2 string expressions:'
                ' %s' % safe_repr(argument),
                locator=self.locator)

        self.modelable_entity_name = parse_modelable_entity_name(
            context, presentation, 'get_attribute', 0, argument[0])
        # The first of these will be tried as a req-or-cap name:
        self.nested_property_name_or_index = argument[1:]
def get_node_template(context, presentation, name):
    node_template_name = presentation._raw[0]
    node_template = context.presentation.get_from_dict('service_template',
                                                       'topology_template',
                                                       'node_templates',
                                                       node_template_name)
    if node_template is None:
        context.validation.report(
            'substitution mappings %s "%s" refers to an unknown node template: %s'
            % (name, presentation._name, safe_repr(node_template_name)),
            locator=presentation._locator,
            level=Issue.FIELD)
    return node_template
예제 #21
0
    def __init__(self, entry_schema, constraints, value, aspect):
        str_value = str(value)
        match = re.match(self.RE, str_value)
        if match is None:
            raise ValueError(
                'scalar must be formatted as <scalar> <unit>: %s' %
                safe_repr(value))

        self.factor = float(match.group('scalar'))
        self.unit = match.group('unit')

        unit_lower = self.unit.lower()
        unit_size = None
        for k, v in self.UNITS.iteritems():
            if k.lower() == unit_lower:
                self.unit = k
                unit_size = v
                break
        if unit_size is None:
            raise ValueError('scalar specified with unsupported unit: %s' %
                             safe_repr(self.unit))

        self.value = self.TYPE(self.factor * unit_size)
예제 #22
0
def coerce_value(context,
                 presentation,
                 the_type,
                 entry_schema,
                 constraints,
                 value,
                 aspect=None):
    """
    Returns the value after it's coerced to its type, reporting validation errors if it cannot be coerced.
    
    Supports both complex data types and primitives.
    
    Data types can use the :code:`coerce_value` extension to hook their own specialized function. If the extension
    is present, we will delegate to that hook.
    """

    is_function, fn = get_function(context, presentation, value)
    if is_function:
        return fn

    if the_type is None:
        return value

    if the_type == None.__class__:
        if value is not None:
            context.validation.report(
                'field "%s" is of type "null" but has a non-null value: %s' %
                (presentation._name, safe_repr(value)),
                locator=presentation._locator,
                level=Issue.BETWEEN_FIELDS)
            return None

    # Delegate to 'coerce_value' extension
    if hasattr(the_type, '_get_extension'):
        coerce_value_fn_name = the_type._get_extension('coerce_value')
        if coerce_value_fn_name is not None:
            if value is None:
                return None
            coerce_value_fn = import_fullname(coerce_value_fn_name)
            return coerce_value_fn(context, presentation, the_type,
                                   entry_schema, constraints, value, aspect)

    if hasattr(the_type, '_coerce_value'):
        # Delegate to '_coerce_value' (likely a DataType instance)
        return the_type._coerce_value(context, presentation, entry_schema,
                                      constraints, value, aspect)

    # Coerce to primitive type
    return coerce_to_primitive(context, presentation, the_type, constraints,
                               value, aspect)
예제 #23
0
    def __init__(self, context, presentation, argument):
        self.locator = presentation._locator

        if not isinstance(argument, list):
            raise InvalidValueError(
                'function "concat" argument must be a list of string expressions: %s'
                % safe_repr(argument),
                locator=self.locator)

        string_expressions = []
        for index, an_argument in enumerate(argument):
            string_expressions.append(
                parse_string_expression(context, presentation, 'concat', index,
                                        None, an_argument))
        self.string_expressions = FrozenList(string_expressions)
예제 #24
0
def get_relationship_assigned_and_defined_property_values(
        context, presentation):
    values = get_assigned_and_defined_property_values(context, presentation)

    if 'connection_type' in values:
        value = values['connection_type']
        if value.value not in ('all_to_all', 'all_to_one'):
            context.validation.report(
                '"connection_type" property is not "all_to_all" or "all_to_one" in relationship in node template "%s": %s'
                % (presentation._container._fullname, safe_repr(value)),
                locator=presentation._get_child_locator(
                    'properties', 'connection_type'),
                level=Issue.BETWEEN_FIELDS)

    return values
예제 #25
0
def get_relationship_inherited_property_definitions(context, presentation):
    properties = get_inherited_property_definitions(context, presentation,
                                                    'properties')

    definition = properties.get('connection_type')
    if definition is not None:
        default = definition.default
        if default not in ('all_to_all', 'all_to_one'):
            context.validation.report(
                '"connection_type" property default is not "all_to_all" or "all_to_one" in relationship type "%s": %s'
                % (presentation._fullname, safe_repr(default)),
                locator=definition._locator,
                level=Issue.BETWEEN_FIELDS)

    return properties
예제 #26
0
    def __init__(self, context, presentation, argument):
        self.locator = presentation._locator

        self.input_property_name = parse_string_expression(
            context, presentation, 'get_input', None,
            'the input property name', argument)

        if isinstance(self.input_property_name, basestring):
            the_input = context.presentation.get_from_dict(
                'service_template', 'topology_template', 'inputs',
                self.input_property_name)
            if the_input is None:
                raise InvalidValueError(
                    'function "get_input" argument is not a valid input name: %s'
                    % safe_repr(argument),
                    locator=self.locator)
예제 #27
0
    def __init__(self, context, presentation, argument):
        self.locator = presentation._locator

        self.node_type_name = parse_string_expression(context, presentation,
                                                      'get_nodes_of_type',
                                                      None,
                                                      'the node type name',
                                                      argument)

        if isinstance(self.node_type_name, basestring):
            node_types = context.presentation.get('service_template',
                                                  'node_types')
            if (node_types is None) or (self.node_type_name not in node_types):
                raise InvalidValueError(
                    'function "get_nodes_of_type" argument is not a valid node type name: %s'
                    % safe_repr(argument),
                    locator=self.locator)
예제 #28
0
    def _create(context, presentation, entry_schema, constraints, value,
                aspect):
        if not isinstance(value, list):
            raise ValueError('"list" data type value is not a list: %s' %
                             safe_repr(value))

        entry_schema_type = entry_schema._get_type(context)
        entry_schema_constraints = entry_schema.constraints

        r = List()
        for v in value:
            v = coerce_value(context, presentation, entry_schema_type, None,
                             entry_schema_constraints, v, aspect)
            if v is not None:
                r.append(v)

        return r
예제 #29
0
 def __init__(self, entry_schema, constraints, value, aspect):
     value = str(value)
     match = re.match(Timestamp.RE_SHORT, value)
     if match is not None:
         # Parse short form
         year = int(match.group('year'))
         month = int(match.group('month'))
         day = int(match.group('day'))
         self.value = datetime(year, month, day, tzinfo=UTC)
     else:
         match = re.match(Timestamp.RE_LONG, value)
         if match is not None:
             # Parse long form
             year = int(match.group('year'))
             month = int(match.group('month'))
             day = int(match.group('day'))
             hour = match.group('hour')
             if hour is not None:
                 hour = int(hour)
             minute = match.group('minute')
             if minute is not None:
                 minute = int(minute)
             second = match.group('second')
             if second is not None:
                 second = int(second)
             fraction = match.group('fraction')
             if fraction is not None:
                 fraction = int(float(fraction) *
                                1000000.0)  # convert to microseconds
             tzhour = match.group('tzhour')
             if tzhour is not None:
                 tzhour = int(tzhour)
             else:
                 tzhour = 0
             tzminute = match.group('tzminute')
             if tzminute is not None:
                 tzminute = int(tzminute)
             else:
                 tzminute = 0
             self.value = datetime(year, month, day, hour, minute, second,
                                   fraction, Timezone(tzhour, tzminute))
         else:
             raise ValueError(
                 'timestamp must be formatted as YAML ISO8601 variant or "YYYY-MM-DD": %s'
                 % safe_repr(value))
def validate_subtitution_mappings_capability(context, presentation):
    if not validate_format(context, presentation, 'capability'):
        return

    node_template = get_node_template(context, presentation, 'capability')
    if node_template is None:
        return

    node_type = presentation._container._get_type(context)
    if node_type is None:
        return

    capabilities = node_type._get_capabilities(context)
    type_capability = capabilities.get(presentation._name)
    if type_capability is None:
        context.validation.report(
            'substitution mappings capability "%s" is not declared in node type "%s"'
            % (presentation._name, node_type._name),
            locator=presentation._locator,
            level=Issue.BETWEEN_TYPES)
        return

    capability_name = presentation._raw[1]
    capabilities = node_template._get_capabilities(context)
    capability = capabilities.get(capability_name)

    if capability is None:
        context.validation.report(
            'substitution mappings capability "%s" refers to an unknown capability of node template'
            ' "%s": %s' % (presentation._name, node_template._name,
                           safe_repr(capability_name)),
            locator=presentation._locator,
            level=Issue.BETWEEN_TYPES)
        return

    type_capability_type = type_capability._get_type(context)
    capability_type = capability._get_type(context)

    if not type_capability_type._is_descendant(context, capability_type):
        context.validation.report(
            'type "%s" of substitution mappings capability "%s" is not a descendant of "%s"'
            % (capability_type._name, presentation._name,
               type_capability_type._name),
            locator=presentation._locator,
            level=Issue.BETWEEN_TYPES)