Skip to content

Conversation

last-genius
Copy link
Contributor

@last-genius last-genius commented Jun 26, 2025

This script serves as one half of a vhd-tool-like solution for QCOW, only offering the export side (converting a raw file to a qcow2 stream). We can't use qemu-img or some other ready-made library because these create a temporary file (seeking in both the source and the destination), which we want to avoid.

The script is taken from upstream QEMU, with some modifications for our use-case:

  • we want the script to only operate on "raw" files
  • it needs to work on block special files as opposed to regular files
  • and it needs to export a "difference" between two files, just like vhd-tool does

The script is currently unused.

The import half (qcow2 stream->raw file) was merged in ocaml-qcow and will later be integrated into xapi together with this script through a qcow_tool_wrapper.

Taken from https://github.com/qemu/qemu/blob/a9cd5bc6399a80fcf233ed0fffe6067b731227d8/scripts/qcow2-to-stdout.py

> This tool converts a disk image to qcow2, writing the result directly
> to stdout. This can be used for example to send the generated file
> over the network.
>
> This is equivalent to using qemu-img to convert a file to qcow2 and
> then writing the result to stdout, with the difference that this tool
> does not need to create this temporary qcow2 file and therefore does
> not need any additional disk space.

Signed-off-by: Andrii Sultanov <[email protected]>
We are only ever going to use this script with "raw" files.

Signed-off-by: Andrii Sultanov <[email protected]>
The original script is designed to only work on regular files. Adapt it
slightly to work on special block devices (since that's what we want to export
from).

Aside from dropping some unnecessary checks and replacing os.path.getsize with
a functional equivalent that works on block special files, these changes remove
detection of "holes" in the raw file, since SEEK_DATA and SEEK_HOLE are
unimplemented in this case.

Signed-off-by: Andrii Sultanov <[email protected]>
…sters

When specified, only the clusters that have changed between diff_file_name and
input_file will be allocated and exported in a sparse manner.

This is analogous to vhd-tool's --relative-to option.

Example usage:
```
Create an empty raw file:
$ dd if=/dev/zero of=disk.before.img bs=1M count=100

Fill the first three clusters with random data
$ dd if=/dev/random conv=notrunc of=disk.before.img bs=65536 count=3
$ python3/libexec/qcow2-to-stdout.py disk.before.img > disk.before.qcow2

Check that only the first three clusters are allocated (each is 0x10000 in length)
$ qemu-img map disk.before.qcow2
Offset          Length          Mapped to       File
0               0x30000         0x50000         disk.before.qcow2

Overwrite the 2nd and 3rd clusters with new data
$ cp disk.before.img disk.after.img
$ dd if=/dev/random conv=notrunc of=disk.after.img bs=65536 count=2 oseek=1

Export the difference, verifying that only the 2nd and 3rd clusters are allocated
$ python3/libexec/qcow2-to-stdout.py disk.after.img --diff disk.before.img > disk.diff.qcow2
$ qemu-img map disk.diff.qcow2
Offset          Length          Mapped to       File
0x10000         0x20000         0x50000         disk.diff.qcow2

The image can be recreated if the base is imported first, with the difference
overwriting it
$ qemu-img convert -f qcow2 -O raw disk.before.qcow2 disk.test.img
$ qemu-img convert -f qcow2 -O raw disk.diff.qcow2 disk.test.img --target-is-zero -n
$ diff disk.test.img disk.after.img
<the same>

```

Signed-off-by: Andrii Sultanov <[email protected]>
@last-genius
Copy link
Contributor Author

This script also needs to be added to the specfile (if only we had an upstream one 🤔) :

 /opt/xensource/libexec/usb_scan.py
+/opt/xensource/libexec/qcow2-to-stdout.py
 /etc/xensource/usb-policy.conf

@psafont
Copy link
Member

psafont commented Jun 27, 2025

hopefully the dog with the warnings apepars only during reviews and doesn't block anything. I've yet to review the diff feature

@last-genius last-genius added this pull request to the merge queue Jul 4, 2025
Merged via the queue into xapi-project:master with commit c941af3 Jul 4, 2025
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants