示例#1
0
def process_reserve_over_quota(context, overs, usages, quotas, size):
    def _consumed(name):
        return (usages[name]['reserved'] + usages[name]['in_use'])

    for over in overs:
        if 'gigabytes' in over:
            msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
                      "%(s_size)sG snapshot (%(d_consumed)dG of "
                      "%(d_quota)dG already consumed).")
            LOG.warning(
                msg, {
                    's_pid': context.project_id,
                    's_size': size,
                    'd_consumed': _consumed(over),
                    'd_quota': quotas[over]
                })
            raise exception.VolumeSizeExceedsAvailableQuota(
                requested=size,
                consumed=_consumed('gigabytes'),
                quota=quotas['gigabytes'])
        elif 'snapshots' in over:
            msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
                      "snapshot (%(d_consumed)d snapshots "
                      "already consumed).")
            LOG.warning(msg, {
                's_pid': context.project_id,
                'd_consumed': _consumed(over)
            })
            raise exception.SnapshotLimitExceeded(allowed=quotas[over])
示例#2
0
    def execute(self, context, size, volume_type_id, optional_args):
        try:
            values = {'per_volume_gigabytes': size}
            QUOTAS.limit_check(context,
                               project_id=context.project_id,
                               **values)
        except exception.OverQuota as e:
            quotas = e.kwargs['quotas']
            raise exception.VolumeSizeExceedsLimit(
                size=size, limit=quotas['per_volume_gigabytes'])

        try:
            reserve_opts = {'volumes': 1, 'gigabytes': size}
            QUOTAS.add_volume_type_opts(context, reserve_opts, volume_type_id)
            reservations = QUOTAS.reserve(context, **reserve_opts)
            return {
                'reservations': reservations,
            }
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            quotas = e.kwargs['quotas']
            usages = e.kwargs['usages']

            def _consumed(name):
                return usages[name]['reserved'] + usages[name]['in_use']

            def _is_over(name):
                for over in overs:
                    if name in over:
                        return True
                return False

            if _is_over('gigabytes'):
                msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
                          "%(s_size)sG volume (%(d_consumed)dG "
                          "of %(d_quota)dG already consumed)")
                LOG.warning(
                    msg, {
                        's_pid': context.project_id,
                        's_size': size,
                        'd_consumed': _consumed('gigabytes'),
                        'd_quota': quotas['gigabytes']
                    })
                raise exception.VolumeSizeExceedsAvailableQuota(
                    requested=size,
                    consumed=_consumed('gigabytes'),
                    quota=quotas['gigabytes'])
            elif _is_over('volumes'):
                msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
                          "volume (%(d_consumed)d volumes "
                          "already consumed)")
                LOG.warning(
                    msg, {
                        's_pid': context.project_id,
                        'd_consumed': _consumed('volumes')
                    })
                raise exception.VolumeLimitExceeded(allowed=quotas['volumes'])
            else:
                # If nothing was reraised, ensure we reraise the initial error
                raise
示例#3
0
def get_volume_type_reservation(ctxt,
                                volume,
                                type_id,
                                reserve_vol_type_only=False):
    from cinder import quota
    QUOTAS = quota.QUOTAS
    # Reserve quotas for the given volume type
    try:
        reserve_opts = {'volumes': 1, 'gigabytes': volume['size']}
        QUOTAS.add_volume_type_opts(ctxt, reserve_opts, type_id)
        # If reserve_vol_type_only is True, just reserve volume_type quota,
        # not volume quota.
        if reserve_vol_type_only:
            reserve_opts.pop('volumes')
            reserve_opts.pop('gigabytes')
        # Note that usually the project_id on the volume will be the same as
        # the project_id in the context. But, if they are different then the
        # reservations must be recorded against the project_id that owns the
        # volume.
        project_id = volume['project_id']
        reservations = QUOTAS.reserve(ctxt,
                                      project_id=project_id,
                                      **reserve_opts)
    except exception.OverQuota as e:
        overs = e.kwargs['overs']
        usages = e.kwargs['usages']
        quotas = e.kwargs['quotas']

        def _consumed(name):
            return (usages[name]['reserved'] + usages[name]['in_use'])

        for over in overs:
            if 'gigabytes' in over:
                s_size = volume['size']
                d_quota = quotas[over]
                d_consumed = _consumed(over)
                LOG.warning(
                    _LW("Quota exceeded for %(s_pid)s, tried to create "
                        "%(s_size)sG volume - (%(d_consumed)dG of "
                        "%(d_quota)dG already consumed)"), {
                            's_pid': ctxt.project_id,
                            's_size': s_size,
                            'd_consumed': d_consumed,
                            'd_quota': d_quota
                        })
                raise exception.VolumeSizeExceedsAvailableQuota(
                    requested=s_size, quota=d_quota, consumed=d_consumed)
            elif 'volumes' in over:
                LOG.warning(
                    _LW("Quota exceeded for %(s_pid)s, tried to create "
                        "volume (%(d_consumed)d volumes "
                        "already consumed)"), {
                            's_pid': ctxt.project_id,
                            'd_consumed': _consumed(over)
                        })
                raise exception.VolumeLimitExceeded(allowed=quotas[over])
    return reservations
示例#4
0
    def extend(self, context, volume, new_size):
        if volume['status'] != 'available':
            msg = _('Volume status must be available to extend.')
            raise exception.InvalidVolume(reason=msg)

        size_increase = (int(new_size)) - volume['size']
        if size_increase <= 0:
            msg = (_("New size for extend must be greater "
                     "than current size. (current: %(size)s, "
                     "extended: %(new_size)s)") % {
                         'new_size': new_size,
                         'size': volume['size']
                     })
            raise exception.InvalidInput(reason=msg)

        try:
            reservations = QUOTAS.reserve(context, gigabytes=+size_increase)
        except exception.OverQuota as exc:
            usages = exc.kwargs['usages']
            quotas = exc.kwargs['quotas']

            def _consumed(name):
                return (usages[name]['reserved'] + usages[name]['in_use'])

            msg = _("Quota exceeded for %(s_pid)s, tried to extend volume by "
                    "%(s_size)sG, (%(d_consumed)dG of %(d_quota)dG already "
                    "consumed).")
            LOG.error(
                msg % {
                    's_pid': context.project_id,
                    's_size': size_increase,
                    'd_consumed': _consumed('gigabytes'),
                    'd_quota': quotas['gigabytes']
                })
            raise exception.VolumeSizeExceedsAvailableQuota(
                requested=size_increase,
                consumed=_consumed('gigabytes'),
                quota=quotas['gigabytes'])

        self.update(context, volume, {'status': 'extending'})
        self.volume_rpcapi.extend_volume(context, volume, new_size,
                                         reservations)
示例#5
0
def get_volume_type_reservation(ctxt, volume, type_id):
    # Reserve quotas for the given volume type
    try:
        reserve_opts = {'volumes': 1, 'gigabytes': volume['size']}
        QUOTAS.add_volume_type_opts(ctxt, reserve_opts, type_id)
        reservations = QUOTAS.reserve(ctxt, **reserve_opts)
    except exception.OverQuota as e:
        overs = e.kwargs['overs']
        usages = e.kwargs['usages']
        quotas = e.kwargs['quotas']

        def _consumed(name):
            return (usages[name]['reserved'] + usages[name]['in_use'])

        for over in overs:
            if 'gigabytes' in over:
                s_size = volume['size']
                d_quota = quotas[over]
                d_consumed = _consumed(over)
                msg = _("Quota exceeded for %(s_pid)s, tried to create "
                        "%(s_size)sG volume - (%(d_consumed)dG of "
                        "%(d_quota)dG already consumed)")
                LOG.warn(
                    msg % {
                        's_pid': ctxt.project_id,
                        's_size': s_size,
                        'd_consumed': d_consumed,
                        'd_quota': d_quota
                    })
                raise exception.VolumeSizeExceedsAvailableQuota(
                    requested=s_size, quota=d_quota, consumed=d_consumed)
            elif 'volumes' in over:
                msg = _("Quota exceeded for %(s_pid)s, tried to create "
                        "volume (%(d_consumed)d volumes "
                        "already consumed)")

                LOG.warn(msg % {
                    's_pid': ctxt.project_id,
                    'd_consumed': _consumed(over)
                })
                raise exception.VolumeLimitExceeded(allowed=quotas[over])
    return reservations
示例#6
0
 def fake_transfer_api_accept_throwing_VolumeSizeExceedsAvailableQuota(
         cls, context, transfer, volume_id):
     raise exception.VolumeSizeExceedsAvailableQuota(requested='2',
                                                     consumed='2',
                                                     quota='3')
示例#7
0
文件: api.py 项目: wangxiyuan/cinder
    def accept(self, context, transfer_id, auth_key):
        """Accept a volume that has been offered for transfer."""
        # We must use an elevated context to see the volume that is still
        # owned by the donor.
        volume_api.check_policy(context, 'accept_transfer')
        transfer = self.db.transfer_get(context.elevated(), transfer_id)

        crypt_hash = self._get_crypt_hash(transfer['salt'], auth_key)
        if crypt_hash != transfer['crypt_hash']:
            msg = (_("Attempt to transfer %s with invalid auth key.") %
                   transfer_id)
            LOG.error(msg)
            raise exception.InvalidAuthKey(reason=msg)

        volume_id = transfer['volume_id']
        vol_ref = self.db.volume_get(context.elevated(), volume_id)
        if vol_ref['consistencygroup_id']:
            msg = _("Volume %s must not be part of a consistency "
                    "group.") % vol_ref['id']
            LOG.error(msg)
            raise exception.InvalidVolume(reason=msg)

        volume_utils.notify_about_volume_usage(context, vol_ref,
                                               "transfer.accept.start")

        try:
            reserve_opts = {'volumes': 1, 'gigabytes': vol_ref.size}
            QUOTAS.add_volume_type_opts(context, reserve_opts,
                                        vol_ref.volume_type_id)
            reservations = QUOTAS.reserve(context, **reserve_opts)
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            usages = e.kwargs['usages']
            quotas = e.kwargs['quotas']

            def _consumed(name):
                return (usages[name]['reserved'] + usages[name]['in_use'])

            for over in overs:
                if 'gigabytes' in over:
                    msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
                              "%(s_size)sG volume (%(d_consumed)dG of "
                              "%(d_quota)dG already consumed)")
                    LOG.warning(
                        msg, {
                            's_pid': context.project_id,
                            's_size': vol_ref['size'],
                            'd_consumed': _consumed(over),
                            'd_quota': quotas[over]
                        })
                    raise exception.VolumeSizeExceedsAvailableQuota(
                        requested=vol_ref['size'],
                        consumed=_consumed(over),
                        quota=quotas[over])
                elif 'volumes' in over:
                    msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
                              "volume (%(d_consumed)d volumes "
                              "already consumed)")
                    LOG.warning(msg, {
                        's_pid': context.project_id,
                        'd_consumed': _consumed(over)
                    })
                    raise exception.VolumeLimitExceeded(allowed=quotas[over],
                                                        name=over)

        try:
            donor_id = vol_ref['project_id']
            reserve_opts = {'volumes': -1, 'gigabytes': -vol_ref.size}
            QUOTAS.add_volume_type_opts(context, reserve_opts,
                                        vol_ref.volume_type_id)
            donor_reservations = QUOTAS.reserve(context.elevated(),
                                                project_id=donor_id,
                                                **reserve_opts)
        except Exception:
            donor_reservations = None
            LOG.exception(
                _LE("Failed to update quota donating volume"
                    " transfer id %s"), transfer_id)

        try:
            # Transfer ownership of the volume now, must use an elevated
            # context.
            self.volume_api.accept_transfer(context, vol_ref, context.user_id,
                                            context.project_id)
            self.db.transfer_accept(context.elevated(), transfer_id,
                                    context.user_id, context.project_id)
            QUOTAS.commit(context, reservations)
            if donor_reservations:
                QUOTAS.commit(context, donor_reservations, project_id=donor_id)
            LOG.info(_LI("Volume %s has been transferred."), volume_id)
        except Exception:
            with excutils.save_and_reraise_exception():
                QUOTAS.rollback(context, reservations)
                if donor_reservations:
                    QUOTAS.rollback(context,
                                    donor_reservations,
                                    project_id=donor_id)

        vol_ref = self.db.volume_get(context, volume_id)
        volume_utils.notify_about_volume_usage(context, vol_ref,
                                               "transfer.accept.end")
        return {
            'id': transfer_id,
            'display_name': transfer['display_name'],
            'volume_id': vol_ref['id']
        }
示例#8
0
    def _create_snapshot(self,
                         context,
                         volume,
                         name,
                         description,
                         force=False,
                         metadata=None):
        check_policy(context, 'create_snapshot', volume)

        if volume['migration_status'] is not None:
            # Volume is migrating, wait until done
            msg = _("Snapshot cannot be created while volume is migrating")
            raise exception.InvalidVolume(reason=msg)

        if ((not force) and (volume['status'] != "available")):
            msg = _("must be available")
            raise exception.InvalidVolume(reason=msg)

        try:
            if CONF.no_snapshot_gb_quota:
                reserve_opts = {'snapshots': 1}
            else:
                reserve_opts = {'snapshots': 1, 'gigabytes': volume['size']}
            QUOTAS.add_volume_type_opts(context, reserve_opts,
                                        volume.get('volume_type_id'))
            reservations = QUOTAS.reserve(context, **reserve_opts)
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            usages = e.kwargs['usages']
            quotas = e.kwargs['quotas']

            def _consumed(name):
                return (usages[name]['reserved'] + usages[name]['in_use'])

            for over in overs:
                if 'gigabytes' in over:
                    msg = _("Quota exceeded for %(s_pid)s, tried to create "
                            "%(s_size)sG snapshot (%(d_consumed)dG of "
                            "%(d_quota)dG already consumed)")
                    LOG.warn(
                        msg % {
                            's_pid': context.project_id,
                            's_size': volume['size'],
                            'd_consumed': _consumed(over),
                            'd_quota': quotas[over]
                        })
                    raise exception.VolumeSizeExceedsAvailableQuota(
                        requested=volume['size'],
                        consumed=_consumed('gigabytes'),
                        quota=quotas['gigabytes'])
                elif 'snapshots' in over:
                    msg = _("Quota exceeded for %(s_pid)s, tried to create "
                            "snapshot (%(d_consumed)d snapshots "
                            "already consumed)")

                    LOG.warn(msg % {
                        's_pid': context.project_id,
                        'd_consumed': _consumed(over)
                    })
                    raise exception.SnapshotLimitExceeded(allowed=quotas[over])

        self._check_metadata_properties(metadata)
        options = {
            'volume_id': volume['id'],
            'user_id': context.user_id,
            'project_id': context.project_id,
            'status': "creating",
            'progress': '0%',
            'volume_size': volume['size'],
            'display_name': name,
            'display_description': description,
            'volume_type_id': volume['volume_type_id'],
            'encryption_key_id': volume['encryption_key_id'],
            'metadata': metadata
        }

        try:
            snapshot = self.db.snapshot_create(context, options)
            QUOTAS.commit(context, reservations)
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    self.db.snapshot_destroy(context, volume['id'])
                finally:
                    QUOTAS.rollback(context, reservations)

        self.volume_rpcapi.create_snapshot(context, volume, snapshot)

        return snapshot
示例#9
0
    def execute(self, context, size, volume_type_id, optional_args):
        try:
            values = {'per_volume_gigabytes': size}
            QUOTAS.limit_check(context,
                               project_id=context.project_id,
                               **values)
        except exception.OverQuota as e:
            quotas = e.kwargs['quotas']
            raise exception.VolumeSizeExceedsLimit(
                size=size, limit=quotas['per_volume_gigabytes'])

        try:
            reserve_opts = {'volumes': 1, 'gigabytes': size}
            QUOTAS.add_volume_type_opts(context, reserve_opts, volume_type_id)
            reservations = QUOTAS.reserve(context, **reserve_opts)
            return {
                'reservations': reservations,
            }
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            quotas = e.kwargs['quotas']
            usages = e.kwargs['usages']

            def _consumed(name):
                usage = usages[name]
                return usage['reserved'] + usage['in_use'] + usage.get(
                    'allocated', 0)

            def _get_over(name):
                for over in overs:
                    if name in over:
                        return over
                return None

            over_name = _get_over('gigabytes')
            exceeded_vol_limit_name = _get_over('volumes')
            if over_name:
                # TODO(mc_nair): improve error message for child -1 limit
                msg = _LW("Quota exceeded for %(s_pid)s, tried to create "
                          "%(s_size)sG volume (%(d_consumed)dG "
                          "of %(d_quota)dG already consumed)")
                LOG.warning(
                    msg, {
                        's_pid': context.project_id,
                        's_size': size,
                        'd_consumed': _consumed(over_name),
                        'd_quota': quotas[over_name]
                    })
                raise exception.VolumeSizeExceedsAvailableQuota(
                    name=over_name,
                    requested=size,
                    consumed=_consumed(over_name),
                    quota=quotas[over_name])
            elif exceeded_vol_limit_name:
                msg = _LW("Quota %(s_name)s exceeded for %(s_pid)s, tried "
                          "to create volume (%(d_consumed)d volume(s) "
                          "already consumed).")
                LOG.warning(
                    msg, {
                        's_name': exceeded_vol_limit_name,
                        's_pid': context.project_id,
                        'd_consumed': _consumed(exceeded_vol_limit_name)
                    })
                # TODO(mc_nair): improve error message for child -1 limit
                raise exception.VolumeLimitExceeded(
                    allowed=quotas[exceeded_vol_limit_name],
                    name=exceeded_vol_limit_name)
            else:
                # If nothing was reraised, ensure we reraise the initial error
                raise
示例#10
0
 def fake_transfer_api_accept_throwing_VolumeSizeExceedsAvailableQuota(
         cls, context, transfer, volume_id):
     raise exception.VolumeSizeExceedsAvailableQuota()
示例#11
0
 def fake_backup_api_restore_throwing_VolumeSizeExceedsAvailableQuota(
         cls, context, backup_id, volume_id):
     raise exception.VolumeSizeExceedsAvailableQuota(requested='2',
                                                     consumed='2',
                                                     quota='3')
示例#12
0
文件: api.py 项目: tek-life/cinder
    def create(self, context, size, name, description, snapshot=None,
                image_id=None, volume_type=None, metadata=None,
                availability_zone=None):
        check_policy(context, 'create')
        if snapshot is not None:
            if snapshot['status'] != "available":
                msg = _("status must be available")
                raise exception.InvalidSnapshot(reason=msg)
            if not size:
                size = snapshot['volume_size']

            snapshot_id = snapshot['id']
        else:
            snapshot_id = None

        def as_int(s):
            try:
                return int(s)
            except ValueError:
                return s

        # tolerate size as stringified int
        size = as_int(size)

        if not isinstance(size, int) or size <= 0:
            msg = (_("Volume size '%s' must be an integer and greater than 0")
                   % size)
            raise exception.InvalidInput(reason=msg)
        try:
            reservations = QUOTAS.reserve(context, volumes=1, gigabytes=size)
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            usages = e.kwargs['usages']
            quotas = e.kwargs['quotas']

            def _consumed(name):
                return (usages[name]['reserved'] + usages[name]['in_use'])

            pid = context.project_id
            if 'gigabytes' in overs:
                consumed = _consumed('gigabytes')
                quota = quotas['gigabytes']
                LOG.warn(_("Quota exceeded for %(pid)s, tried to create "
                           "%(size)sG volume (%(consumed)dG of %(quota)dG "
                           "already consumed)") % locals())
                raise exception.VolumeSizeExceedsAvailableQuota()
            elif 'volumes' in overs:
                consumed = _consumed('volumes')
                LOG.warn(_("Quota exceeded for %(pid)s, tried to create "
                           "volume (%(consumed)d volumes already consumed)")
                           % locals())
                raise exception.VolumeLimitExceeded(allowed=quotas['volumes'])

        if image_id:
            # check image existence
            image_meta = self.image_service.show(context, image_id)
            image_size_in_gb = (int(image_meta['size']) + GB - 1) / GB
            #check image size is not larger than volume size.
            if image_size_in_gb > size:
                msg = _('Size of specified image is larger than volume size.')
                raise exception.InvalidInput(reason=msg)

        if availability_zone is None:
            availability_zone = FLAGS.storage_availability_zone

        if volume_type is None:
            volume_type_id = None
        else:
            volume_type_id = volume_type.get('id', None)

        options = {
            'size': size,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'snapshot_id': snapshot_id,
            'availability_zone': availability_zone,
            'status': "creating",
            'attach_status': "detached",
            'display_name': name,
            'display_description': description,
            'volume_type_id': volume_type_id,
            'metadata': metadata,
            }

        volume = self.db.volume_create(context, options)

        QUOTAS.commit(context, reservations)

        self._cast_create_volume(context, volume['id'], snapshot_id,
                                 image_id)
        return volume
示例#13
0
 def fake_backup_api_restore_throwing_VolumeSizeExceedsAvailableQuota(
         cls, context, backup_id, volume_id):
     raise exception.VolumeSizeExceedsAvailableQuota()
示例#14
0
文件: api.py 项目: jjacob512/cinder-1
    def create(self,
               context,
               size,
               name,
               description,
               snapshot=None,
               image_id=None,
               volume_type=None,
               metadata=None,
               availability_zone=None,
               source_volume=None,
               scheduler_hints=None):

        exclusive_options = (snapshot, image_id, source_volume)
        exclusive_options_set = sum(1 for option in exclusive_options
                                    if option is not None)
        if exclusive_options_set > 1:
            msg = (_("May specify only one of snapshot, imageRef "
                     "or source volume"))
            raise exception.InvalidInput(reason=msg)

        check_policy(context, 'create')
        if snapshot is not None:
            if snapshot['status'] != "available":
                msg = _("status must be available")
                raise exception.InvalidSnapshot(reason=msg)
            if not size:
                size = snapshot['volume_size']
            elif size < snapshot['volume_size']:
                msg = _("Volume size cannot be lesser than"
                        " the Snapshot size")
                raise exception.InvalidInput(reason=msg)
            snapshot_id = snapshot['id']
        else:
            snapshot_id = None

        if source_volume is not None:
            if source_volume['status'] == "error":
                msg = _("Unable to clone volumes that are in an error state")
                raise exception.InvalidSourceVolume(reason=msg)
            if not size:
                size = source_volume['size']
            else:
                if size < source_volume['size']:
                    msg = _("Clones currently must be "
                            ">= original volume size.")
                    raise exception.InvalidInput(reason=msg)
            source_volid = source_volume['id']
        else:
            source_volid = None

        def as_int(s):
            try:
                return int(s)
            except (ValueError, TypeError):
                return s

        # tolerate size as stringified int
        size = as_int(size)

        if not isinstance(size, int) or size <= 0:
            msg = (
                _("Volume size '%s' must be an integer and greater than 0") %
                size)
            raise exception.InvalidInput(reason=msg)

        if (image_id and not (source_volume or snapshot)):
            # check image existence
            image_meta = self.image_service.show(context, image_id)
            image_size_in_gb = (int(image_meta['size']) + GB - 1) / GB
            #check image size is not larger than volume size.
            if image_size_in_gb > size:
                msg = _('Size of specified image is larger than volume size.')
                raise exception.InvalidInput(reason=msg)
            # Check image minDisk requirement is met for the particular volume
            if size < image_meta.get('min_disk', 0):
                msg = _('Image minDisk size is larger than the volume size.')
                raise exception.InvalidInput(reason=msg)

        if availability_zone is None:
            if snapshot is not None:
                availability_zone = snapshot['volume']['availability_zone']
            elif source_volume is not None:
                availability_zone = source_volume['availability_zone']
            else:
                availability_zone = CONF.storage_availability_zone
        else:
            self._check_availabilty_zone(availability_zone)

        if CONF.cloned_volume_same_az:
            if (snapshot and snapshot['volume']['availability_zone'] !=
                    availability_zone):
                msg = _("Volume must be in the same "
                        "availability zone as the snapshot")
                raise exception.InvalidInput(reason=msg)
            elif source_volume and \
                    source_volume['availability_zone'] != availability_zone:
                msg = _("Volume must be in the same "
                        "availability zone as the source volume")
                raise exception.InvalidInput(reason=msg)

        if not volume_type and not source_volume:
            volume_type = volume_types.get_default_volume_type()

        if not volume_type and source_volume:
            volume_type_id = source_volume['volume_type_id']
        else:
            volume_type_id = volume_type.get('id')

        try:
            reserve_opts = {'volumes': 1, 'gigabytes': size}
            QUOTAS.add_volume_type_opts(context, reserve_opts, volume_type_id)
            reservations = QUOTAS.reserve(context, **reserve_opts)
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            usages = e.kwargs['usages']
            quotas = e.kwargs['quotas']

            def _consumed(name):
                return (usages[name]['reserved'] + usages[name]['in_use'])

            for over in overs:
                if 'gigabytes' in over:
                    msg = _("Quota exceeded for %(s_pid)s, tried to create "
                            "%(s_size)sG volume (%(d_consumed)dG of "
                            "%(d_quota)dG already consumed)")
                    LOG.warn(
                        msg % {
                            's_pid': context.project_id,
                            's_size': size,
                            'd_consumed': _consumed(over),
                            'd_quota': quotas[over]
                        })
                    raise exception.VolumeSizeExceedsAvailableQuota()
                elif 'volumes' in over:
                    msg = _("Quota exceeded for %(s_pid)s, tried to create "
                            "volume (%(d_consumed)d volumes"
                            "already consumed)")
                    LOG.warn(msg % {
                        's_pid': context.project_id,
                        'd_consumed': _consumed(over)
                    })
                    raise exception.VolumeLimitExceeded(allowed=quotas[over])

        self._check_metadata_properties(context, metadata)
        options = {
            'size': size,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'snapshot_id': snapshot_id,
            'availability_zone': availability_zone,
            'status': "creating",
            'attach_status': "detached",
            'display_name': name,
            'display_description': description,
            'volume_type_id': volume_type_id,
            'metadata': metadata,
            'source_volid': source_volid
        }

        try:
            volume = self.db.volume_create(context, options)
            QUOTAS.commit(context, reservations)
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    self.db.volume_destroy(context, volume['id'])
                finally:
                    QUOTAS.rollback(context, reservations)

        request_spec = {
            'volume_properties': options,
            'volume_type': volume_type,
            'volume_id': volume['id'],
            'snapshot_id': volume['snapshot_id'],
            'image_id': image_id,
            'source_volid': volume['source_volid']
        }

        if scheduler_hints:
            filter_properties = {'scheduler_hints': scheduler_hints}
        else:
            filter_properties = {}

        self._cast_create_volume(context, request_spec, filter_properties)

        return volume
示例#15
0
    def create(self,
               context,
               size,
               name,
               description,
               snapshot=None,
               image_id=None,
               volume_type=None,
               metadata=None,
               availability_zone=None,
               source_volume=None):

        if ((snapshot is not None) and (source_volume is not None)):
            msg = (_("May specify either snapshot, "
                     "or src volume but not both!"))
            raise exception.InvalidInput(reason=msg)

        check_policy(context, 'create')
        if snapshot is not None:
            if snapshot['status'] != "available":
                msg = _("status must be available")
                raise exception.InvalidSnapshot(reason=msg)
            if not size:
                size = snapshot['volume_size']

            snapshot_id = snapshot['id']
        else:
            snapshot_id = None

        if source_volume is not None:
            if source_volume['status'] == "error":
                msg = _("Unable to clone volumes that are in an error state")
                raise exception.InvalidSourceVolume(reason=msg)
            if not size:
                size = source_volume['size']
            else:
                if size < source_volume['size']:
                    msg = _("Clones currently must be "
                            ">= original volume size.")
                    raise exception.InvalidInput(reason=msg)
            source_volid = source_volume['id']
        else:
            source_volid = None

        def as_int(s):
            try:
                return int(s)
            except (ValueError, TypeError):
                return s

        # tolerate size as stringified int
        size = as_int(size)

        if not isinstance(size, int) or size <= 0:
            msg = (
                _("Volume size '%s' must be an integer and greater than 0") %
                size)
            raise exception.InvalidInput(reason=msg)

        if (image_id and not (source_volume or snapshot)):
            # check image existence
            image_meta = self.image_service.show(context, image_id)
            image_size_in_gb = (int(image_meta['size']) + GB - 1) / GB
            #check image size is not larger than volume size.
            if image_size_in_gb > size:
                msg = _('Size of specified image is larger than volume size.')
                raise exception.InvalidInput(reason=msg)

        try:
            reservations = QUOTAS.reserve(context, volumes=1, gigabytes=size)
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            usages = e.kwargs['usages']
            quotas = e.kwargs['quotas']

            def _consumed(name):
                return (usages[name]['reserved'] + usages[name]['in_use'])

            if 'gigabytes' in overs:
                msg = _("Quota exceeded for %(s_pid)s, tried to create "
                        "%(s_size)sG volume (%(d_consumed)dG of %(d_quota)dG "
                        "already consumed)")
                LOG.warn(
                    msg % {
                        's_pid': context.project_id,
                        's_size': size,
                        'd_consumed': _consumed('gigabytes'),
                        'd_quota': quotas['gigabytes']
                    })
                raise exception.VolumeSizeExceedsAvailableQuota()
            elif 'volumes' in overs:
                msg = _("Quota exceeded for %(s_pid)s, tried to create "
                        "volume (%(d_consumed)d volumes"
                        "already consumed)")
                LOG.warn(
                    msg % {
                        's_pid': context.project_id,
                        'd_consumed': _consumed('volumes')
                    })
                raise exception.VolumeLimitExceeded(allowed=quotas['volumes'])

        if availability_zone is None:
            availability_zone = FLAGS.storage_availability_zone

        if not volume_type and not source_volume:
            volume_type = volume_types.get_default_volume_type()

        if not volume_type and source_volume:
            volume_type_id = source_volume['volume_type_id']
        else:
            volume_type_id = volume_type.get('id')

        self._check_metadata_properties(context, metadata)
        options = {
            'size': size,
            'user_id': context.user_id,
            'project_id': context.project_id,
            'snapshot_id': snapshot_id,
            'availability_zone': availability_zone,
            'status': "creating",
            'attach_status': "detached",
            'display_name': name,
            'display_description': description,
            'volume_type_id': volume_type_id,
            'metadata': metadata,
            'source_volid': source_volid
        }

        try:
            volume = self.db.volume_create(context, options)
            QUOTAS.commit(context, reservations)
        except Exception:
            with excutils.save_and_reraise_exception():
                try:
                    self.db.volume_destroy(context, volume['id'])
                finally:
                    QUOTAS.rollback(context, reservations)

        request_spec = {
            'volume_properties': options,
            'volume_type': volume_type,
            'volume_id': volume['id'],
            'snapshot_id': volume['snapshot_id'],
            'image_id': image_id,
            'source_volid': volume['source_volid']
        }

        filter_properties = {}

        self._cast_create_volume(context, request_spec, filter_properties)

        return volume
示例#16
0
文件: api.py 项目: jjacob512/cinder-1
    def accept(self, context, transfer_id, auth_key):
        """Accept a volume that has been offered for transfer."""
        # We must use an elevated context to see the volume that is still
        # owned by the donor.
        volume_api.check_policy(context, 'accept_transfer')
        transfer = self.db.transfer_get(context.elevated(), transfer_id)

        crypt_hash = self._get_crypt_hash(transfer['salt'], auth_key)
        if crypt_hash != transfer['crypt_hash']:
            msg = (_("Attempt to transfer %s with invalid auth key.") %
                   transfer_id)
            LOG.error(msg)
            raise exception.InvalidAuthKey(reason=msg)

        volume_id = transfer['volume_id']
        vol_ref = self.db.volume_get(context.elevated(), volume_id)

        try:
            reservations = QUOTAS.reserve(context,
                                          volumes=1,
                                          gigabytes=vol_ref['size'])
        except exception.OverQuota as e:
            overs = e.kwargs['overs']
            usages = e.kwargs['usages']
            quotas = e.kwargs['quotas']

            def _consumed(name):
                return (usages[name]['reserved'] + usages[name]['in_use'])

            if 'gigabytes' in overs:
                msg = _("Quota exceeded for %(s_pid)s, tried to create "
                        "%(s_size)sG volume (%(d_consumed)dG of %(d_quota)dG "
                        "already consumed)")
                LOG.warn(
                    msg % {
                        's_pid': context.project_id,
                        's_size': vol_ref['size'],
                        'd_consumed': _consumed('gigabytes'),
                        'd_quota': quotas['gigabytes']
                    })
                raise exception.VolumeSizeExceedsAvailableQuota()
            elif 'volumes' in overs:
                msg = _("Quota exceeded for %(s_pid)s, tried to create "
                        "volume (%(d_consumed)d volumes "
                        "already consumed)")
                LOG.warn(
                    msg % {
                        's_pid': context.project_id,
                        'd_consumed': _consumed('volumes')
                    })
                raise exception.VolumeLimitExceeded(allowed=quotas['volumes'])
        try:
            donor_id = vol_ref['project_id']
            donor_reservations = QUOTAS.reserve(context.elevated(),
                                                project_id=donor_id,
                                                volumes=-1,
                                                gigabytes=-vol_ref['size'])
        except Exception:
            donor_reservations = None
            LOG.exception(
                _("Failed to update quota donating volume"
                  "transfer id %s") % transfer_id)

        try:
            # Transfer ownership of the volume now, must use an elevated
            # context.
            self.volume_api.accept_transfer(context, vol_ref)
            self.db.transfer_accept(context.elevated(), transfer_id,
                                    context.user_id, context.project_id)
            QUOTAS.commit(context, reservations)
            if donor_reservations:
                QUOTAS.commit(context, donor_reservations, project_id=donor_id)
            LOG.info(_("Volume %s has been transferred.") % volume_id)
        except Exception:
            with excutils.save_and_reraise_exception():
                QUOTAS.rollback(context, reservations)
                if donor_reservations:
                    QUOTAS.rollback(context,
                                    donor_reservations,
                                    project_id=donor_id)

        vol_ref = self.db.volume_get(context, volume_id)
        return {
            'id': transfer_id,
            'display_name': transfer['display_name'],
            'volume_id': vol_ref['id']
        }