Esempio n. 1
0
    def get_all(self,
                context,
                search_opts=None,
                marker=None,
                limit=None,
                offset=None,
                sort_keys=None,
                sort_dirs=None):
        context.authorize(policy.GET_ALL_POLICY)

        search_opts = search_opts or {}

        all_tenants = search_opts.pop('all_tenants', '0')
        if not strutils.is_valid_boolstr(all_tenants):
            msg = _("all_tenants must be a boolean, got '%s'.") % all_tenants
            raise exception.InvalidParameterValue(err=msg)

        if context.is_admin and strutils.bool_from_string(all_tenants):
            backups = objects.BackupList.get_all(context, search_opts, marker,
                                                 limit, offset, sort_keys,
                                                 sort_dirs)
        else:
            backups = objects.BackupList.get_all_by_project(
                context, context.project_id, search_opts, marker, limit,
                offset, sort_keys, sort_dirs)

        return backups
Esempio n. 2
0
    def _create(self, req, body):
        """Creates a new volume type."""
        context = req.environ['cinder.context']
        authorize(context)

        self.assert_valid_body(body, 'volume_type')

        vol_type = body['volume_type']
        name = vol_type.get('name', None)
        description = vol_type.get('description')
        specs = vol_type.get('extra_specs', {})
        utils.validate_dictionary_string_length(specs)
        is_public = vol_type.get('os-volume-type-access:is_public', True)

        if name is None or len(name.strip()) == 0:
            msg = _("Volume type name can not be empty.")
            raise webob.exc.HTTPBadRequest(explanation=msg)

        utils.check_string_length(name,
                                  'Type name',
                                  min_length=1,
                                  max_length=255)

        if description is not None:
            utils.check_string_length(description,
                                      'Type description',
                                      min_length=0,
                                      max_length=255)

        if not strutils.is_valid_boolstr(is_public):
            msg = _("Invalid value '%s' for is_public. Accepted values: "
                    "True or False.") % is_public
            raise webob.exc.HTTPBadRequest(explanation=msg)

        try:
            volume_types.create(context,
                                name,
                                specs,
                                is_public,
                                description=description)
            vol_type = volume_types.get_volume_type_by_name(context, name)
            req.cache_resource(vol_type, name='types')
            self._notify_volume_type_info(context, 'volume_type.create',
                                          vol_type)

        except exception.VolumeTypeExists as err:
            self._notify_volume_type_error(context,
                                           'volume_type.create',
                                           err,
                                           volume_type=vol_type)
            raise webob.exc.HTTPConflict(explanation=six.text_type(err))
        except exception.VolumeTypeNotFoundByName as err:
            self._notify_volume_type_error(context,
                                           'volume_type.create',
                                           err,
                                           name=name)
            # Not found exception will be handled at the wsgi level
            raise

        return self._view_builder.show(req, vol_type)
Esempio n. 3
0
    def update(self, req, id, body):
        # Update description for a given group type.
        context = req.environ['cinder.context']
        self._check_policy(context)

        self.assert_valid_body(body, 'group_type')

        grp_type = body['group_type']
        description = grp_type.get('description')
        name = grp_type.get('name')
        is_public = grp_type.get('is_public')

        # Name and description can not be both None.
        # If name specified, name can not be empty.
        if name and len(name.strip()) == 0:
            msg = _("Group type name can not be empty.")
            raise webob.exc.HTTPBadRequest(explanation=msg)

        if name is None and description is None and is_public is None:
            msg = _("Specify group type name, description or "
                    "a combination thereof.")
            raise webob.exc.HTTPBadRequest(explanation=msg)

        if is_public is not None and not strutils.is_valid_boolstr(is_public):
            msg = _("Invalid value '%s' for is_public. Accepted values: "
                    "True or False.") % is_public
            raise webob.exc.HTTPBadRequest(explanation=msg)

        if name:
            utils.check_string_length(name, 'Type name',
                                      min_length=1, max_length=255)

        if description is not None:
            utils.check_string_length(description, 'Type description',
                                      min_length=0, max_length=255)

        try:
            group_types.update(context, id, name, description,
                               is_public=is_public)
            # Get the updated
            grp_type = group_types.get_group_type(context, id)
            req.cache_resource(grp_type, name='group_types')
            self._notify_group_type_info(
                context, 'group_type.update', grp_type)

        except exception.GroupTypeNotFound as err:
            self._notify_group_type_error(
                context, 'group_type.update', err, id=id)
            raise webob.exc.HTTPNotFound(explanation=six.text_type(err))
        except exception.GroupTypeExists as err:
            self._notify_group_type_error(
                context, 'group_type.update', err, group_type=grp_type)
            raise webob.exc.HTTPConflict(explanation=six.text_type(err))
        except exception.GroupTypeUpdateFailed as err:
            self._notify_group_type_error(
                context, 'group_type.update', err, group_type=grp_type)
            raise webob.exc.HTTPInternalServerError(
                explanation=six.text_type(err))

        return self._view_builder.show(req, grp_type)
Esempio n. 4
0
def get_bool_param(param_string, params):
    param = params.get(param_string, False)
    if not strutils.is_valid_boolstr(param):
        msg = _('Value %(param)s for %(param_string)s is not a '
                'boolean.') % {'param': param, 'param_string': param_string}
        raise exception.InvalidParameterValue(err=msg)

    return strutils.bool_from_string(param, strict=True)
Esempio n. 5
0
def get_bool_param(param_string, params, default=False):
    param = params.get(param_string, default)
    if not strutils.is_valid_boolstr(param):
        msg = _("Value '%(param)s' for '%(param_string)s' is not "
                "a boolean.") % {'param': param, 'param_string': param_string}
        raise exception.InvalidParameterValue(err=msg)

    return strutils.bool_from_string(param, strict=True)
Esempio n. 6
0
def get_bool_param(param_string, params, default=False):
    param = params.get(param_string, default)
    if not strutils.is_valid_boolstr(param):
        msg = _("Value '%(param)s' for '%(param_string)s' is not "
                "a boolean.") % {'param': param, 'param_string': param_string}
        raise exception.InvalidParameterValue(err=msg)

    return strutils.bool_from_string(param, strict=True)
Esempio n. 7
0
def get_bool_param(param_string, params):
    param = params.get(param_string, False)
    if not strutils.is_valid_boolstr(param):
        msg = _('Value %(param)s for %(param_string)s is not a '
                'boolean.') % {
                    'param': param,
                    'param_string': param_string
                }
        raise exception.InvalidParameterValue(err=msg)

    return strutils.bool_from_string(param, strict=True)
Esempio n. 8
0
    def _create(self, req, body):
        """Creates a new volume type."""
        context = req.environ['cinder.context']
        authorize(context)

        self.assert_valid_body(body, 'volume_type')

        vol_type = body['volume_type']
        name = vol_type.get('name', None)
        description = vol_type.get('description')
        specs = vol_type.get('extra_specs', {})
        utils.validate_dictionary_string_length(specs)
        is_public = vol_type.get('os-volume-type-access:is_public', True)

        if name is None or len(name.strip()) == 0:
            msg = _("Volume type name can not be empty.")
            raise webob.exc.HTTPBadRequest(explanation=msg)

        utils.check_string_length(name, 'Type name',
                                  min_length=1, max_length=255)

        if description is not None:
            utils.check_string_length(description, 'Type description',
                                      min_length=0, max_length=255)

        if not strutils.is_valid_boolstr(is_public):
            msg = _("Invalid value '%s' for is_public. Accepted values: "
                    "True or False.") % is_public
            raise webob.exc.HTTPBadRequest(explanation=msg)

        try:
            volume_types.create(context,
                                name,
                                specs,
                                is_public,
                                description=description)
            vol_type = volume_types.get_volume_type_by_name(context, name)
            req.cache_resource(vol_type, name='types')
            self._notify_volume_type_info(
                context, 'volume_type.create', vol_type)

        except exception.VolumeTypeExists as err:
            self._notify_volume_type_error(
                context, 'volume_type.create', err, volume_type=vol_type)
            raise webob.exc.HTTPConflict(explanation=six.text_type(err))
        except exception.VolumeTypeNotFoundByName as err:
            self._notify_volume_type_error(
                context, 'volume_type.create', err, name=name)
            # Not found exception will be handled at the wsgi level
            raise

        return self._view_builder.show(req, vol_type)
Esempio n. 9
0
    def _validate_reservation_params(self, values):
        if 'amount' in values:
            try:
                values['amount'] = strutils.validate_integer(
                    values['amount'], "amount", 1, db_api.DB_MAX_INT)
            except ValueError as e:
                raise mgr_exceptions.MalformedParameter(six.text_type(e))

        if 'affinity' in values:
            if (values['affinity'] not in NONE_VALUES
                    and not strutils.is_valid_boolstr(values['affinity'])):
                raise mgr_exceptions.MalformedParameter(
                    param='affinity (must be a bool value or None)')
Esempio n. 10
0
    def create(self, req, body):
        """Creates a new snapshot."""
        kwargs = {}
        context = req.environ['cinder.context']

        if not self.is_valid_body(body, 'snapshot'):
            raise exc.HTTPUnprocessableEntity()

        snapshot = body['snapshot']
        kwargs['metadata'] = snapshot.get('metadata', None)

        try:
            volume_id = snapshot['volume_id']
        except KeyError:
            msg = _("'volume_id' must be specified")
            raise exc.HTTPBadRequest(explanation=msg)

        # Not found exception will be handled at the wsgi level
        volume = self.volume_api.get(context, volume_id)

        force = snapshot.get('force', False)
        msg = _LI("Create snapshot from volume %s")
        LOG.info(msg, volume_id)

        if not strutils.is_valid_boolstr(force):
            msg = _("Invalid value '%s' for force. ") % force
            raise exception.InvalidParameterValue(err=msg)

        if strutils.bool_from_string(force):
            new_snapshot = self.volume_api.create_snapshot_force(
                context,
                volume,
                snapshot.get('display_name'),
                snapshot.get('display_description'),
                **kwargs)
        else:
            new_snapshot = self.volume_api.create_snapshot(
                context,
                volume,
                snapshot.get('display_name'),
                snapshot.get('display_description'),
                **kwargs)
        req.cache_db_snapshot(new_snapshot)

        retval = _translate_snapshot_detail_view(new_snapshot)

        return {'snapshot': retval}
Esempio n. 11
0
def extract_extra_specs(extra_specs, specs_to_add):
    for item in specs_to_add:
        (key, value) = item.split('=', 1)
        if key in extra_specs:
            msg = ("Argument '%s' value specified twice." % key)
            raise exceptions.CommandError(msg)
        elif key in constants.BOOL_SPECS:
            if strutils.is_valid_boolstr(value):
                extra_specs[key] = value.capitalize()
            else:
                msg = ("Argument '%s' is of boolean "
                       "type and has invalid value: %s" %
                       (key, six.text_type(value)))
                raise exceptions.CommandError(msg)
        else:
            extra_specs[key] = value
    return extra_specs
Esempio n. 12
0
    def create(self, req, body):
        """Creates a new snapshot."""
        kwargs = {}
        context = req.environ['cinder.context']

        if not self.is_valid_body(body, 'snapshot'):
            raise exc.HTTPUnprocessableEntity()

        snapshot = body['snapshot']
        kwargs['metadata'] = snapshot.get('metadata', None)

        try:
            volume_id = snapshot['volume_id']
        except KeyError:
            msg = _("'volume_id' must be specified")
            raise exc.HTTPBadRequest(explanation=msg)

        # Not found exception will be handled at the wsgi level
        volume = self.volume_api.get(context, volume_id)

        force = snapshot.get('force', False)
        msg = _LI("Create snapshot from volume %s")
        LOG.info(msg, volume_id)

        if not strutils.is_valid_boolstr(force):
            msg = _("Invalid value '%s' for force. ") % force
            raise exception.InvalidParameterValue(err=msg)

        if strutils.bool_from_string(force):
            new_snapshot = self.volume_api.create_snapshot_force(
                context, volume, snapshot.get('display_name'),
                snapshot.get('display_description'), **kwargs)
        else:
            new_snapshot = self.volume_api.create_snapshot(
                context, volume, snapshot.get('display_name'),
                snapshot.get('display_description'), **kwargs)
        req.cache_db_snapshot(new_snapshot)

        retval = _translate_snapshot_detail_view(new_snapshot)

        return {'snapshot': retval}
Esempio n. 13
0
    def get_all(self, context, search_opts=None, marker=None, limit=None,
                offset=None, sort_keys=None, sort_dirs=None):
        check_policy(context, 'get_all')

        search_opts = search_opts or {}

        all_tenants = search_opts.pop('all_tenants', '0')
        if not strutils.is_valid_boolstr(all_tenants):
            msg = _("all_tenants must be a boolean, got '%s'.") % all_tenants
            raise exception.InvalidParameterValue(err=msg)

        if context.is_admin and strutils.bool_from_string(all_tenants):
            backups = objects.BackupList.get_all(context, search_opts,
                                                 marker, limit, offset,
                                                 sort_keys, sort_dirs)
        else:
            backups = objects.BackupList.get_all_by_project(
                context, context.project_id, search_opts,
                marker, limit, offset, sort_keys, sort_dirs
            )

        return backups
Esempio n. 14
0
        def is_local_link_information_valid(local_link_information_list):
            if not local_link_information_list:
                return False

            if len(local_link_information_list) > 1:
                LOG.warning(
                    "'local_link_information' must have only one value")
                return False

            switch_info = common.switch_info_from_local_link_information_list(
                local_link_information_list)

            if not switch_info:
                LOG.warning(
                    "'local_link_information' must contain 'switch_info'.")
                return False

            server_hardware = (
                common.server_hardware_from_local_link_information_list(
                    self.oneview_client, local_link_information_list))
            server_hardware_id = server_hardware.get('uuid')

            if strutils.is_valid_boolstr(switch_info.get('bootable')):
                bootable = strutils.bool_from_string(
                    switch_info.get('bootable'))
            else:
                bootable = switch_info.get('bootable')

            if not (server_hardware_id or bootable):
                LOG.warning("'local_link_information' must contain "
                            "'server_hardware_id' and 'bootable'.")
                return False

            if not isinstance(bootable, bool):
                LOG.warning("'bootable' must be a boolean.")
                return False

            return True
Esempio n. 15
0
def extract_extra_specs(extra_specs,
                        specs_to_add,
                        bool_specs=constants.BOOL_SPECS):
    try:
        for item in specs_to_add:
            (key, value) = item.split('=', 1)
            if key in extra_specs:
                msg = ("Argument '%s' value specified twice." % key)
                raise exceptions.CommandError(msg)
            elif key in bool_specs:
                if strutils.is_valid_boolstr(value):
                    extra_specs[key] = value.capitalize()
                else:
                    msg = ("Argument '%s' is of boolean "
                           "type and has invalid value: %s" %
                           (key, str(value)))
                    raise exceptions.CommandError(msg)
            else:
                extra_specs[key] = value
    except ValueError:
        msg = LOG.error(_("Wrong format: specs should be key=value pairs."))
        raise exceptions.CommandError(msg)
    return extra_specs
Esempio n. 16
0
    def test_is_valid_boolstr(self):
        self.assertTrue(strutils.is_valid_boolstr('true'))
        self.assertTrue(strutils.is_valid_boolstr('false'))
        self.assertTrue(strutils.is_valid_boolstr('yes'))
        self.assertTrue(strutils.is_valid_boolstr('no'))
        self.assertTrue(strutils.is_valid_boolstr('y'))
        self.assertTrue(strutils.is_valid_boolstr('n'))
        self.assertTrue(strutils.is_valid_boolstr('1'))
        self.assertTrue(strutils.is_valid_boolstr('0'))
        self.assertTrue(strutils.is_valid_boolstr(1))
        self.assertTrue(strutils.is_valid_boolstr(0))

        self.assertFalse(strutils.is_valid_boolstr('maybe'))
        self.assertFalse(strutils.is_valid_boolstr('only on tuesdays'))
Esempio n. 17
0
    def update(self, req, id, body):
        # Update description for a given group type.
        context = req.environ['cinder.context']
        self._check_policy(context)

        self.assert_valid_body(body, 'group_type')

        grp_type = body['group_type']
        description = grp_type.get('description')
        name = grp_type.get('name')
        is_public = grp_type.get('is_public')

        # Name and description can not be both None.
        # If name specified, name can not be empty.
        if name and len(name.strip()) == 0:
            msg = _("Group type name can not be empty.")
            raise webob.exc.HTTPBadRequest(explanation=msg)

        if name is None and description is None and is_public is None:
            msg = _("Specify group type name, description or "
                    "a combination thereof.")
            raise webob.exc.HTTPBadRequest(explanation=msg)

        if is_public is not None and not strutils.is_valid_boolstr(is_public):
            msg = _("Invalid value '%s' for is_public. Accepted values: "
                    "True or False.") % is_public
            raise webob.exc.HTTPBadRequest(explanation=msg)

        if name:
            utils.check_string_length(name,
                                      'Type name',
                                      min_length=1,
                                      max_length=255)

        if description is not None:
            utils.check_string_length(description,
                                      'Type description',
                                      min_length=0,
                                      max_length=255)

        try:
            group_types.update(context,
                               id,
                               name,
                               description,
                               is_public=is_public)
            # Get the updated
            grp_type = group_types.get_group_type(context, id)
            req.cache_resource(grp_type, name='group_types')
            self._notify_group_type_info(context, 'group_type.update',
                                         grp_type)

        except exception.GroupTypeNotFound as err:
            self._notify_group_type_error(context,
                                          'group_type.update',
                                          err,
                                          id=id)
            raise webob.exc.HTTPNotFound(explanation=six.text_type(err))
        except exception.GroupTypeExists as err:
            self._notify_group_type_error(context,
                                          'group_type.update',
                                          err,
                                          group_type=grp_type)
            raise webob.exc.HTTPConflict(explanation=six.text_type(err))
        except exception.GroupTypeUpdateFailed as err:
            self._notify_group_type_error(context,
                                          'group_type.update',
                                          err,
                                          group_type=grp_type)
            raise webob.exc.HTTPInternalServerError(
                explanation=six.text_type(err))

        return self._view_builder.show(req, grp_type)
Esempio n. 18
0
    def update(self, req, id, body):
        """Update Quota for a particular tenant

        This works for hierarchical and non-hierarchical projects. For
        hierarchical projects only immediate parent admin or the
        CLOUD admin are able to perform an update.

        :param req: request
        :param id: target project id that needs to be updated
        :param body: key, value pair that will be applied to
                     the resources if the update succeeds
        """
        context = req.environ['cinder.context']
        authorize_update(context)
        self.validate_string_length(id, 'quota_set_name',
                                    min_length=1, max_length=255)

        self.assert_valid_body(body, 'quota_set')

        # TODO(wxy): Change "skip_validation"'s default value to  False in
        # Queens.
        # Get the optional argument 'skip_validation' from body,
        # if skip_validation is False, then validate existing resource.
        skip_flag = body.get('skip_validation', True)
        if not strutils.is_valid_boolstr(skip_flag):
            msg = _("Invalid value '%s' for skip_validation.") % skip_flag
            raise exception.InvalidParameterValue(err=msg)
        skip_flag = strutils.bool_from_string(skip_flag)
        if skip_flag:
            LOG.warning("It's unsafe to skip validating the existing "
                        "resource's quota when updating it. Cinder will force "
                        "validate it in Queens, please try to use "
                        "skip_validation=False for quota updating now.")

        target_project_id = id
        bad_keys = []

        # NOTE(ankit): Pass #1 - In this loop for body['quota_set'].items(),
        # we figure out if we have any bad keys.
        for key, value in body['quota_set'].items():
            if (key not in QUOTAS and key not in GROUP_QUOTAS and key not in
                    NON_QUOTA_KEYS):
                bad_keys.append(key)
                continue

        if len(bad_keys) > 0:
            msg = _("Bad key(s) in quota set: %s") % ",".join(bad_keys)
            raise webob.exc.HTTPBadRequest(explanation=msg)

        # Saving off this value since we need to use it multiple times
        use_nested_quotas = QUOTAS.using_nested_quotas()
        if use_nested_quotas:
            # Get the parent_id of the target project to verify whether we are
            # dealing with hierarchical namespace or non-hierarchical namespace
            target_project = quota_utils.get_project_hierarchy(
                context, target_project_id, parents_as_ids=True)
            parent_id = target_project.parent_id

            if parent_id:
                # Get the children of the project which the token is scoped to
                # in order to know if the target_project is in its hierarchy.
                context_project = quota_utils.get_project_hierarchy(
                    context, context.project_id, subtree_as_ids=True,
                    is_admin_project=context.is_admin)
                self._authorize_update_or_delete(context_project,
                                                 target_project.id,
                                                 parent_id)

        # NOTE(ankit): Pass #2 - In this loop for body['quota_set'].keys(),
        # we validate the quota limits to ensure that we can bail out if
        # any of the items in the set is bad. Meanwhile we validate value
        # to ensure that the value can't be lower than number of existing
        # resources.
        quota_values = QUOTAS.get_project_quotas(context, target_project_id,
                                                 defaults=False)
        group_quota_values = GROUP_QUOTAS.get_project_quotas(context,
                                                             target_project_id,
                                                             defaults=False)
        quota_values.update(group_quota_values)
        valid_quotas = {}
        reservations = []
        for key in body['quota_set'].keys():
            if key in NON_QUOTA_KEYS:
                continue

            value = utils.validate_integer(
                body['quota_set'][key], key, min_value=-1,
                max_value=db.MAX_INT)

            # Can't skip the validation of nested quotas since it could mess up
            # hierarchy if parent limit is less than childrens' current usage
            if not skip_flag or use_nested_quotas:
                self._validate_existing_resource(key, value, quota_values)

            if use_nested_quotas:
                try:
                    reservations += self._update_nested_quota_allocated(
                        context, target_project, quota_values, key, value)
                except exception.OverQuota as e:
                    if reservations:
                        db.reservation_rollback(context, reservations)
                    raise webob.exc.HTTPBadRequest(explanation=e.msg)

            valid_quotas[key] = value

        # NOTE(ankit): Pass #3 - At this point we know that all the keys and
        # values are valid and we can iterate and update them all in one shot
        # without having to worry about rolling back etc as we have done
        # the validation up front in the 2 loops above.
        project_quotas = self._get_quotas(context, target_project_id)
        domain_quota_sync.check_valid(context,
                                      target_project_id,
                                      valid_quotas.copy(),
                                      project_quotas.copy())

        for key, value in valid_quotas.items():
            try:
                db.quota_update(context, target_project_id, key, value)
            except exception.ProjectQuotaNotFound:
                db.quota_create(context, target_project_id, key, value)
            except exception.AdminRequired:
                raise webob.exc.HTTPForbidden()

        if reservations:
            db.reservation_commit(context, reservations)
        return {'quota_set': self._get_quotas(context, target_project_id)}
Esempio n. 19
0
    def test_is_valid_boolstr(self):
        self.assertTrue(strutils.is_valid_boolstr('true'))
        self.assertTrue(strutils.is_valid_boolstr('false'))
        self.assertTrue(strutils.is_valid_boolstr('yes'))
        self.assertTrue(strutils.is_valid_boolstr('no'))
        self.assertTrue(strutils.is_valid_boolstr('y'))
        self.assertTrue(strutils.is_valid_boolstr('n'))
        self.assertTrue(strutils.is_valid_boolstr('1'))
        self.assertTrue(strutils.is_valid_boolstr('0'))
        self.assertTrue(strutils.is_valid_boolstr(1))
        self.assertTrue(strutils.is_valid_boolstr(0))

        self.assertFalse(strutils.is_valid_boolstr('maybe'))
        self.assertFalse(strutils.is_valid_boolstr('only on tuesdays'))
Esempio n. 20
0
    def update(self, req, id, body):
        """Update Quota for a particular tenant

        This works for hierarchical and non-hierarchical projects. For
        hierarchical projects only immediate parent admin or the
        CLOUD admin are able to perform an update.

        :param req: request
        :param id: target project id that needs to be updated
        :param body: key, value pair that will be applied to
                     the resources if the update succeeds
        """
        context = req.environ["cinder.context"]
        authorize_update(context)
        self.validate_string_length(id, "quota_set_name", min_length=1, max_length=255)

        self.assert_valid_body(body, "quota_set")

        # Get the optional argument 'skip_validation' from body,
        # if skip_validation is False, then validate existing resource.
        skip_flag = body.get("skip_validation", True)
        if not strutils.is_valid_boolstr(skip_flag):
            msg = _("Invalid value '%s' for skip_validation.") % skip_flag
            raise exception.InvalidParameterValue(err=msg)
        skip_flag = strutils.bool_from_string(skip_flag)

        target_project_id = id
        bad_keys = []

        # NOTE(ankit): Pass #1 - In this loop for body['quota_set'].items(),
        # we figure out if we have any bad keys.
        for key, value in body["quota_set"].items():
            if key not in QUOTAS and key not in NON_QUOTA_KEYS:
                bad_keys.append(key)
                continue

        if len(bad_keys) > 0:
            msg = _("Bad key(s) in quota set: %s") % ",".join(bad_keys)
            raise webob.exc.HTTPBadRequest(explanation=msg)

        # Saving off this value since we need to use it multiple times
        use_nested_quotas = QUOTAS.using_nested_quotas()
        if use_nested_quotas:
            # Get the parent_id of the target project to verify whether we are
            # dealing with hierarchical namespace or non-hierarchical namespace
            target_project = quota_utils.get_project_hierarchy(context, target_project_id, parents_as_ids=True)
            parent_id = target_project.parent_id

            if parent_id:
                # Get the children of the project which the token is scoped to
                # in order to know if the target_project is in its hierarchy.
                context_project = quota_utils.get_project_hierarchy(
                    context, context.project_id, subtree_as_ids=True, is_admin_project=context.is_admin
                )
                self._authorize_update_or_delete(context_project, target_project.id, parent_id)

        # NOTE(ankit): Pass #2 - In this loop for body['quota_set'].keys(),
        # we validate the quota limits to ensure that we can bail out if
        # any of the items in the set is bad. Meanwhile we validate value
        # to ensure that the value can't be lower than number of existing
        # resources.
        quota_values = QUOTAS.get_project_quotas(context, target_project_id, defaults=False)
        valid_quotas = {}
        reservations = []
        for key in body["quota_set"].keys():
            if key in NON_QUOTA_KEYS:
                continue

            value = utils.validate_integer(body["quota_set"][key], key, min_value=-1, max_value=db.MAX_INT)

            # Can't skip the validation of nested quotas since it could mess up
            # hierarchy if parent limit is less than childrens' current usage
            if not skip_flag or use_nested_quotas:
                self._validate_existing_resource(key, value, quota_values)

            if use_nested_quotas:
                try:
                    reservations += self._update_nested_quota_allocated(
                        context, target_project, quota_values, key, value
                    )
                except exception.OverQuota as e:
                    if reservations:
                        db.reservation_rollback(context, reservations)
                    raise webob.exc.HTTPBadRequest(explanation=e.msg)

            valid_quotas[key] = value

        # NOTE(ankit): Pass #3 - At this point we know that all the keys and
        # values are valid and we can iterate and update them all in one shot
        # without having to worry about rolling back etc as we have done
        # the validation up front in the 2 loops above.
        for key, value in valid_quotas.items():
            try:
                db.quota_update(context, target_project_id, key, value)
            except exception.ProjectQuotaNotFound:
                db.quota_create(context, target_project_id, key, value)
            except exception.AdminRequired:
                raise webob.exc.HTTPForbidden()

        if reservations:
            db.reservation_commit(context, reservations)
        return {"quota_set": self._get_quotas(context, target_project_id)}