eppini-she opened a new issue, #13574:
URL: https://github.com/apache/cloudstack/issues/13574
### 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()`:
```java
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:
```sql
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:
```diff
- 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):
```java
@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));
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]