ceph/patches/0015-ceph-volume-fix-set_dmcrypt_no_workqueue.patch
Thomas Lamprecht b7c0642969 cherry-pick fixes for parsing the version of modern cryptsetup
Recent 18.2.4 release contained a cherry-pick of 0985e201342
("ceph-volume: use 'no workqueue' options with dmcrypt") and that
patch introduced parsing the output of `cryptsetup --version`, but it
had a coupling on either a old (or distro-specific) cryptsetup version
output and/or some legacy behavior of the python `packaging` module that
is used for the version parsing.

As the `cryptsetup` tool on bookworm outputs the following version:
> cryptsetup 2.6.1 flags: UDEV BLKID KEYRING KERNEL_CAPI

As the extra strings at the end are not accepted anymore by the
`packaging` python module in bookworm [0], this test fails ceph-volume when
encrypted OSDs are used, which we do by default.

[0]: due to https://github.com/pypa/packaging/pull/407 being included
     in the bookworm version

To make this work again cherry-pick two patches that first filter out
the numerical part from the raw version output using a regex and only
pass that to the version parsing call.

Fixes: https://tracker.ceph.com/issues/66393
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2024-07-30 20:32:56 +02:00

92 lines
3.7 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Guillaume Abrioux <gabrioux@ibm.com>
Date: Fri, 7 Jun 2024 10:46:16 +0200
Subject: [PATCH] ceph-volume: fix set_dmcrypt_no_workqueue()
`set_dmcrypt_no_workqueue()` from `ceph_volume.util.encryption`
The function `set_dmcrypt_no_workqueue` in `encryption.py` now
dynamically retrieves the installed cryptsetup version using `cryptsetup
--version` command. It then parses the version string using a regular
expression to accommodate varying digit counts. If the retrieved version
is greater than or equal to the specified target version,
`conf.dmcrypt_no_workqueue` is set to True, allowing for flexible version
handling.
Fixes: https://tracker.ceph.com/issues/66393
Signed-off-by: Guillaume Abrioux <gabrioux@ibm.com>
(cherry picked from commit dc28b77a6ea50b3390663ac02eeb80367650b7ed)
(cherry picked from commit 05ea72c70e06cc70f74b459c399c43f0a8863986)
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---
.../ceph_volume/util/encryption.py | 44 +++++++++++++++++--
1 file changed, 40 insertions(+), 4 deletions(-)
diff --git a/src/ceph-volume/ceph_volume/util/encryption.py b/src/ceph-volume/ceph_volume/util/encryption.py
index 844a81620d2..09f1cccf384 100644
--- a/src/ceph-volume/ceph_volume/util/encryption.py
+++ b/src/ceph-volume/ceph_volume/util/encryption.py
@@ -1,6 +1,7 @@
import base64
import os
import logging
+import re
from ceph_volume import process, conf, terminal
from ceph_volume.util import constants, system
from ceph_volume.util.device import Device
@@ -12,14 +13,49 @@ logger = logging.getLogger(__name__)
mlogger = terminal.MultiLogger(__name__)
def set_dmcrypt_no_workqueue(target_version: str = '2.3.4') -> None:
- """
- set `conf.dmcrypt_no_workqueue` to `True` if the available
- version of `cryptsetup` is greater or equal to `version`
+ """Set `conf.dmcrypt_no_workqueue` to `True` if the installed version
+ of `cryptsetup` is greater than or equal to the specified `target_version`.
+
+ Depending on the crypsetup version, `cryptsetup --version` output can be different.
+ Eg:
+
+ CentOS Stream9:
+ $ cryptsetup --version
+ cryptsetup 2.6.0 flags: UDEV BLKID KEYRING FIPS KERNEL_CAPI PWQUALITY
+
+ CentOS Stream8:
+ $ cryptsetup --version
+ cryptsetup 2.3.7
+
+ Args:
+ target_version (str, optional): The minimum version required for setting
+ `conf.dmcrypt_no_workqueue` to `True`. Defaults to '2.3.4'.
+
+ Raises:
+ RuntimeError: If failed to retrieve the cryptsetup version.
+ RuntimeError: If failed to parse the cryptsetup version.
+ RuntimeError: If failed to compare the cryptsetup version with the target version.
"""
command = ["cryptsetup", "--version"]
out, err, rc = process.call(command)
+
+ # This regex extracts the version number from
+ # the `cryptsetup --version` output
+ pattern: str = r'\b\d+(\.\d+)*\b'
+
+ if rc:
+ raise RuntimeError(f"Can't retrieve cryptsetup version: {err}")
+
try:
- if version.parse(out[0]) >= version.parse(f'cryptsetup {target_version}'):
+ cryptsetup_version = re.match(pattern, out[0])
+
+ if cryptsetup_version is None:
+ _output: str = "\n".join(out)
+ raise RuntimeError('Error while checking cryptsetup version.\n',
+ '`cryptsetup --version` output:\n',
+ f'{_output}')
+
+ if version.parse(cryptsetup_version.group(0)) >= version.parse(target_version):
conf.dmcrypt_no_workqueue = True
except IndexError:
mlogger.debug(f'cryptsetup version check: rc={rc} out={out} err={err}')