From e1232fdcdf91243737bd67972910500ae8629e66 Mon Sep 17 00:00:00 2001 From: Shreyash Date: Wed, 24 Jun 2026 00:08:08 +0530 Subject: [PATCH] filesystem: fix bcachefs get_fs_size() for new bcachefs-tools output format (#12291) * filesystem: fix bcachefs get_fs_size() for new bcachefs-tools output format (#12259) * filesystem: fix ruff formatting and enable bcachefs UUID tests Fix ruff format violations (spaces around ** operators, single-quoted regex string) and set bcachefs new_uuid to 'random' since it supports UUID setting via -U/--uuid, fixing the set_fs_uuid_on_creation test assertion failure on Arch Linux. Co-Authored-By: Claude Opus 4.6 * filesystem: skip reset_fs_uuid test for bcachefs bcachefs supports UUID at creation (-U/--uuid) but has no CHANGE_UUID tool for resetting UUID on existing filesystems, so skip the reset_fs_uuid test to avoid a get_bin_path(None) crash. Co-Authored-By: Claude Opus 4.6 * filesystem: address review comments on bcachefs size parsing * changelog: correct bcachefs-tools version to v1.38.4 The output format change (commit e635903b95) first appeared in bcachefs-tools v1.38.4, not v1.37.0. Co-Authored-By: Claude Opus 4.6 * changelog: add PR link to changelog fragment --------- Co-authored-by: Claude Opus 4.6 --- ...12259-filesystem-bcachefs-size-parsing.yml | 4 ++ plugins/modules/filesystem.py | 63 ++++++++++++------- .../targets/filesystem/defaults/main.yml | 2 +- .../targets/filesystem/tasks/main.yml | 6 +- 4 files changed, 46 insertions(+), 29 deletions(-) create mode 100644 changelogs/fragments/12259-filesystem-bcachefs-size-parsing.yml diff --git a/changelogs/fragments/12259-filesystem-bcachefs-size-parsing.yml b/changelogs/fragments/12259-filesystem-bcachefs-size-parsing.yml new file mode 100644 index 0000000000..ab50efc420 --- /dev/null +++ b/changelogs/fragments/12259-filesystem-bcachefs-size-parsing.yml @@ -0,0 +1,4 @@ +bugfixes: + - filesystem - the module now also handles the output format of bcachefs-tools + v1.38.4 and above (https://github.com/ansible-collections/community.general/issues/12259, + https://github.com/ansible-collections/community.general/pull/12291). diff --git a/plugins/modules/filesystem.py b/plugins/modules/filesystem.py index cb7d901574..713a6655d2 100644 --- a/plugins/modules/filesystem.py +++ b/plugins/modules/filesystem.py @@ -422,6 +422,36 @@ class Bcachefs(Filesystem): GROW = "bcachefs" GROW_MAX_SPACE_FLAGS = ["device", "resize"] + SIZE_PATTERN = re.compile(r"Size:\s+(?P[\d.]+)\s*(?P\S+)") + + UNIT_FACTORS = { + "B": 1, + "k": 1024, + "M": 1024**2, + "G": 1024**3, + "T": 1024**4, + "P": 1024**5, + "E": 1024**6, + "Z": 1024**7, + "Y": 1024**8, + "KiB": 1024, + "MiB": 1024**2, + "GiB": 1024**3, + "TiB": 1024**4, + "PiB": 1024**5, + "EiB": 1024**6, + "ZiB": 1024**7, + "YiB": 1024**8, + "kB": 1000, + "MB": 1000**2, + "GB": 1000**3, + "TB": 1000**4, + "PB": 1000**5, + "EB": 1000**6, + "ZB": 1000**7, + "YB": 1000**8, + } + def get_fs_size(self, dev): """Return size in bytes of filesystem on device (integer).""" dummy, stdout, dummy = self.module.run_command( @@ -429,30 +459,15 @@ class Bcachefs(Filesystem): ) for line in stdout.splitlines(): - if "Size: " in line: - parts = line.split() - unit = parts[2] - - base = None - exp = None - - units_2 = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"] - units_10 = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] - - try: - exp = units_2.index(unit) - base = 1024 - except ValueError: - exp = units_10.index(unit) - base = 1000 - - if exp == 0: - value = int(parts[1]) - else: - value = float(parts[1]) - - if base is not None and exp is not None: - return int(value * pow(base, exp)) + match = self.SIZE_PATTERN.search(line) + if match: + value_str = match.group("value") + unit = match.group("unit") + factor = self.UNIT_FACTORS.get(unit) + if factor is None: + raise ValueError(repr(stdout)) + value = int(value_str) if factor == 1 else float(value_str) + return int(value * factor) raise ValueError(repr(stdout)) diff --git a/tests/integration/targets/filesystem/defaults/main.yml b/tests/integration/targets/filesystem/defaults/main.yml index 1b803258c1..5aa02e0279 100644 --- a/tests/integration/targets/filesystem/defaults/main.yml +++ b/tests/integration/targets/filesystem/defaults/main.yml @@ -15,7 +15,7 @@ tested_filesystems: # - 1.7.0 requires at least 30Mo # - 1.10.0 requires at least 38Mo # - resizefs asserts when initial fs is smaller than 60Mo and seems to require 1.10.0 - bcachefs: {fssize: 20, grow: true, new_uuid: null, label: null} + bcachefs: {fssize: 20, grow: true, new_uuid: 'random', label: null} ext4: {fssize: 10, grow: true, new_uuid: 'random', label: null} ext4dev: {fssize: 10, grow: true, new_uuid: 'random', label: null} ext3: {fssize: 10, grow: true, new_uuid: 'random', label: null} diff --git a/tests/integration/targets/filesystem/tasks/main.yml b/tests/integration/targets/filesystem/tasks/main.yml index 88f6642f7d..40351adc65 100644 --- a/tests/integration/targets/filesystem/tasks/main.yml +++ b/tests/integration/targets/filesystem/tasks/main.yml @@ -50,10 +50,6 @@ # bcachefs only on Alpine > 3.18 and Arch Linux for now # other distributions have too old versions of bcachefs-tools and/or util-linux (blkid for UUID tests) - 'not (ansible_facts.distribution not in ["Alpine", "Archlinux"] and item.0.key == "bcachefs")' - # TODO: bcachefs on Arch uses a different output format; instead of 'Size: 20.0 MiB' it now prints 'Size: 20.0M', - # which breaks Bcachefs.get_fs_size(). This seems to be related to the C -> Rust conversion of the CLI tools. - # It also seems that it is now impossible to know whether base 2 or 10 units are used... :( - - 'not (ansible_facts.distribution in ["Archlinux"] and item.0.key == "bcachefs")' # TODO: bcachefs on Alpine doesn't seem to work for unknown reasons, debug this! - 'not (ansible_facts.distribution in ["Alpine"] and item.0.key == "bcachefs")' # btrfs packages not available on RHEL/CentOS/Fedora @@ -81,6 +77,8 @@ # TODO: figure out why it fails, fix it! # swap does not work on Alpine due to no -f support in mkswap - 'not (item.0.key == "swap" and ansible_facts.distribution == "Alpine")' + # bcachefs does not support UUID reset on existing filesystems (no CHANGE_UUID tool) + - 'not (item.0.key == "bcachefs" and item.1 == "reset_fs_uuid")' # GFS2 not available on these distributions - 'not (item.0.key == "gfs2" and ansible_facts.distribution in ["Alpine", "Archlinux", "CentOS", "RedHat"])'