'Note:
if file being merged into == active image:
do a blockRebase (pull) operation
else:
do a blockCommit operation
Files must be adjacent in snap chain.
:param instance: instance object reference
:param volume_id: volume UUID
:param snapshot_id: snapshot UUID (unused currently)
:param delete_info: {
\'type\':              \'qcow2\',
\'file_to_merge\':     \'a.img\',
\'merge_target_file\': \'b.img\' or None (if merging file_to_merge into
active image)'

def _volume_snapshot_delete(self, context, instance, volume_id, snapshot_id, delete_info=None):

    LOG.debug('volume_snapshot_delete:    delete_info:    %s', delete_info, instance=instance)
    if (delete_info['type'] != 'qcow2'):
        msg = (_('Unknown    delete_info    type    %s') % delete_info['type'])
        raise exception.InternalError(msg)
    try:
        guest = self._host.get_guest(instance)
    except exception.InstanceNotFound:
        raise exception.InstanceNotRunning(instance_id=instance.uuid)
    my_dev = None
    active_disk = None
    xml = guest.get_xml_desc()
    xml_doc = etree.fromstring(xml)
    device_info = vconfig.LibvirtConfigGuest()
    device_info.parse_dom(xml_doc)
    active_disk_object = None
    for guest_disk in device_info.devices:
        if (guest_disk.root_name != 'disk'):
            continue
        if ((guest_disk.target_dev is None) or (guest_disk.serial is None)):
            continue
        if (guest_disk.serial == volume_id):
            my_dev = guest_disk.target_dev
            active_disk = guest_disk.source_path
            active_protocol = guest_disk.source_protocol
            active_disk_object = guest_disk
            break
    if ((my_dev is None) or ((active_disk is None) and (active_protocol is None))):
        LOG.debug('Domain    XML:    %s', xml, instance=instance)
        msg = (_('Disk    with    id:    %s    not    found    attached    to    instance.') % volume_id)
        raise exception.InternalError(msg)
    LOG.debug('found    device    at    %s', my_dev, instance=instance)
    def _get_snap_dev(filename, backing_store):
        if (filename is None):
            msg = _('filename    cannot    be    None')
            raise exception.InternalError(msg)
        LOG.debug('XML:    %s', xml)
        LOG.debug('active    disk    object:    %s', active_disk_object)
        filename_to_merge = filename
        matched_name = None
        b = backing_store
        index = None
        current_filename = active_disk_object.source_name.split('/')[1]
        if (current_filename == filename_to_merge):
            return (my_dev + '[0]')
        while (b is not None):
            source_filename = b.source_name.split('/')[1]
            if (source_filename == filename_to_merge):
                LOG.debug('found    match:    %s', b.source_name)
                matched_name = b.source_name
                index = b.index
                break
            b = b.backing_store
        if (matched_name is None):
            msg = (_('no    match    found    for    %s') % filename_to_merge)
            raise exception.InternalError(msg)
        LOG.debug('index    of    match    (%s)    is    %s', b.source_name, index)
        my_snap_dev = ('%s[%s]' % (my_dev, index))
        return my_snap_dev
    if (delete_info['merge_target_file'] is None):
        rebase_disk = my_dev
        rebase_base = delete_info['file_to_merge']
        if ((active_protocol is not None) and (rebase_base is not None)):
            rebase_base = _get_snap_dev(rebase_base, active_disk_object.backing_store)
        try:
            libvirt.VIR_DOMAIN_BLOCK_REBASE_RELATIVE
            relative = (rebase_base is not None)
        except AttributeError:
            LOG.warning('Relative    blockrebase    support    was    not    detected.    Continuing    with    old    behaviour.')
            relative = False
        LOG.debug('disk:    %(disk)s,    base:    %(base)s,    bw:    %(bw)s,    relative:    %(relative)s', {'disk': rebase_disk, 'base': rebase_base, 'bw': libvirt_guest.BlockDevice.REBASE_DEFAULT_BANDWIDTH, 'relative': str(relative)}, instance=instance)
        dev = guest.get_block_device(rebase_disk)
        if guest.is_active():
            result = dev.rebase(rebase_base, relative=relative)
            if (result == 0):
                LOG.debug('blockRebase    started    successfully', instance=instance)
            while (not dev.is_job_complete()):
                LOG.debug('waiting    for    blockRebase    job    completion', instance=instance)
                time.sleep(0.5)
        else:
            LOG.debug('Guest    is    not    running    so    doing    a    block    rebase    using    "qemu-img    rebase"', instance=instance)
            self._rebase_with_qemu_img(guest, dev, active_disk_object, rebase_base)
    else:
        my_snap_base = None
        my_snap_top = None
        commit_disk = my_dev
        if (active_protocol is not None):
            my_snap_base = _get_snap_dev(delete_info['merge_target_file'], active_disk_object.backing_store)
            my_snap_top = _get_snap_dev(delete_info['file_to_merge'], active_disk_object.backing_store)
        commit_base = (my_snap_base or delete_info['merge_target_file'])
        commit_top = (my_snap_top or delete_info['file_to_merge'])
        LOG.debug('will    call    blockCommit    with    commit_disk=%(commit_disk)s    commit_base=%(commit_base)s    commit_top=%(commit_top)s    ', {'commit_disk': commit_disk, 'commit_base': commit_base, 'commit_top': commit_top}, instance=instance)
        dev = guest.get_block_device(commit_disk)
        result = dev.commit(commit_base, commit_top, relative=True)
        if (result == 0):
            LOG.debug('blockCommit    started    successfully', instance=instance)
        while (not dev.is_job_complete()):
            LOG.debug('waiting    for    blockCommit    job    completion', instance=instance)
            time.sleep(0.5)
