def get_transfer_service(disk_snapshot_id):
    # Get a reference to the service that manages the image transfer:
    transfers_service = system_service.image_transfers_service()

    # Add a new image transfer:
    transfer = transfers_service.add(
        types.ImageTransfer(
            snapshot=types.DiskSnapshot(id=disk_snapshot_id),
            direction=types.ImageTransferDirection.DOWNLOAD,
        ))

    # Get reference to the created transfer service:
    transfer_service = transfers_service.image_transfer_service(transfer.id)

    while transfer.phase == types.ImageTransferPhase.INITIALIZING:
        time.sleep(1)
        transfer = transfer_service.get()

    return transfer_service
Ejemplo n.º 2
0
def create_transfer(connection,
                    disk=None,
                    direction=types.ImageTransferDirection.UPLOAD,
                    host=None,
                    backup=None,
                    inactivity_timeout=None,
                    timeout=60,
                    disk_snapshot=None,
                    shallow=None):
    """
    Create image transfer for upload to disk or download from disk.

    Arguments:
        connection (ovirtsdk4.Connection): connection to ovirt engine
        disk (ovirtsdk4.types.Disk): disk object. Not needed if disk_snaphost
            is specified.
        direction (ovirtsdk4.typles.ImageTransferDirection): transfer
            direction (default UPLOAD)
        host (ovirtsdk4.types.Host): host object that should perform the
            transfer. If not specified engine will pick a random host.
        backup (ovirtsdk4.types.Backup): When downloading backup, the backup
            object owning the disks.
        inactivity_timeout (int): Number of seconds engine will wait for client
            activity before pausing the transfer. If not set, use engine
            default value.
        timeout (float, optional): number of seconds to wait for transfer
            to become ready.
        disk_snapshot (ovirtsdk4.types.DiskSnapshot): transfer a disk snapshot
            instead of current data of the disk.
        shallow (bool): Download only the specified image instead of the entire
            image chain. When downloading a disk transfer only the active disk
            snapshot data. When downloading a disk snapshot, transfer only the
            specified disk snaphost data.

    Returns:
        ovirtsdk4.types.ImageTransfer in phase TRANSFERRING
    """
    log.info(
        "Creating image transfer for %s=%s, direction=%s host=%s backup=%s "
        "shallow=%s",
        "disk_snapshot" if disk_snapshot else "disk",
        disk_snapshot.id if disk_snapshot else disk.id,
        direction,
        host,
        backup,
        shallow,
    )

    # Create image transfer for disk or snapshot.

    transfer = types.ImageTransfer(
        host=host,
        direction=direction,
        backup=backup,
        inactivity_timeout=inactivity_timeout,

        # format=raw uses the NBD backend, enabling:
        # - Transfer raw guest data, regardless of the disk format.
        # - Automatic format conversion to remote disk format. For example,
        #   upload qcow2 image to raw disk, or raw image to qcow2 disk.
        # - Collapsed qcow2 chains to single raw file.
        # - Extents reporting for qcow2 images and raw images on file storage,
        #   speeding up downloads.
        format=types.DiskFormat.RAW,
        shallow=shallow,
    )

    if disk_snapshot:
        transfer.snapshot = types.DiskSnapshot(id=disk_snapshot.id)
    else:
        transfer.disk = types.Disk(id=disk.id)

    transfers_service = connection.system_service().image_transfers_service()

    # Add the new transfer to engine. This starts the transfer and retruns a
    # transfer ID that can be used to track this image transfer.
    transfer = transfers_service.add(transfer)

    # You can use the transfer id to locate logs for this transfer.
    log.info("Transfer ID %s", transfer.id)

    # At this point the transfer owns the disk and will delete the disk if the
    # transfer is canceled, or if finalizing the transfer fails.

    transfer_service = transfers_service.image_transfer_service(transfer.id)
    start = time.time()

    while True:
        time.sleep(1)
        try:
            transfer = transfer_service.get()
        except sdk.NotFoundError:
            # The system has removed the disk and the transfer.
            raise RuntimeError("Transfer {} was removed".format(transfer.id))

        if transfer.phase == types.ImageTransferPhase.FINISHED_FAILURE:
            # The system will remove the disk and the transfer soon.
            raise RuntimeError("Transfer {} has failed".format(transfer.id))

        if transfer.phase == types.ImageTransferPhase.PAUSED_SYSTEM:
            transfer_service.cancel()
            raise RuntimeError("Transfer {} was paused by system".format(
                transfer.id))

        if transfer.phase == types.ImageTransferPhase.TRANSFERRING:
            break

        if transfer.phase != types.ImageTransferPhase.INITIALIZING:
            transfer_service.cancel()
            raise RuntimeError("Unexpected transfer {} phase {}".format(
                transfer.id, transfer.phase))

        if time.time() > start + timeout:
            log.info("Cancelling transfer %s", transfer.id)
            transfer_service.cancel()
            raise RuntimeError("Timed out waiting for transfer {}".format(
                transfer.id))

    log.info("Transfer initialized in %.3f seconds", time.time() - start)

    # Log the transfer host name. This is very useful for troubleshooting.
    hosts_service = connection.system_service().hosts_service()
    host_service = hosts_service.host_service(transfer.host.id)
    transfer.host = host_service.get()

    log.info("Transfer host name: %s", transfer.host.name)

    return transfer