'Create an incremental backup from an RBD image.'

def _backup_rbd(self, backup, volume_file, volume_name, length):

    rbd_user = volume_file.rbd_user
    rbd_pool = volume_file.rbd_pool
    rbd_conf = volume_file.rbd_conf
    source_rbd_image = volume_file.rbd_image
    volume_id = backup.volume_id
    updates = {}
    from_snap = self._get_most_recent_snap(source_rbd_image)
    LOG.debug("Using    --from-snap    '%(snap)s'    for    incremental    backup    of    volume    %(volume)s.", {'snap': from_snap, 'volume': volume_id})
    base_name = self._get_backup_base_name(volume_id, diff_format=True)
    image_created = False
    with rbd_driver.RADOSClient(self, backup.container) as client:
        if (base_name not in self.rbd.RBD().list(ioctx=client.ioctx)):
            if from_snap:
                LOG.debug("Source    snapshot    '%(snapshot)s'    of    volume    %(volume)s    is    stale    so    deleting.", {'snapshot': from_snap, 'volume': volume_id})
                source_rbd_image.remove_snap(from_snap)
                from_snap = None
            self._create_base_image(base_name, length, client)
            image_created = True
        elif (not self._snap_exists(base_name, from_snap, client)):
            errmsg = (_("Snapshot='%(snap)s'    does    not    exist    in    base    image='%(base)s'    -    aborting    incremental    backup") % {'snap': from_snap, 'base': base_name})
            LOG.info(errmsg)
            raise exception.BackupRBDOperationFailed(errmsg)
    new_snap = self._get_new_snap_name(backup.id)
    LOG.debug("Creating    backup    snapshot='%s'", new_snap)
    source_rbd_image.create_snap(new_snap)
    try:
        before = time.time()
        self._rbd_diff_transfer(volume_name, rbd_pool, base_name, backup.container, src_user=rbd_user, src_conf=rbd_conf, dest_user=self._ceph_backup_user, dest_conf=self._ceph_backup_conf, src_snap=new_snap, from_snap=from_snap)
        LOG.debug('Differential    backup    transfer    completed    in    %.4fs', (time.time() - before))
        if from_snap:
            source_rbd_image.remove_snap(from_snap)
    except exception.BackupRBDOperationFailed:
        with excutils.save_and_reraise_exception():
            LOG.debug('Differential    backup    transfer    failed')
            if image_created:
                self._try_delete_base_image(backup, base_name=base_name)
            LOG.debug("Deleting    diff    backup    snapshot='%(snapshot)s'    of    source    volume='%(volume)s'.", {'snapshot': new_snap, 'volume': volume_id})
            source_rbd_image.remove_snap(new_snap)
    if from_snap:
        parent_id = from_snap.split('.')
        updates = {'parent_id': parent_id[1]}
    return updates
