1
0
mirror of https://gitlab.com/libvirt/libvirt-python.git synced 2025-07-25 04:58:57 +03:00
Files
libvirt-python/examples/sparsestream.py
Michal Privoznik 9b98fe2d6f examples: Introduce sparsestream.py
Sparse streams are not that straight forward to use for the very
first time. Especially the sparseRecvAll() and sparseSendAll()
methods which expects callbacks. What we can do to make it easier
for developers is to have an example where they can take an
inspiration from.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2017-05-24 13:32:41 +02:00

118 lines
3.4 KiB
Python
Executable File

#!/usr/bin/env python
# Example of sparse streams usage
#
# Authors:
# Michal Privoznik <mprivozn@redhat.com>
import libvirt, sys, os
def bytesWriteHandler(stream, buf, opaque):
fd = opaque
return os.write(fd, buf)
def bytesReadHandler(stream, nbytes, opaque):
fd = opaque
return os.read(fd, nbytes)
def recvSkipHandler(stream, length, opaque):
fd = opaque
cur = os.lseek(fd, length, os.SEEK_CUR)
return os.ftruncate(fd, cur)
def sendSkipHandler(stream, length, opaque):
fd = opaque
return os.lseek(fd, length, os.SEEK_CUR)
def holeHandler(stream, opaque):
fd = opaque
cur = os.lseek(fd, 0, os.SEEK_CUR)
try:
data = os.lseek(fd, cur, os.SEEK_DATA)
except OSError as e:
if e.errno != 6:
raise e
else:
data = -1;
# There are three options:
# 1) data == cur; @cur is in data
# 2) data > cur; @cur is in a hole, next data at @data
# 3) data < 0; either @cur is in trailing hole, or @cur is beyond EOF.
if data < 0:
# case 3
inData = False
eof = os.lseek(fd, 0, os.SEEK_END)
if (eof < cur):
raise RuntimeError("Current position in file after EOF: %d" % cur)
sectionLen = eof - cur
else:
if (data > cur):
# case 2
inData = False
sectionLen = data - cur
else:
# case 1
inData = True
# We don't know where does the next hole start. Let's find out.
# Here we get the same options as above
hole = os.lseek(fd, data, os.SEEK_HOLE)
if hole < 0:
# case 3. But wait a second. There is always a trailing hole.
# Do the best what we can here
raise RuntimeError("No trailing hole")
if (hole == data):
# case 1. Again, this is suspicious. The reason we are here is
# because we are in data. But at the same time we are in a
# hole. WAT?
raise RuntimeError("Impossible happened")
else:
# case 2
sectionLen = hole - data
os.lseek(fd, cur, os.SEEK_SET)
return [inData, sectionLen]
def download(vol, st, filename):
offset = 0
length = 0
fd = os.open(filename, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, mode=0o0660)
vol.download(st, offset, length, libvirt.VIR_STORAGE_VOL_DOWNLOAD_SPARSE_STREAM)
st.sparseRecvAll(bytesWriteHandler, recvSkipHandler, fd)
os.close(fd)
def upload(vol, st, filename):
offset = 0
length = 0
fd = os.open(filename, os.O_RDONLY)
vol.upload(st, offset, length, libvirt.VIR_STORAGE_VOL_UPLOAD_SPARSE_STREAM)
st.sparseSendAll(bytesReadHandler, holeHandler, sendSkipHandler, fd)
os.close(fd)
# main
if len(sys.argv) != 5:
print("Usage: ", sys.argv[0], " URI --upload/--download VOLUME FILE")
print("Either uploads local FILE to libvirt VOLUME, or downloads libvirt ")
print("VOLUME into local FILE while preserving FILE/VOLUME sparseness")
sys.exit(1)
conn = libvirt.open(sys.argv[1])
vol = conn.storageVolLookupByKey(sys.argv[3])
st = conn.newStream()
if sys.argv[2] == "--download":
download(vol, st, sys.argv[4])
elif sys.argv[2] == "--upload":
upload(vol, st, sys.argv[4])
else:
print("Unknown operation: %s " % sys.argv[1])
sys.exit(1)
st.finish()
conn.close()