Esempio n. 1
0
def get_sorts(request, attr_info):
    """Extract sort_key and sort_dir from request.

    Return as: [(key1, value1), (key2, value2)]
    """
    attributes.populate_project_info(attr_info)
    sort_keys = list_args(request, "sort_key")
    sort_dirs = list_args(request, "sort_dir")
    if len(sort_keys) != len(sort_dirs):
        msg = _("The number of sort_keys and sort_dirs must be same")
        raise exc.HTTPBadRequest(explanation=msg)
    valid_dirs = [constants.SORT_DIRECTION_ASC, constants.SORT_DIRECTION_DESC]
    absent_keys = [x for x in sort_keys if x not in attr_info]
    if absent_keys:
        msg = _("%s is invalid attribute for sort_keys") % absent_keys
        raise exc.HTTPBadRequest(explanation=msg)
    invalid_dirs = [x for x in sort_dirs if x not in valid_dirs]
    if invalid_dirs:
        msg = (_("%(invalid_dirs)s is invalid value for sort_dirs, "
                 "valid value is '%(asc)s' and '%(desc)s'") %
               {'invalid_dirs': invalid_dirs,
                'asc': constants.SORT_DIRECTION_ASC,
                'desc': constants.SORT_DIRECTION_DESC})
        raise exc.HTTPBadRequest(explanation=msg)
    return list(zip(sort_keys,
                    [x == constants.SORT_DIRECTION_ASC for x in sort_dirs]))
Esempio n. 2
0
def get_filters_from_dict(data, attr_info, skips=None):
    """Extracts the filters from a dict of query parameters.

    Returns a dict of lists for the filters:
    check=a&check=b&name=Bob&
    becomes:
    {'check': [u'a', u'b'], 'name': [u'Bob']}
    """
    attributes.populate_project_info(attr_info)
    is_empty_string_supported = is_empty_string_filtering_supported()
    skips = skips or []
    res = {}
    for key, values in data.items():
        if key in skips or hasattr(model_base.BASEV2, key):
            continue
        values = [
            v for v in values if v or (v == "" and is_empty_string_supported)
        ]
        key_attr_info = attr_info.get(key, {})
        if 'convert_list_to' in key_attr_info:
            values = key_attr_info['convert_list_to'](values)
        elif 'convert_to' in key_attr_info:
            convert_to = key_attr_info['convert_to']
            values = [convert_to(v) for v in values]
        if values:
            res[key] = values
    return res
Esempio n. 3
0
    def get_all_quotas(context, resources):
        """Given a list of resources, retrieve the quotas for the all tenants.

        :param context: The request context, for access checks.
        :param resources: A dictionary of the registered resource keys.
        :return: quotas list of dict of tenant_id:, resourcekey1:
        resourcekey2: ...
        """
        tenant_default = dict((key, resource.default)
                              for key, resource in resources.items())

        all_tenant_quotas = {}

        for quota in quota_obj.Quota.get_objects(context):
            tenant_id = quota['project_id']

            # avoid setdefault() because only want to copy when actually
            # required
            tenant_quota = all_tenant_quotas.get(tenant_id)
            if tenant_quota is None:
                tenant_quota = tenant_default.copy()
                tenant_quota['tenant_id'] = tenant_id
                attributes.populate_project_info(tenant_quota)
                all_tenant_quotas[tenant_id] = tenant_quota

            tenant_quota[quota['resource']] = quota['limit']

        # Convert values to a list to as caller expect an indexable iterable,
        # where python3's dict_values does not support indexing
        return list(all_tenant_quotas.values())
Esempio n. 4
0
    def prepare_request_body(context,
                             body,
                             is_create,
                             resource,
                             attr_info,
                             allow_bulk=False):
        """Verifies required attributes are in request body.

        Also checking that an attribute is only specified if it is allowed
        for the given operation (create/update).

        Attribute with default values are considered to be optional.

        body argument must be the deserialized body.
        """
        collection = resource + "s"
        if not body:
            raise webob.exc.HTTPBadRequest(_("Resource body required"))

        LOG.debug("Request body: %(body)s", {'body': body})
        try:
            if collection in body:
                if not allow_bulk:
                    raise webob.exc.HTTPBadRequest(
                        _("Bulk operation "
                          "not supported"))
                if not body[collection]:
                    raise webob.exc.HTTPBadRequest(_("Resources required"))
                bulk_body = [
                    Controller.prepare_request_body(
                        context,
                        item if resource in item else {resource: item},
                        is_create, resource, attr_info, allow_bulk)
                    for item in body[collection]
                ]
                return {collection: bulk_body}
            res_dict = body.get(resource)
        except (AttributeError, TypeError):
            msg = _("Body contains invalid data")
            raise webob.exc.HTTPBadRequest(msg)
        if res_dict is None:
            msg = _("Unable to find '%s' in request body") % resource
            raise webob.exc.HTTPBadRequest(msg)

        attr_ops = attributes.AttributeInfo(attr_info)
        attr_ops.populate_project_id(context, res_dict, is_create)
        attributes.populate_project_info(attr_info)
        attr_ops.verify_attributes(res_dict)

        if is_create:  # POST
            attr_ops.fill_post_defaults(res_dict,
                                        exc_cls=webob.exc.HTTPBadRequest)
        else:  # PUT
            for attr, attr_vals in attr_info.items():
                if attr in res_dict and not attr_vals['allow_put']:
                    msg = _("Cannot update read-only attribute %s") % attr
                    raise webob.exc.HTTPBadRequest(msg)

        attr_ops.convert_values(res_dict, exc_cls=webob.exc.HTTPBadRequest)
        return body
Esempio n. 5
0
def get_sorts(request, attr_info):
    """Extract sort_key and sort_dir from request.

    Return as: [(key1, value1), (key2, value2)]
    """
    attributes.populate_project_info(attr_info)
    sort_keys = list_args(request, "sort_key")
    sort_dirs = list_args(request, "sort_dir")
    if len(sort_keys) != len(sort_dirs):
        msg = _("The number of sort_keys and sort_dirs must be same")
        raise exc.HTTPBadRequest(explanation=msg)
    valid_dirs = [constants.SORT_DIRECTION_ASC, constants.SORT_DIRECTION_DESC]
    valid_sort_keys = set(attr for attr, schema in attr_info.items()
                          if schema.get('is_sort_key', False))
    absent_keys = [x for x in sort_keys if x not in valid_sort_keys]
    if absent_keys:
        msg = _("%s is invalid attribute for sort_keys") % absent_keys
        raise exc.HTTPBadRequest(explanation=msg)
    invalid_dirs = [x for x in sort_dirs if x not in valid_dirs]
    if invalid_dirs:
        msg = (_("%(invalid_dirs)s is invalid value for sort_dirs, "
                 "valid value is '%(asc)s' and '%(desc)s'") % {
                     'invalid_dirs': invalid_dirs,
                     'asc': constants.SORT_DIRECTION_ASC,
                     'desc': constants.SORT_DIRECTION_DESC
                 })
        raise exc.HTTPBadRequest(explanation=msg)
    return list(
        zip(sort_keys, [x == constants.SORT_DIRECTION_ASC for x in sort_dirs]))
Esempio n. 6
0
    def get_all_quotas(context, resources):
        """Given a list of resources, retrieve the quotas for the all tenants.

        :param context: The request context, for access checks.
        :param resources: A dictionary of the registered resource keys.
        :return: quotas list of dict of tenant_id:, resourcekey1:
        resourcekey2: ...
        """
        tenant_default = dict(
            (key, resource.default) for key, resource in resources.items())

        all_tenant_quotas = {}

        for quota in quota_obj.Quota.get_objects(context):
            tenant_id = quota['project_id']

            # avoid setdefault() because only want to copy when actually
            # required
            tenant_quota = all_tenant_quotas.get(tenant_id)
            if tenant_quota is None:
                tenant_quota = tenant_default.copy()
                tenant_quota['tenant_id'] = tenant_id
                attributes.populate_project_info(tenant_quota)
                all_tenant_quotas[tenant_id] = tenant_quota

            tenant_quota[quota['resource']] = quota['limit']

        # Convert values to a list to as caller expect an indexable iterable,
        # where python3's dict_values does not support indexing
        return list(all_tenant_quotas.values())
Esempio n. 7
0
    def prepare_request_body(context, body, is_create, resource, attr_info,
                             allow_bulk=False):
        """Verifies required attributes are in request body.

        Also checking that an attribute is only specified if it is allowed
        for the given operation (create/update).

        Attribute with default values are considered to be optional.

        body argument must be the deserialized body.
        """
        collection = resource + "s"
        if not body:
            raise webob.exc.HTTPBadRequest(_("Resource body required"))

        LOG.debug("Request body: %(body)s", {'body': body})
        try:
            if collection in body:
                if not allow_bulk:
                    raise webob.exc.HTTPBadRequest(_("Bulk operation "
                                                     "not supported"))
                if not body[collection]:
                    raise webob.exc.HTTPBadRequest(_("Resources required"))
                bulk_body = [
                    Controller.prepare_request_body(
                        context, item if resource in item
                        else {resource: item}, is_create, resource, attr_info,
                        allow_bulk) for item in body[collection]
                ]
                return {collection: bulk_body}
            res_dict = body.get(resource)
        except (AttributeError, TypeError):
            msg = _("Body contains invalid data")
            raise webob.exc.HTTPBadRequest(msg)
        if res_dict is None:
            msg = _("Unable to find '%s' in request body") % resource
            raise webob.exc.HTTPBadRequest(msg)
        if not isinstance(res_dict, dict):
            msg = _("Object '%s' contains invalid data") % resource
            raise webob.exc.HTTPBadRequest(msg)

        attr_ops = attributes.AttributeInfo(attr_info)
        attr_ops.populate_project_id(context, res_dict, is_create)
        attributes.populate_project_info(attr_info)
        attr_ops.verify_attributes(res_dict)

        if is_create:  # POST
            attr_ops.fill_post_defaults(
                res_dict, exc_cls=webob.exc.HTTPBadRequest)
        else:  # PUT
            for attr, attr_vals in attr_info.items():
                if attr in res_dict and not attr_vals['allow_put']:
                    msg = _("Cannot update read-only attribute %s") % attr
                    raise webob.exc.HTTPBadRequest(msg)

        attr_ops.convert_values(res_dict, exc_cls=webob.exc.HTTPBadRequest)
        return body
Esempio n. 8
0
def normalize_l7parameters(parameters):
    parameters = converters.convert_none_to_empty_dict(parameters)
    for key in parameters:
        if key not in SUPPORTED_L7_PARAMETERS:
            raise FlowClassifierInvalidL7Parameter(
                error_message='Unknown key %s.' % key)
    try:
        _l7_param_attrs.fill_post_defaults(parameters)
        attr.populate_project_info(SUPPORTED_L7_PARAMETERS)
        _l7_param_attrs.convert_values(parameters)
    except ValueError as error:
        raise FlowClassifierInvalidL7Parameter(error_message=str(error))
    return parameters
Esempio n. 9
0
def normalize_l7parameters(parameters):
    parameters = converters.convert_none_to_empty_dict(parameters)
    for key in parameters:
        if key not in SUPPORTED_L7_PARAMETERS:
            raise FlowClassifierInvalidL7Parameter(
                error_message='Unknown key %s.' % key)
    try:
        _l7_param_attrs.fill_post_defaults(parameters)
        attr.populate_project_info(SUPPORTED_L7_PARAMETERS)
        _l7_param_attrs.convert_values(parameters)
    except ValueError as error:
        raise FlowClassifierInvalidL7Parameter(error_message=str(error))
    return parameters
Esempio n. 10
0
def _fixup_res_dict(context, attr_name, res_dict, check_allow_post=True):
    attr_info = attributes.RESOURCE_ATTRIBUTE_MAP[attr_name]
    attr_ops = lib_attrs.AttributeInfo(attr_info)
    try:
        attr_ops.populate_project_id(context, res_dict, True)
        lib_attrs.populate_project_info(attr_info)
        attr_ops.verify_attributes(res_dict)
    except webob.exc.HTTPBadRequest as e:
        # convert webob exception into ValueError as these functions are
        # for internal use. webob exception doesn't make sense.
        raise ValueError(e.detail)
    attr_ops.fill_post_defaults(res_dict, check_allow_post=check_allow_post)
    attr_ops.convert_values(res_dict)
    return res_dict
Esempio n. 11
0
def _fixup_res_dict(context, attr_name, res_dict, check_allow_post=True):
    attr_info = attributes.RESOURCE_ATTRIBUTE_MAP[attr_name]
    attr_ops = lib_attrs.AttributeInfo(attr_info)
    try:
        attr_ops.populate_project_id(context, res_dict, True)
        lib_attrs.populate_project_info(attr_info)
        attr_ops.verify_attributes(res_dict)
    except webob.exc.HTTPBadRequest as e:
        # convert webob exception into ValueError as these functions are
        # for internal use. webob exception doesn't make sense.
        raise ValueError(e.detail)
    attr_ops.fill_post_defaults(res_dict, check_allow_post=check_allow_post)
    attr_ops.convert_values(res_dict)
    return res_dict
Esempio n. 12
0
def get_collection(context, model, dict_func,
                   filters=None, fields=None,
                   sorts=None, limit=None, marker_obj=None,
                   page_reverse=False):
    """Get a collection for a said model.

    :param context: The context to use for the DB session.
    :param model: The model for the collection.
    :param dict_func: The function used to build the collection dict.
    :param filters: The filters to apply.
    :param fields: The fields to collect.
    :param sorts: The sort keys to use.
    :param limit: The limit for the query if applicable.
    :param marker_obj: The marker object if applicable.
    :param page_reverse: If reverse paging should be used.
    :returns: A list of dicts where each dict is an object in the collection.
    """
    query = get_collection_query(context, model,
                                 filters=filters, sorts=sorts,
                                 limit=limit, marker_obj=marker_obj,
                                 page_reverse=page_reverse)
    items = [
        attributes.populate_project_info(
            dict_func(c, fields) if dict_func else c)
        for c in query
    ]
    if limit and page_reverse:
        items.reverse()
    return items
Esempio n. 13
0
def _fixup_res_dict(context, attr_name, res_dict, check_allow_post=True):
    # This method is a replacement of _fixup_res_dict which is used in
    # neutron.plugin.common.utils. All this mock does is insert a uuid
    # for the id field if one is not found ONLY if running in api_replay_mode.
    if cfg.CONF.api_replay_mode and 'id' not in res_dict:
        res_dict['id'] = uuidutils.generate_uuid()
    attr_info = attributes.RESOURCE_ATTRIBUTE_MAP[attr_name]
    attr_ops = lib_attrs.AttributeInfo(attr_info)
    try:
        attr_ops.populate_project_id(context, res_dict, True)
        lib_attrs.populate_project_info(attr_info)
        attr_ops.verify_attributes(res_dict)
    except webob.exc.HTTPBadRequest as e:
        # convert webob exception into ValueError as these functions are
        # for internal use. webob exception doesn't make sense.
        raise ValueError(e.detail)

    attr_ops.fill_post_defaults(res_dict, check_allow_post=check_allow_post)
    attr_ops.convert_values(res_dict)
    return res_dict
Esempio n. 14
0
def resource_fields(resource, fields):
    """Return only the resource items that are in fields.

    :param resource: A resource dict.
    :param fields: A list of fields to select from the resource.
    :returns: A new dict that contains only fields from resource as well
        as its attribute project info.
    """
    if fields:
        resource = {key: item for key, item in resource.items()
                    if key in fields}
    return attributes.populate_project_info(resource)
Esempio n. 15
0
def get_filters_from_dict(data,
                          attr_info,
                          skips=None,
                          is_filter_validation_supported=False):
    """Extracts the filters from a dict of query parameters.

    Returns a dict of lists for the filters:
    check=a&check=b&name=Bob&
    becomes:
    {'check': [u'a', u'b'], 'name': [u'Bob']}
    """
    attributes.populate_project_info(attr_info)
    is_empty_string_supported = is_empty_string_filtering_supported()
    skips = skips or []
    res = {}
    invalid_keys = []
    check_is_filter = False
    if is_filter_validation_supported and is_filter_validation_enabled():
        check_is_filter = True
    for key, values in data.items():
        if key in skips or hasattr(model_base.BASEV2, key):
            continue
        values = [
            v for v in values if v or (v == "" and is_empty_string_supported)
        ]
        key_attr_info = attr_info.get(key, {})
        if check_is_filter and not key_attr_info.get('is_filter'):
            invalid_keys.append(key)
            continue
        if 'convert_list_to' in key_attr_info:
            values = key_attr_info['convert_list_to'](values)
        elif 'convert_to' in key_attr_info:
            convert_to = key_attr_info['convert_to']
            values = [convert_to(v) for v in values]
        if values:
            res[key] = values
    if invalid_keys:
        msg = _("%s is invalid attribute for filtering") % invalid_keys
        raise exc.HTTPBadRequest(explanation=msg)
    return res
Esempio n. 16
0
def resource_fields(resource, fields):
    """Return only the resource items that are in fields.

    :param resource: a resource dictionary
    :type resource: dict
    :param fields: a list of fields to select from the resource
    :type fields: list

    """
    if fields:
        resource = {key: item for key, item in resource.items()
                    if key in fields}
    return attributes.populate_project_info(resource)
Esempio n. 17
0
def _fixup_res_dict(context, attr_name, res_dict, check_allow_post=True):
    # This method is a replacement of _fixup_res_dict which is used in
    # neutron.plugin.common.utils. All this mock does is insert a uuid
    # for the id field if one is not found ONLY if running in api_replay_mode.
    if cfg.CONF.api_replay_mode and 'id' not in res_dict:
        # exclude gateway ports from this
        if (attr_name != 'ports' or
            res_dict.get('device_owner') != 'network:router_gateway'):
            res_dict['id'] = uuidutils.generate_uuid()
    attr_info = lib_attrs.RESOURCES[attr_name]
    attr_ops = lib_attrs.AttributeInfo(attr_info)
    try:
        attr_ops.populate_project_id(context, res_dict, True)
        lib_attrs.populate_project_info(attr_info)
        attr_ops.verify_attributes(res_dict)
    except webob.exc.HTTPBadRequest as e:
        # convert webob exception into ValueError as these functions are
        # for internal use. webob exception doesn't make sense.
        raise ValueError(e.detail)

    attr_ops.fill_post_defaults(res_dict, check_allow_post=check_allow_post)
    attr_ops.convert_values(res_dict)
    return res_dict
Esempio n. 18
0
def get_filters_from_dict(data, attr_info, skips=None,
                          is_filter_validation_supported=False):
    """Extracts the filters from a dict of query parameters.

    Returns a dict of lists for the filters:
    check=a&check=b&name=Bob&
    becomes:
    {'check': [u'a', u'b'], 'name': [u'Bob']}
    """
    attributes.populate_project_info(attr_info)
    is_empty_string_supported = is_empty_string_filtering_supported()
    skips = skips or []
    res = {}
    invalid_keys = []
    check_is_filter = False
    if is_filter_validation_supported and is_filter_validation_enabled():
        check_is_filter = True
    for key, values in data.items():
        if key in skips or hasattr(model_base.BASEV2, key):
            continue
        values = [v for v in values
                  if v or (v == "" and is_empty_string_supported)]
        key_attr_info = attr_info.get(key, {})
        if check_is_filter and not key_attr_info.get('is_filter'):
            invalid_keys.append(key)
            continue
        if 'convert_list_to' in key_attr_info:
            values = key_attr_info['convert_list_to'](values)
        elif 'convert_to' in key_attr_info:
            convert_to = key_attr_info['convert_to']
            values = [convert_to(v) for v in values]
        if values:
            res[key] = values
    if invalid_keys:
        msg = _("%s is invalid attribute for filtering") % invalid_keys
        raise exc.HTTPBadRequest(explanation=msg)
    return res
Esempio n. 19
0
def get_collection(context, model, dict_func,
                   filters=None, fields=None,
                   sorts=None, limit=None, marker_obj=None,
                   page_reverse=False):
    query = get_collection_query(context, model,
                                 filters=filters, sorts=sorts,
                                 limit=limit, marker_obj=marker_obj,
                                 page_reverse=page_reverse)
    items = [
        attributes.populate_project_info(
            dict_func(c, fields) if dict_func else c)
        for c in query
    ]
    if limit and page_reverse:
        items.reverse()
    return items
Esempio n. 20
0
def get_collection(context, model, dict_func,
                   filters=None, fields=None,
                   sorts=None, limit=None, marker_obj=None,
                   page_reverse=False):
    query = get_collection_query(context, model,
                                 filters=filters, sorts=sorts,
                                 limit=limit, marker_obj=marker_obj,
                                 page_reverse=page_reverse)
    items = [
        attributes.populate_project_info(
            dict_func(c, fields) if dict_func else c)
        for c in query
    ]
    if limit and page_reverse:
        items.reverse()
    return items
Esempio n. 21
0
 def test_populate_project_info_ids_match(self):
     project_id = uuidutils.generate_uuid()
     attrs_in = {'project_id': project_id, 'tenant_id': project_id}
     attrs_out = attributes.populate_project_info(attrs_in)
     self.assertEqual(attrs_in, attrs_out)
Esempio n. 22
0
 def test_populate_project_info_ids_match(self):
     project_id = uuidutils.generate_uuid()
     attrs_in = {'project_id': project_id, 'tenant_id': project_id}
     attrs_out = attributes.populate_project_info(attrs_in)
     self.assertEqual(attrs_in, attrs_out)
Esempio n. 23
0
 def test_populate_project_info_add_tenant(self):
     attrs_in = {'project_id': uuidutils.generate_uuid()}
     attrs_out = attributes.populate_project_info(attrs_in)
     self.assertIn('tenant_id', attrs_out)
     self.assertEqual(attrs_in['project_id'], attrs_out['tenant_id'])
     self.assertEqual(2, len(attrs_out))
Esempio n. 24
0
 def test_populate_project_info_add_tenant(self):
     attrs_in = {'project_id': uuidutils.generate_uuid()}
     attrs_out = attributes.populate_project_info(attrs_in)
     self.assertIn('tenant_id', attrs_out)
     self.assertEqual(attrs_in['project_id'], attrs_out['tenant_id'])
     self.assertEqual(2, len(attrs_out))