@locked_volume_operation
def delete_volume(self, context, volume_id, unmanage_only=False, volume=None, cascade=False):
    'Deletes and unexports volume.\n\n        1. Delete a volume(normal case)\n           Delete a volume and update quotas.\n\n        2. Delete a migration volume\n           If deleting the volume in a migration, we want to skip\n           quotas but we need database updates for the volume.\n      '
    context = context.elevated()
    try:
        if (volume is None):
            volume = objects.Volume.get_by_id(context, volume_id)
        else:
            volume.refresh()
    except exception.VolumeNotFound:
        LOG.debug('Attempted delete of non-existent volume: %s', volume_id)
        return
    if (context.project_id != volume.project_id):
        project_id = volume.project_id
    else:
        project_id = context.project_id
    if (volume['attach_status'] == 'attached'):
        raise exception.VolumeAttached(volume_id=volume_id)
    if (vol_utils.extract_host(volume.host) != self.host):
        raise exception.InvalidVolume(reason=_('volume is not local to this node'))
    if (unmanage_only and cascade):
        raise exception.Invalid(reason=_('Unmanage and cascade delete options are mutually exclusive.'))
    is_migrating = (volume.migration_status not in (None, 'error', 'success'))
    is_migrating_dest = (is_migrating and volume.migration_status.startswith('target:'))
    self._notify_about_volume_usage(context, volume, 'delete.start')
    try:
        utils.require_driver_initialized(self.driver)
        self.driver.remove_export(context, volume)
        if unmanage_only:
            self.driver.unmanage(volume)
        elif cascade:
            LOG.debug('Performing cascade delete.')
            snapshots = objects.SnapshotList.get_all_for_volume(context, volume.id)
            for s in snapshots:
                if (s.status != 'deleting'):
                    self._clear_db(context, is_migrating_dest, volume, 'error_deleting')
                    msg = (_("Snapshot %(id)s was found in state %(state)s rather than 'deleting' during cascade delete.") % {'id': s.id, 'state': s.status})
                    raise exception.InvalidSnapshot(reason=msg)
                self.delete_snapshot(context, s)
            LOG.debug('Snapshots deleted, issuing volume delete')
            self.driver.delete_volume(volume)
        else:
            self.driver.delete_volume(volume)
    except exception.VolumeIsBusy:
        LOG.error(_LE('Unable to delete busy volume.'), resource=volume)
        self._clear_db(context, is_migrating_dest, volume, 'available')
        return
    except Exception:
        with excutils.save_and_reraise_exception():
            self._clear_db(context, is_migrating_dest, volume, 'error_deleting')
    if (not is_migrating):
        try:
            reserve_opts = {'volumes': (- 1), 'gigabytes': (- volume.size)}
            QUOTAS.add_volume_type_opts(context, reserve_opts, volume.volume_type_id)
            reservations = QUOTAS.reserve(context, project_id=project_id, **reserve_opts)
        except Exception:
            reservations = None
            LOG.exception(_LE('Failed to update usages deleting volume.'), resource=volume)
    self.db.volume_glance_metadata_delete_by_volume(context, volume_id)
    volume.destroy()
    if (not is_migrating):
        self._notify_about_volume_usage(context, volume, 'delete.end')
        if reservations:
            QUOTAS.commit(context, reservations, project_id=project_id)
        pool = vol_utils.extract_host(volume.host, 'pool')
        if (pool is None):
            pool = (self.driver.configuration.safe_get('volume_backend_name') or vol_utils.extract_host(volume.host, 'pool', True))
        size = volume.size
        try:
            self.stats['pools'][pool]['allocated_capacity_gb'] -= size
        except KeyError:
            self.stats['pools'][pool] = dict(allocated_capacity_gb=(- size))
        self.publish_service_capabilities(context)
    LOG.info(_LI('Deleted volume successfully.'), resource=volume)
Deletes and unexports volume.

1. Delete a volume(normal case)
   Delete a volume and update quotas.

2. Delete a migration volume
   If deleting the volume in a migration, we want to skip
   quotas but we need database updates for the volume.
@locked_volume_operation
def delete_volume(self, context, volume_id, unmanage_only=False, volume=None, cascade=False):
    'Deletes and unexports volume.\n\n        1. Delete a volume(normal case)\n           Delete a volume and update quotas.\n\n        2. Delete a migration volume\n           If deleting the volume in a migration, we want to skip\n           quotas but we need database updates for the volume.\n      '
    context = context.elevated()
    try:
        if (volume is None):
            volume = objects.Volume.get_by_id(context, volume_id)
        else:
            volume.refresh()
    except exception.VolumeNotFound:
        LOG.debug('Attempted delete of non-existent volume: %s', volume_id)
        return
    if (context.project_id != volume.project_id):
        project_id = volume.project_id
    else:
        project_id = context.project_id
    if (volume['attach_status'] == 'attached'):
        raise exception.VolumeAttached(volume_id=volume_id)
    if (vol_utils.extract_host(volume.host) != self.host):
        raise exception.InvalidVolume(reason=_('volume is not local to this node'))
    if (unmanage_only and cascade):
        raise exception.Invalid(reason=_('Unmanage and cascade delete options are mutually exclusive.'))
    is_migrating = (volume.migration_status not in (None, 'error', 'success'))
    is_migrating_dest = (is_migrating and volume.migration_status.startswith('target:'))
    self._notify_about_volume_usage(context, volume, 'delete.start')
    try:
        utils.require_driver_initialized(self.driver)
        self.driver.remove_export(context, volume)
        if unmanage_only:
            self.driver.unmanage(volume)
        elif cascade:
            LOG.debug('Performing cascade delete.')
            snapshots = objects.SnapshotList.get_all_for_volume(context, volume.id)
            for s in snapshots:
                if (s.status != 'deleting'):
                    self._clear_db(context, is_migrating_dest, volume, 'error_deleting')
                    msg = (_("Snapshot %(id)s was found in state %(state)s rather than 'deleting' during cascade delete.") % {'id': s.id, 'state': s.status})
                    raise exception.InvalidSnapshot(reason=msg)
                self.delete_snapshot(context, s)
            LOG.debug('Snapshots deleted, issuing volume delete')
            self.driver.delete_volume(volume)
        else:
            self.driver.delete_volume(volume)
    except exception.VolumeIsBusy:
        LOG.error(_LE('Unable to delete busy volume.'), resource=volume)
        self._clear_db(context, is_migrating_dest, volume, 'available')
        return
    except Exception:
        with excutils.save_and_reraise_exception():
            self._clear_db(context, is_migrating_dest, volume, 'error_deleting')
    if (not is_migrating):
        try:
            reserve_opts = {'volumes': (- 1), 'gigabytes': (- volume.size)}
            QUOTAS.add_volume_type_opts(context, reserve_opts, volume.volume_type_id)
            reservations = QUOTAS.reserve(context, project_id=project_id, **reserve_opts)
        except Exception:
            reservations = None
            LOG.exception(_LE('Failed to update usages deleting volume.'), resource=volume)
    self.db.volume_glance_metadata_delete_by_volume(context, volume_id)
    volume.destroy()
    if (not is_migrating):
        self._notify_about_volume_usage(context, volume, 'delete.end')
        if reservations:
            QUOTAS.commit(context, reservations, project_id=project_id)
        pool = vol_utils.extract_host(volume.host, 'pool')
        if (pool is None):
            pool = (self.driver.configuration.safe_get('volume_backend_name') or vol_utils.extract_host(volume.host, 'pool', True))
        size = volume.size
        try:
            self.stats['pools'][pool]['allocated_capacity_gb'] -= size
        except KeyError:
            self.stats['pools'][pool] = dict(allocated_capacity_gb=(- size))
        self.publish_service_capabilities(context)
    LOG.info(_LI('Deleted volume successfully.'), resource=volume)