]> git.proxmox.com Git - ceph.git/commitdiff
cherry-pick fixes for parsing the version of modern cryptsetup
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Tue, 30 Jul 2024 18:21:40 +0000 (20:21 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Tue, 30 Jul 2024 18:32:56 +0000 (20:32 +0200)
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>
patches/0015-ceph-volume-fix-set_dmcrypt_no_workqueue.patch [new file with mode: 0644]
patches/0016-ceph-volume-fix-regex-usage-in-set_dmcrypt_no_workqu.patch [new file with mode: 0644]
patches/series

diff --git a/patches/0015-ceph-volume-fix-set_dmcrypt_no_workqueue.patch b/patches/0015-ceph-volume-fix-set_dmcrypt_no_workqueue.patch
new file mode 100644 (file)
index 0000000..c6d7d01
--- /dev/null
@@ -0,0 +1,91 @@
+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}')
diff --git a/patches/0016-ceph-volume-fix-regex-usage-in-set_dmcrypt_no_workqu.patch b/patches/0016-ceph-volume-fix-regex-usage-in-set_dmcrypt_no_workqu.patch
new file mode 100644 (file)
index 0000000..6d90f8d
--- /dev/null
@@ -0,0 +1,98 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Guillaume Abrioux <gabrioux@ibm.com>
+Date: Wed, 19 Jun 2024 15:06:52 +0200
+Subject: [PATCH] ceph-volume: fix regex usage in `set_dmcrypt_no_workqueue`
+
+- Updated the regex pattern to `r'(\d+\.?)+'` to more accurately
+  capture version numbers.
+
+- Replaced `re.match` with `re.search` to properly match the cryptsetup
+  version in the output.
+
+- `re.match` only checks for a match at the beginning of the string,
+   while `re.search` looks for a match anywhere in the string.
+
+This fix ensures that the function correctly retrieves the
+cryptsetup version from the output.
+
+Fixes: https://tracker.ceph.com/issues/66393
+
+Signed-off-by: Guillaume Abrioux <gabrioux@ibm.com>
+(cherry picked from commit 607eb34b2c278566c386efcbf3018629cf08ccfd)
+(cherry picked from commit d49b2888486623415a038630da54f5e1c99f1c63)
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ .../ceph_volume/tests/util/test_encryption.py | 40 ++++++++++++++++++-
+ .../ceph_volume/util/encryption.py            |  4 +-
+ 2 files changed, 41 insertions(+), 3 deletions(-)
+
+diff --git a/src/ceph-volume/ceph_volume/tests/util/test_encryption.py b/src/ceph-volume/ceph_volume/tests/util/test_encryption.py
+index cd2ea8f187f..200f1da84d8 100644
+--- a/src/ceph-volume/ceph_volume/tests/util/test_encryption.py
++++ b/src/ceph-volume/ceph_volume/tests/util/test_encryption.py
+@@ -1,6 +1,44 @@
+ from ceph_volume.util import encryption
+-from mock.mock import patch
++from mock.mock import patch, Mock
+ import base64
++import pytest
++
++
++class TestNoWorkqueue:
++    def setup_method(self):
++        encryption.conf.dmcrypt_no_workqueue = None
++
++    @patch('ceph_volume.util.encryption.process.call',
++           Mock(return_value=(['cryptsetup 2.7.2 flags: UDEV BLKID KEYRING' \
++                               'FIPS KERNEL_CAPI PWQUALITY '], [''], 0)))
++    def test_set_dmcrypt_no_workqueue_true(self):
++        encryption.set_dmcrypt_no_workqueue()
++        assert encryption.conf.dmcrypt_no_workqueue
++
++    @patch('ceph_volume.util.encryption.process.call',
++           Mock(return_value=(['cryptsetup 2.0.0'], [''], 0)))
++    def test_set_dmcrypt_no_workqueue_false(self):
++        encryption.set_dmcrypt_no_workqueue()
++        assert encryption.conf.dmcrypt_no_workqueue is None
++
++    @patch('ceph_volume.util.encryption.process.call',
++           Mock(return_value=([''], ['fake error'], 1)))
++    def test_set_dmcrypt_no_workqueue_cryptsetup_version_fails(self):
++        with pytest.raises(RuntimeError):
++            encryption.set_dmcrypt_no_workqueue()
++
++    @patch('ceph_volume.util.encryption.process.call',
++           Mock(return_value=(['unexpected output'], [''], 0)))
++    def test_set_dmcrypt_no_workqueue_pattern_not_found(self):
++        with pytest.raises(RuntimeError):
++            encryption.set_dmcrypt_no_workqueue()
++
++    @patch('ceph_volume.util.encryption.process.call',
++           Mock(return_value=([], [''], 0)))
++    def test_set_dmcrypt_no_workqueue_index_error(self):
++        with pytest.raises(RuntimeError):
++            encryption.set_dmcrypt_no_workqueue()
++
+ class TestGetKeySize(object):
+     def test_get_size_from_conf_default(self, conf_ceph_stub):
+diff --git a/src/ceph-volume/ceph_volume/util/encryption.py b/src/ceph-volume/ceph_volume/util/encryption.py
+index 09f1cccf384..15a31315645 100644
+--- a/src/ceph-volume/ceph_volume/util/encryption.py
++++ b/src/ceph-volume/ceph_volume/util/encryption.py
+@@ -41,13 +41,13 @@ def set_dmcrypt_no_workqueue(target_version: str = '2.3.4') -> None:
+     # This regex extracts the version number from
+     # the `cryptsetup --version` output
+-    pattern: str = r'\b\d+(\.\d+)*\b'
++    pattern: str = r'(\d+\.?)+'
+     if rc:
+         raise RuntimeError(f"Can't retrieve cryptsetup version: {err}")
+     try:
+-        cryptsetup_version = re.match(pattern, out[0])
++        cryptsetup_version = re.search(pattern, out[0])
+         if cryptsetup_version is None:
+             _output: str = "\n".join(out)
index a52bc4c67a4ffa1d799a331a6c06d71c45470ad6..efde3ed4a4c68f6949deb5535a504d0ea825c516 100644 (file)
@@ -12,3 +12,5 @@
 0012-ceph-osd-postinst-do-not-always-reload-all-sysctl-se.patch
 0013-debian-recursively-adjust-permissions-of-var-lib-cep.patch
 0014-ceph-crash-change-order-of-client-names.patch
+0015-ceph-volume-fix-set_dmcrypt_no_workqueue.patch
+0016-ceph-volume-fix-regex-usage-in-set_dmcrypt_no_workqu.patch