1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

lvol - extending volumes with '+' only work for percentages (#2267)

* Merged changes from old PR

* Added suppurt for -, other adaptations regarding size.

* Implementing +- support for -l

* Added changelog

* Renamed changelog

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
zigaSRC 2021-04-26 07:07:14 +02:00 committed by GitHub
parent aea12899cc
commit ffd73296de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 16 deletions

View file

@ -0,0 +1,5 @@
---
minor_changes:
- lvol - added proper support for ``+-`` options when extending or reducing the logical volume (https://github.com/ansible-collections/community.general/issues/1988).
bugfixes:
- lvol - fixed sizing calculation rounding to match the underlying tools (https://github.com/ansible-collections/community.general/issues/1988).

View file

@ -12,6 +12,8 @@ DOCUMENTATION = '''
author:
- Jeroen Hoekx (@jhoekx)
- Alexander Bulimov (@abulimov)
- Raoul Baudach (@unkaputtbar112)
- Ziga Kern (@zigaSRC)
module: lvol
short_description: Configure LVM logical volumes
description:
@ -33,7 +35,11 @@ options:
default in megabytes or optionally with one of [bBsSkKmMgGtTpPeE] units; or
according to lvcreate(8) --extents as a percentage of [VG|PVS|FREE];
Float values must begin with a digit.
Resizing using percentage values was not supported prior to 2.1.
- When resizing, apart from specifying an absolute size you may, according to
lvextend(8)|lvreduce(8) C(--size), specify the amount to extend the logical volume with
the prefix C(+) or the amount to reduce the logical volume by with prefix C(-).
- Resizing using C(+) or C(-) was not supported prior to community.general 3.0.0.
- Please note that when using C(+) or C(-), the module is B(not idempotent).
state:
type: str
description:
@ -136,6 +142,12 @@ EXAMPLES = '''
lv: test
size: +100%FREE
- name: Extend the logical volume by given space
community.general.lvol:
vg: firefly
lv: test
size: +512M
- name: Extend the logical volume to take all remaining space of the PVs and resize the underlying filesystem
community.general.lvol:
vg: firefly
@ -157,6 +169,13 @@ EXAMPLES = '''
size: 512
force: yes
- name: Reduce the logical volume by given space
community.general.lvol:
vg: firefly
lv: test
size: -512M
force: yes
- name: Set the logical volume to 512m and do not try to shrink if size is lower than current one
community.general.lvol:
vg: firefly
@ -209,7 +228,6 @@ import re
from ansible.module_utils.basic import AnsibleModule
LVOL_ENV_VARS = dict(
# make sure we use the C locale when running lvol-related commands
LANG='C',
@ -307,6 +325,7 @@ def main():
thinpool = module.params['thinpool']
size_opt = 'L'
size_unit = 'm'
size_operator = None
snapshot = module.params['snapshot']
pvs = module.params['pvs']
@ -325,7 +344,16 @@ def main():
test_opt = ''
if size:
# LVCREATE(8) -l --extents option with percentage
# LVEXTEND(8)/LVREDUCE(8) -l, -L options: Check for relative value for resizing
if size.startswith('+'):
size_operator = '+'
size = size[1:]
elif size.startswith('-'):
size_operator = '-'
size = size[1:]
# LVCREATE(8) does not support [+-]
# LVCREATE(8)/LVEXTEND(8)/LVREDUCE(8) -l --extents option with percentage
if '%' in size:
size_parts = size.split('%', 1)
size_percent = int(size_parts[0])
@ -339,10 +367,10 @@ def main():
size_opt = 'l'
size_unit = ''
# LVCREATE(8)/LVEXTEND(8)/LVREDUCE(8) -L --size option unit
if '%' not in size:
# LVCREATE(8) -L --size option unit
if size[-1].lower() in 'bskmgtpe':
size_unit = size[-1].lower()
size_unit = size[-1]
size = size[0:-1]
try:
@ -398,7 +426,6 @@ def main():
else:
module.fail_json(msg="Snapshot origin LV %s does not exist in volume group %s." % (lv, vg))
check_lv = snapshot
elif thinpool:
if lv:
# Check thin volume pre-conditions
@ -423,6 +450,8 @@ def main():
msg = ''
if this_lv is None:
if state == 'present':
if size_operator is not None:
module.fail_json(msg="Bad size specification of '%s%s' for creating LV" % (size_operator, size))
# Require size argument except for snapshot of thin volumes
if (lv or thinpool) and not size:
for test_lv in lvs:
@ -476,13 +505,19 @@ def main():
else: # size_whole == 'FREE':
size_requested = size_percent * this_vg['free'] / 100
# Round down to the next lowest whole physical extent
size_requested -= (size_requested % this_vg['ext_size'])
if '+' in size:
# from LVEXTEND(8) - The resulting value is rounded upward.
# from LVREDUCE(8) - The resulting value for the substraction is rounded downward, for the absolute size it is rounded upward.
if size_operator == '+':
size_requested += this_lv['size']
size_requested += this_vg['ext_size'] - (size_requested % this_vg['ext_size'])
elif size_operator == '-':
size_requested = this_lv['size'] - size_requested
size_requested -= (size_requested % this_vg['ext_size'])
else:
size_requested += this_vg['ext_size'] - (size_requested % this_vg['ext_size'])
if this_lv['size'] < size_requested:
if (size_free > 0) and (('+' not in size) or (size_free >= (size_requested - this_lv['size']))):
if (size_free > 0) and (size_free >= (size_requested - this_lv['size'])):
tool = module.get_bin_path("lvextend", required=True)
else:
module.fail_json(
@ -490,7 +525,7 @@ def main():
(this_lv['name'], (size_requested - this_lv['size']), unit, size_free, unit)
)
elif shrink and this_lv['size'] > size_requested + this_vg['ext_size']: # more than an extent too large
if size_requested == 0:
if size_requested < 1:
module.fail_json(msg="Sorry, no shrinking of %s to 0 permitted." % (this_lv['name']))
elif not force:
module.fail_json(msg="Sorry, no shrinking of %s without force=yes" % (this_lv['name']))
@ -501,7 +536,10 @@ def main():
if tool:
if resizefs:
tool = '%s %s' % (tool, '--resizefs')
cmd = "%s %s -%s %s%s %s/%s %s" % (tool, test_opt, size_opt, size, size_unit, vg, this_lv['name'], pvs)
if size_operator:
cmd = "%s %s -%s %s%s%s %s/%s %s" % (tool, test_opt, size_opt, size_operator, size, size_unit, vg, this_lv['name'], pvs)
else:
cmd = "%s %s -%s %s%s %s/%s %s" % (tool, test_opt, size_opt, size, size_unit, vg, this_lv['name'], pvs)
rc, out, err = module.run_command(cmd)
if "Reached maximum COW size" in out:
module.fail_json(msg="Unable to resize %s to %s%s" % (lv, size, size_unit), rc=rc, err=err, out=out)
@ -518,9 +556,9 @@ def main():
else:
# resize LV based on absolute values
tool = None
if float(size) > this_lv['size']:
if float(size) > this_lv['size'] or size_operator == '+':
tool = module.get_bin_path("lvextend", required=True)
elif shrink and float(size) < this_lv['size']:
elif shrink and float(size) < this_lv['size'] or size_operator == '-':
if float(size) == 0:
module.fail_json(msg="Sorry, no shrinking of %s to 0 permitted." % (this_lv['name']))
if not force:
@ -532,7 +570,10 @@ def main():
if tool:
if resizefs:
tool = '%s %s' % (tool, '--resizefs')
cmd = "%s %s -%s %s%s %s/%s %s" % (tool, test_opt, size_opt, size, size_unit, vg, this_lv['name'], pvs)
if size_operator:
cmd = "%s %s -%s %s%s%s %s/%s %s" % (tool, test_opt, size_opt, size_operator, size, size_unit, vg, this_lv['name'], pvs)
else:
cmd = "%s %s -%s %s%s %s/%s %s" % (tool, test_opt, size_opt, size, size_unit, vg, this_lv['name'], pvs)
rc, out, err = module.run_command(cmd)
if "Reached maximum COW size" in out:
module.fail_json(msg="Unable to resize %s to %s%s" % (lv, size, size_unit), rc=rc, err=err, out=out)