'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.'

@coordination.synchronized('{volume.id}-{f_name}')
@objects.Volume.set_workers
def delete_volume(self, context, volume, unmanage_only=False, cascade=False):

    context = context.elevated()
    try:
        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'] == fields.VolumeAttachStatus.ATTACHED):
        raise exception.VolumeAttached(volume_id=volume.id)
    self._check_is_our_resource(volume)
    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:'))
    notification = 'delete.start'
    if unmanage_only:
        notification = 'unmanage.start'
    self._notify_about_volume_usage(context, volume, notification)
    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 != fields.SnapshotStatus.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('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():
            new_status = 'error_deleting'
            if (unmanage_only is True):
                new_status = 'error_unmanaging'
            self._clear_db(context, is_migrating_dest, volume, new_status)
    if (not is_migrating):
        try:
            reservations = None
            if (volume.status != 'error_managing_deleting'):
                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:
            LOG.exception('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):
        notification = 'delete.end'
        if unmanage_only:
            notification = 'unmanage.end'
        self._notify_about_volume_usage(context, volume, notification)
        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)
    msg = 'Deleted    volume    successfully.'
    if unmanage_only:
        msg = 'Unmanaged    volume    successfully.'
    LOG.info(msg, resource=volume)
