From nobody Sun Feb 8 22:57:48 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1495450656444789.4527268796336; Mon, 22 May 2017 03:57:36 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A9548C05FFFA; Mon, 22 May 2017 10:57:34 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8574877CA9; Mon, 22 May 2017 10:57:34 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 433884BB7F; Mon, 22 May 2017 10:57:34 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v4MAvQpv011177 for ; Mon, 22 May 2017 06:57:26 -0400 Received: by smtp.corp.redhat.com (Postfix) id BDE327DE0A; Mon, 22 May 2017 10:57:26 +0000 (UTC) Received: from localhost.localdomain (ovpn-204-24.brq.redhat.com [10.40.204.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2E04C7DE02 for ; Mon, 22 May 2017 10:57:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com A9548C05FFFA Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=libvir-list-bounces@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com A9548C05FFFA From: Michal Privoznik To: libvir-list@redhat.com Date: Mon, 22 May 2017 12:57:15 +0200 Message-Id: <6fc7a50827809047df8e68ac1f5dbfadc1d0b7d4.1495450612.git.mprivozn@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Subject: [libvirt] [libvirt-python][PATCH 4/4] examples: Introduce sparsestream.py X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Mon, 22 May 2017 10:57:35 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" 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 --- examples/sparsestream.py | 119 +++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 119 insertions(+) create mode 100755 examples/sparsestream.py diff --git a/examples/sparsestream.py b/examples/sparsestream.py new file mode 100755 index 0000000..b572a31 --- /dev/null +++ b/examples/sparsestream.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# Example of sparse streams usage +# +# Authors: +# Michal Privoznik + +import libvirt, sys, os + +def bytesWriteHandler(stream, buf, opaque): + fd =3D opaque + return os.write(fd, buf) + +def bytesReadHandler(stream, nbytes, opaque): + fd =3D opaque + return os.read(fd, nbytes) + +def recvSkipHandler(stream, length, opaque): + fd =3D opaque + cur =3D os.lseek(fd, length, os.SEEK_CUR) + return os.ftruncate(fd, cur) + +def sendSkipHandler(stream, length, opaque): + fd =3D opaque + return os.lseek(fd, length, os.SEEK_CUR) + +def holeHandler(stream, opaque): + fd =3D opaque + cur =3D os.lseek(fd, 0, os.SEEK_CUR) + + try: + try: + data =3D os.lseek(fd, cur, os.SEEK_DATA) + # There are three options: + # 1) data =3D=3D 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 bey= ond EOF. + except: + # case 3 + inData =3D False + eof =3D os.lseek(fd, 0, os.SEEK_END) + if (eof < cur): + raise RuntimeError("Current position in file after EOF: %d= " % cur) + sectionLen =3D eof - cur + else: + if (data > cur): + # case 2 + inData =3D False + sectionLen =3D data - cur + else: + # case 1 + inData =3D True + + # We don't know where does the next hole start. Let's find= out. + # Here we get the same options as above + try: + hole =3D os.lseek(fd, data, os.SEEK_HOLE) + except: + # case 3. But wait a second. There is always a trailin= g hole. + # Do the best what we can here + raise RuntimeError("No trailing hole") + + if (hole =3D=3D 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 =3D hole - data + finally: + os.lseek(fd, cur, os.SEEK_SET) + return [inData, sectionLen] + +def download(vol, st, filename): + offset =3D 0 + length =3D 0 + + try: + fd =3D os.open(filename, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, mo= de=3D0o0660) + vol.download(st, offset, length, libvirt.VIR_STORAGE_VOL_DOWNLOAD_= SPARSE_STREAM) + st.sparseRecvAll(bytesWriteHandler, recvSkipHandler, fd) + except OSError: + print(sys.exc_info()[0]) + os.unlink(filename) + + os.close(fd) + +def upload(vol, st, filename): + offset =3D 0 + length =3D 0 + + fd =3D os.open(filename, os.O_RDONLY) + vol.upload(st, offset, length, libvirt.VIR_STORAGE_VOL_UPLOAD_SPARSE_S= TREAM) + st.sparseSendAll(bytesReadHandler, holeHandler, sendSkipHandler, fd) + + os.close(fd) + +# main +if len(sys.argv) !=3D 5: + print("Usage: ", sys.argv[0], " URI --upload/--download VOLUME FILE") + print("Either uploads local FILE to libvirt VOLUME, or downloads libvi= rt ") + print("VOLUME into local FILE while preserving FILE/VOLUME sparseness") + sys.exit(1) + +conn =3D libvirt.open(sys.argv[1]) +vol =3D conn.storageVolLookupByKey(sys.argv[3]) + +st =3D conn.newStream() + +if sys.argv[2] =3D=3D "--download": + download(vol, st, sys.argv[4]) +elif sys.argv[2] =3D=3D "--upload": + upload(vol, st, sys.argv[4]) +else: + print("Unknown operation: %s " % sys.argv[1]) + sys.exit(1) + +st.finish() +conn.close() --=20 2.13.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list