Re: [PATCH v2 4/4] iotests: Test convert to qcow2 compressed to NBD

2020-07-28 Thread Eric Blake

On 7/27/20 4:58 PM, Nir Soffer wrote:

Add test for "qemu-img convert -O qcow2 -c" to NBD target. The tests
create a OVA file and write compressed qcow2 disk content directly into
the OVA file via qemu-nbd.

Signed-off-by: Nir Soffer 
---
  tests/qemu-iotests/302 | 127 +
  tests/qemu-iotests/302.out |  31 +
  tests/qemu-iotests/group   |   1 +
  3 files changed, 159 insertions(+)
  create mode 100755 tests/qemu-iotests/302
  create mode 100644 tests/qemu-iotests/302.out



Tested-by: Eric Blake 
Reviewed-by: Eric Blake 

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




[PATCH v2 4/4] iotests: Test convert to qcow2 compressed to NBD

2020-07-27 Thread Nir Soffer
Add test for "qemu-img convert -O qcow2 -c" to NBD target. The tests    
create a OVA file and write compressed qcow2 disk content directly into
the OVA file via qemu-nbd.

Signed-off-by: Nir Soffer 
---
 tests/qemu-iotests/302 | 127 +
 tests/qemu-iotests/302.out |  31 +
 tests/qemu-iotests/group   |   1 +
 3 files changed, 159 insertions(+)
 create mode 100755 tests/qemu-iotests/302
 create mode 100644 tests/qemu-iotests/302.out

diff --git a/tests/qemu-iotests/302 b/tests/qemu-iotests/302
new file mode 100755
index 00..a8506bda15
--- /dev/null
+++ b/tests/qemu-iotests/302
@@ -0,0 +1,127 @@
+#!/usr/bin/env python3
+#
+# Tests converting qcow2 compressed to NBD
+#
+# Copyright (c) 2020 Nir Soffer 
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+#
+# owner=nir...@gmail.com
+
+import io
+import tarfile
+
+import iotests
+
+from iotests import (
+file_path,
+qemu_img,
+qemu_img_check,
+qemu_img_create,
+qemu_img_log,
+qemu_img_measure,
+qemu_io,
+qemu_nbd_popen,
+)
+
+iotests.script_initialize(supported_fmts=["qcow2"])
+
+# Create source disk. Using qcow2 to enable strict comparing later, and
+# avoid issues with random filesystem on CI environment.
+src_disk = file_path("disk.qcow2")
+qemu_img_create("-f", iotests.imgfmt, src_disk, "1g")
+qemu_io("-f", iotests.imgfmt, "-c", "write 1m 64k", src_disk)
+
+# The use case is writing qcow2 image directly into an ova file, which
+# is a tar file with specific layout. This is tricky since we don't know the
+# size of the image before compressing, so we have to do:
+# 1. Add an ovf file.
+# 2. Find the offset of the next member data.
+# 3. Make room for image data, allocating for the worst case.
+# 4. Write compressed image data into the tar.
+# 5. Add a tar entry with the actual image size.
+# 6. Shrink the tar to the actual size, aligned to 512 bytes.
+
+tar_file = file_path("test.ova")
+
+with tarfile.open(tar_file, "w") as tar:
+
+# 1. Add an ovf file.
+
+ovf_data = b""
+ovf = tarfile.TarInfo("vm.ovf")
+ovf.size = len(ovf_data)
+tar.addfile(ovf, io.BytesIO(ovf_data))
+
+# 2. Find the offset of the next member data.
+
+offset = tar.fileobj.tell() + 512
+
+# 3. Make room for image data, allocating for the worst case.
+
+measure = qemu_img_measure("-O", "qcow2", src_disk)
+tar.fileobj.truncate(offset + measure["required"])
+
+# 4. Write compressed image data into the tar.
+
+nbd_sock = file_path("nbd-sock", base_dir=iotests.sock_dir)
+nbd_uri = "nbd+unix:///exp?socket=" + nbd_sock
+
+# Use raw format to allow creating qcow2 directly into tar file.
+with qemu_nbd_popen(
+"--socket", nbd_sock,
+"--export-name", "exp",
+"--format", "raw",
+"--offset", str(offset),
+tar_file):
+
+iotests.log("=== Target image info ===")
+qemu_img_log("info", nbd_uri)
+
+qemu_img(
+"convert",
+"-f", iotests.imgfmt,
+"-O", "qcow2",
+"-c",
+src_disk,
+nbd_uri)
+
+iotests.log("=== Converted image info ===")
+qemu_img_log("info", nbd_uri)
+
+iotests.log("=== Converted image check ===")
+qemu_img_log("check", nbd_uri)
+
+iotests.log("=== Comparing to source disk ===")
+qemu_img_log("compare", src_disk, nbd_uri)
+
+actual_size = qemu_img_check(nbd_uri)["image-end-offset"]
+
+# 5. Add a tar entry with the actual image size.
+
+disk = tarfile.TarInfo("disk")
+disk.size = actual_size
+tar.addfile(disk)
+
+# 6. Shrink the tar to the actual size, aligned to 512 bytes.
+
+tar_size = offset + (disk.size + 511) & ~511
+tar.fileobj.seek(tar_size)
+tar.fileobj.truncate(tar_size)
+
+with tarfile.open(tar_file) as tar:
+members = [{"name": m.name, "size": m.size, "offset": m.offset_data}
+   for m in tar]
+iotests.log("=== OVA file contents ===")
+iotests.log(members)
diff --git a/tests/qemu-iotests/302.out b/tests/qemu-iotests/302.out
new file mode 100644
index 00..e37d3a1030
--- /dev/null
+++ b/tests/qemu-iotests/302.out
@@ -0,0 +1,31 @@
+Start NBD server
+=== Target image info ===
+image: nbd+unix:///exp?socket=SOCK_DIR/PID-nbd-sock
+file format: raw
+virtual size: 448 KiB (458752 bytes)
+disk