From ff5c34c4a71850a15e5334586ea65217a880c2c8 Mon Sep 17 00:00:00 2001 From: Alexei Znamensky <103110+russoz@users.noreply.github.com> Date: Thu, 16 Apr 2026 06:03:16 +1200 Subject: [PATCH] lvm_pv - use CmdRunner (#11811) * lvm_pv - migrate to CmdRunner using shared runners from module_utils/_lvm Co-Authored-By: Claude Sonnet 4.6 * lvm_pv - add changelog fragment for #11811 Co-Authored-By: Claude Sonnet 4.6 * Update changelogs/fragments/11811-lvm_pv-use-cmdrunner.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Claude Sonnet 4.6 Co-authored-by: Felix Fontein --- .../fragments/11811-lvm_pv-use-cmdrunner.yml | 2 + plugins/module_utils/_lvm.py | 12 ++-- plugins/modules/lvm_pv.py | 56 +++++++++---------- 3 files changed, 36 insertions(+), 34 deletions(-) create mode 100644 changelogs/fragments/11811-lvm_pv-use-cmdrunner.yml diff --git a/changelogs/fragments/11811-lvm_pv-use-cmdrunner.yml b/changelogs/fragments/11811-lvm_pv-use-cmdrunner.yml new file mode 100644 index 0000000000..a61c0f1db4 --- /dev/null +++ b/changelogs/fragments/11811-lvm_pv-use-cmdrunner.yml @@ -0,0 +1,2 @@ +minor_changes: + - lvm_pv - migrate to ``CmdRunner`` using shared runners from ``module_utils/_lvm`` (https://github.com/ansible-collections/community.general/pull/11811). diff --git a/plugins/module_utils/_lvm.py b/plugins/module_utils/_lvm.py index c3e6b86258..293653ad14 100644 --- a/plugins/module_utils/_lvm.py +++ b/plugins/module_utils/_lvm.py @@ -54,7 +54,7 @@ def pvcreate_runner(module: AnsibleModule, **kwargs) -> CmdRunner: Runner for C(pvcreate). Used by: community.general.lvg, community.general.lvm_pv, community.general.filesystem. - Suggested arg_formats keys: force yes devices + Suggested arg_formats keys: force yes device """ return CmdRunner( module, @@ -62,7 +62,7 @@ def pvcreate_runner(module: AnsibleModule, **kwargs) -> CmdRunner: arg_formats=dict( force=cmd_runner_fmt.as_bool("-f"), yes=cmd_runner_fmt.as_bool("--yes"), - devices=cmd_runner_fmt.as_list(), + device=cmd_runner_fmt.as_list(), ), **kwargs, ) @@ -108,15 +108,15 @@ def pvremove_runner(module: AnsibleModule, **kwargs) -> CmdRunner: """ Runner for C(pvremove). Used by: community.general.lvm_pv. - Suggested arg_formats keys: yes force device + Suggested arg_formats keys: force device - Note: C(force=True) passes C(-ff), which removes PVs even when part of a VG. + Note: C(-y) is always passed (non-interactive). C(force=True) passes C(-ff), + which removes PVs even when part of a VG. """ return CmdRunner( module, - command="pvremove", + command=["pvremove", "-y"], arg_formats=dict( - yes=cmd_runner_fmt.as_bool("-y"), force=cmd_runner_fmt.as_bool("-ff"), device=cmd_runner_fmt.as_list(), ), diff --git a/plugins/modules/lvm_pv.py b/plugins/modules/lvm_pv.py index c8d7617ad0..205bfa79d7 100644 --- a/plugins/modules/lvm_pv.py +++ b/plugins/modules/lvm_pv.py @@ -73,18 +73,12 @@ import os from ansible.module_utils.basic import AnsibleModule - -def get_pv_status(module, device): - """Check if the device is already a PV.""" - cmd = ["pvs", "--noheadings", "--readonly", device] - return module.run_command(cmd)[0] == 0 - - -def get_pv_size(module, device): - """Get current PV size in bytes.""" - cmd = ["pvs", "--noheadings", "--nosuffix", "--units", "b", "-o", "pv_size", device] - rc, out, err = module.run_command(cmd, check_rc=True) - return int(out.strip()) +from ansible_collections.community.general.plugins.module_utils._lvm import ( + pvcreate_runner, + pvremove_runner, + pvresize_runner, + pvs_runner, +) def rescan_device(module, device): @@ -129,16 +123,30 @@ def main(): device = module.params["device"] state = module.params["state"] - force = module.params["force"] resize = module.params["resize"] changed = False actions = [] + pvs = pvs_runner(module) + pvcreate = pvcreate_runner(module) + pvresize = pvresize_runner(module) + pvremove = pvremove_runner(module) + + def get_pv_status(): + with pvs("noheadings readonly devices", check_rc=False) as ctx: + rc, dummy, dummy = ctx.run(devices=[device]) + return rc == 0 + + def get_pv_size(): + with pvs("noheadings nosuffix readonly units fields devices") as ctx: + dummy, out, dummy = ctx.run(units="b", fields="pv_size", devices=[device]) + return int(out.strip()) + # Validate device existence for present state if state == "present" and not os.path.exists(device): module.fail_json(msg=f"Device {device} not found") - is_pv = get_pv_status(module, device) + is_pv = get_pv_status() if state == "present": # Create PV if needed @@ -147,11 +155,7 @@ def main(): changed = True actions.append("would be created") else: - cmd = ["pvcreate"] - if force: - cmd.append("-f") - cmd.append(device) - rc, out, err = module.run_command(cmd, check_rc=True) + pvcreate("force device", check_rc=True).run() changed = True actions.append("created") is_pv = True @@ -163,12 +167,12 @@ def main(): changed = True actions.append("would be resized") else: - # Perform device rescan if each time + # Perform device rescan each time if rescan_device(module, device): actions.append("rescanned") - original_size = get_pv_size(module, device) - rc, out, err = module.run_command(["pvresize", device], check_rc=True) - new_size = get_pv_size(module, device) + original_size = get_pv_size() + pvresize("device", check_rc=True).run() + new_size = get_pv_size() if new_size != original_size: changed = True actions.append("resized") @@ -179,12 +183,8 @@ def main(): changed = True actions.append("would be removed") else: - cmd = ["pvremove", "-y"] - if force: - cmd.append("-ff") + pvremove("force device", check_rc=True).run() changed = True - cmd.append(device) - rc, out, err = module.run_command(cmd, check_rc=True) actions.append("removed") # Generate final message