KVM: host.volume.encryption always false with qemu-img >= 10.1 (help header changed to "Supported image formats:")

Open Beginner friendly
#13,574 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
85/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
java

Research direction

Start in QemuImg.helpSupportsImageFormat(), then trace its result through LibvirtComputingResource.hostSupportsVolumeEncryption(). Verify the existing qemu-img format detection against both the legacy and QEMU 10.1 headers, add coverage for the new header and missing formats, and run the relevant QemuImg tests; done means LUKS is detected for both headers without matching unsupported formats.

Written by the indexing model from the issue text.

Description

component:kvm type:technical-debt
problem

On KVM hosts running qemu-img 10.1.0 or newer, the agent reports
host.volume.encryption = false even though the host fully supports LUKS
volume encryption (qemu-img lists the luks format and cryptsetup is
installed). As a result, encrypted service/disk offerings cannot be deployed
on affected hosts and encrypted volumes fail placement.

Root cause — a string mismatch after a QEMU change.

LibvirtComputingResource.hostSupportsVolumeEncryption() first checks whether
qemu-img supports the LUKS format and returns early if not, so cryptsetup is
never reached. The result is stored as host.volume.encryption.

The LUKS check is in QemuImg.helpSupportsImageFormat():

Pattern pattern = Pattern.compile(
    "Supported\\sformats:[a-zA-Z0-9-_\\s]*?\\b" + format + "\\b",
    CASE_INSENSITIVE);

The anchor Supported\sformats: expects Supported + one whitespace +
formats:. QEMU changed this header in 10.1.0:

qemu-img version --help header
<= 10.0.0 Supported formats:
>= 10.1.0 Supported image formats:

(qemu-img.c: printf("\nSupported image formats:\n");)

The inserted word image breaks the match, so supportsImageFormat(LUKS)
returns false and host.volume.encryption is stored as false. The luks
format is still in the list — it is just never matched.

Evidence — regex against the real host output:
current regex -> NO match (the bug):
$ qemu-img --help 2>&1 | grep -iP 'Supported\sformats:[a-zA-Z0-9-\s]*?\bluks\b'
(empty)
with "image" optional -> matches:
$ qemu-img --help 2>&1 | grep -izoP 'Supported\s(image\s)?formats:[a-zA-Z0-9-
\s]*?\bluks\b'
Supported image formats:
... io_uring luks

Verified end-to-end: after making image optional in the regex,
host.volume.encryption flipped from false to true on affected hosts, with no
other change.

versions
  • Apache CloudStack: 4.22.1.0 (affected code path is unchanged on main)
  • Hypervisor: KVM on RHEL 9.8
  • qemu-kvm 10.1.0 (qemu-kvm-10.1.0-17.el9_8.3), qemu-img 10.1.0
  • libvirt 11.10.0
  • cryptsetup: installed and functional
  • Primary storage: SharedMountPoint

Actual qemu-img --help on an affected host:

qemu-img version 10.1.0 (qemu-kvm-10.1.0-17.el9_8.3)
...
Supported image formats:
  blkdebug blklogwrites blkverify compress copy-before-write copy-on-read
  file ftp ftps host_cdrom host_device http https io_uring luks nbd null-aio
  null-co nvme nvme-io_uring preallocate qcow2 quorum raw rbd
  snapshot-access throttle vdi vhdx virtio-blk-vfio-pci
  virtio-blk-vhost-user virtio-blk-vhost-vdpa vmdk vpc
The steps to reproduce the bug
  1. Prepare a KVM host with qemu-img >= 10.1.0 (e.g. RHEL 9.8) and cryptsetup installed.
  2. Add the host to CloudStack, or restart the agent so it re-reports host details.
  3. Check the stored value:
   SELECT h.name, hd.value
   FROM host h
   JOIN host_details hd ON hd.host_id = h.id
   WHERE hd.name = 'host.volume.encryption';

Expected: host.volume.encryption = true
Actual: host.volume.encryption = false on every host with qemu-img >= 10.1.0

What to do about it?

Make the image keyword optional in the detection regex in
QemuImg.helpSupportsImageFormat() — minimal and backward compatible:

-        Pattern pattern = Pattern.compile("Supported\\sformats:[a-zA-Z0-9-_\\s]*?\\b" + format + "\\b", CASE_INSENSITIVE);
+        // QEMU >= 10.1.0 changed the qemu-img --help header from
+        // "Supported formats:" to "Supported image formats:".
+        Pattern pattern = Pattern.compile("Supported\\s(image\\s)?formats:[a-zA-Z0-9-_\\s]*?\\b" + format + "\\b", CASE_INSENSITIVE);

Supported\s(image\s)?formats: matches both the old and the new header; the
format list itself is untouched. Suggested unit tests (new header, legacy
header, negative case):

@Test
public void testHelpSupportsImageFormatQemu101Header() {
    String help =
        "Supported image formats:\n" +
        "  file ftp ftps host_cdrom host_device http https io_uring luks nbd\n";
    Assert.assertTrue(QemuImg.helpSupportsImageFormat(help, QemuImg.PhysicalDiskFormat.LUKS));
}

@Test
public void testHelpSupportsImageFormatLegacyHeader() {
    String help = "Supported formats: blkdebug file luks nbd qcow2 raw rbd vmdk\n";
    Assert.assertTrue(QemuImg.helpSupportsImageFormat(help, QemuImg.PhysicalDiskFormat.LUKS));
}

@Test
public void testHelpDoesNotSupportMissingFormat() {
    String help = "Supported image formats:\n  file qcow2 raw\n";
    Assert.assertFalse(QemuImg.helpSupportsImageFormat(help, QemuImg.PhysicalDiskFormat.LUKS));
}
Dominant language
Java
Stars
3.1k
Forks
1.4k
Avg merge
7d 5h
Merged PRs (30d)
28

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from apache/cloudstack

All issues in apache/cloudstack

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.