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