Add thin pool / volume managment to lvol (#19312)
* add functionality to create thin pool / volume on Linux LVM to lvol module add `thinpool' parameter. change `lv' parameter to not required. To create thin poll, specify `thinpool'(, `vg' and `size') parameter and omit `lv' parameter. It will create thin pool, nameed by `thinpool' parameter. To create thin volume, specify both `thinpool' and `lv' parameter (also `vg' and `size' paramter is need). It will create thin volume on `thinpool' pool, named by `lv' parameter. Thin volume and pool can delete whith 'state=absent' parameter. Thin volume is resizable like normal volume. Thin pool can extend, but not reduce. This limitation is in Linux's LVM. * Add thin volume support - Based on f816618 - Indicate that either lv or thinpool are required parameters using AnsibleModule's required_one_of. - Resolve conflict with snapshot functionality * Fix typo in documentation * Fix and simplify logical volume check * Rebase fixes * Convert examples to native YAML syntax * Fix failure with snapshot creation * Properly fail when trying to snapshot a thinpool volume * Don't fail when no size given for thin volume snapshot Fixes ansible/ansible-modules-extras#2478 * Convert old style required property sneaked in through rebase * Fix 'too many leading #' syntax check
This commit is contained in:
parent
e2af5dfae0
commit
466e1b289b
1 changed files with 72 additions and 12 deletions
|
@ -25,11 +25,9 @@ options:
|
||||||
vg:
|
vg:
|
||||||
description:
|
description:
|
||||||
- The volume group this logical volume is part of.
|
- The volume group this logical volume is part of.
|
||||||
required: true
|
|
||||||
lv:
|
lv:
|
||||||
description:
|
description:
|
||||||
- The name of the logical volume.
|
- The name of the logical volume.
|
||||||
required: true
|
|
||||||
size:
|
size:
|
||||||
description:
|
description:
|
||||||
- The size of the logical volume, according to lvcreate(8) --size, by
|
- The size of the logical volume, according to lvcreate(8) --size, by
|
||||||
|
@ -68,6 +66,10 @@ options:
|
||||||
description:
|
description:
|
||||||
- Comma separated list of physical volumes (e.g. /dev/sda,/dev/sdb).
|
- Comma separated list of physical volumes (e.g. /dev/sda,/dev/sdb).
|
||||||
version_added: "2.2"
|
version_added: "2.2"
|
||||||
|
thinpool:
|
||||||
|
description:
|
||||||
|
- The thin pool volume name. When you want to create a thin provisioned volume, specify a thin pool volume name.
|
||||||
|
version_added: "2.5"
|
||||||
shrink:
|
shrink:
|
||||||
description:
|
description:
|
||||||
- Shrink if current size is higher than size requested.
|
- Shrink if current size is higher than size requested.
|
||||||
|
@ -80,6 +82,8 @@ options:
|
||||||
type: bool
|
type: bool
|
||||||
default: 'yes'
|
default: 'yes'
|
||||||
version_added: "2.5"
|
version_added: "2.5"
|
||||||
|
notes:
|
||||||
|
- You must specify lv (when managing the state of logical volumes) or thinpool (when managing a thin provisioned volume).
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = '''
|
||||||
|
@ -188,6 +192,19 @@ EXAMPLES = '''
|
||||||
lv: test
|
lv: test
|
||||||
size: 512g
|
size: 512g
|
||||||
active: false
|
active: false
|
||||||
|
|
||||||
|
# Create a thin pool of 512g.
|
||||||
|
- lvol:
|
||||||
|
vg: firefly
|
||||||
|
thinpool: testpool
|
||||||
|
size: 512g
|
||||||
|
|
||||||
|
# Create a thin volume of 128g.
|
||||||
|
- lvol:
|
||||||
|
vg: firefly
|
||||||
|
lv: test
|
||||||
|
thinpool: testpool
|
||||||
|
size: 128g
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
@ -208,7 +225,9 @@ def parse_lvs(data):
|
||||||
lvs.append({
|
lvs.append({
|
||||||
'name': parts[0].replace('[', '').replace(']', ''),
|
'name': parts[0].replace('[', '').replace(']', ''),
|
||||||
'size': int(decimal_point.match(parts[1]).group(1)),
|
'size': int(decimal_point.match(parts[1]).group(1)),
|
||||||
'active': (parts[2][4] == 'a')
|
'active': (parts[2][4] == 'a'),
|
||||||
|
'thinpool': (parts[2][0] == 't'),
|
||||||
|
'thinvol': (parts[2][0] == 'V'),
|
||||||
})
|
})
|
||||||
return lvs
|
return lvs
|
||||||
|
|
||||||
|
@ -241,7 +260,7 @@ def main():
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
vg=dict(type='str', required=True),
|
vg=dict(type='str', required=True),
|
||||||
lv=dict(type='str', required=True),
|
lv=dict(type='str'),
|
||||||
size=dict(type='str'),
|
size=dict(type='str'),
|
||||||
opts=dict(type='str'),
|
opts=dict(type='str'),
|
||||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
state=dict(type='str', default='present', choices=['absent', 'present']),
|
||||||
|
@ -251,8 +270,12 @@ def main():
|
||||||
snapshot=dict(type='str'),
|
snapshot=dict(type='str'),
|
||||||
pvs=dict(type='str'),
|
pvs=dict(type='str'),
|
||||||
resizefs=dict(type='bool', default=False),
|
resizefs=dict(type='bool', default=False),
|
||||||
|
thinpool=dict(type='str'),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
|
required_one_of=(
|
||||||
|
['lv', 'thinpool'],
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Determine if the "--yes" option should be used
|
# Determine if the "--yes" option should be used
|
||||||
|
@ -274,6 +297,7 @@ def main():
|
||||||
shrink = module.boolean(module.params['shrink'])
|
shrink = module.boolean(module.params['shrink'])
|
||||||
active = module.boolean(module.params['active'])
|
active = module.boolean(module.params['active'])
|
||||||
resizefs = module.boolean(module.params['resizefs'])
|
resizefs = module.boolean(module.params['resizefs'])
|
||||||
|
thinpool = module.params['thinpool']
|
||||||
size_opt = 'L'
|
size_opt = 'L'
|
||||||
size_unit = 'm'
|
size_unit = 'm'
|
||||||
snapshot = module.params['snapshot']
|
snapshot = module.params['snapshot']
|
||||||
|
@ -356,10 +380,32 @@ def main():
|
||||||
|
|
||||||
lvs = parse_lvs(current_lvs)
|
lvs = parse_lvs(current_lvs)
|
||||||
|
|
||||||
if snapshot is None:
|
if snapshot:
|
||||||
check_lv = lv
|
# Check snapshot pre-conditions
|
||||||
else:
|
for test_lv in lvs:
|
||||||
|
if test_lv['name'] == lv or test_lv['name'] == thinpool:
|
||||||
|
if not test_lv['thinpool'] and not thinpool:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
module.fail_json(msg="Snapshots of thin pool LVs are not supported.")
|
||||||
|
else:
|
||||||
|
module.fail_json(msg="Snapshot origin LV %s does not exist in volume group %s." % (lv, vg))
|
||||||
check_lv = snapshot
|
check_lv = snapshot
|
||||||
|
|
||||||
|
elif thinpool:
|
||||||
|
if lv:
|
||||||
|
# Check thin volume pre-conditions
|
||||||
|
for test_lv in lvs:
|
||||||
|
if test_lv['name'] == thinpool:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
module.fail_json(msg="Thin pool LV %s does not exist in volume group %s." % (thinpool, vg))
|
||||||
|
check_lv = lv
|
||||||
|
else:
|
||||||
|
check_lv = thinpool
|
||||||
|
else:
|
||||||
|
check_lv = lv
|
||||||
|
|
||||||
for test_lv in lvs:
|
for test_lv in lvs:
|
||||||
if test_lv['name'] in (check_lv, check_lv.rsplit('/', 1)[-1]):
|
if test_lv['name'] in (check_lv, check_lv.rsplit('/', 1)[-1]):
|
||||||
this_lv = test_lv
|
this_lv = test_lv
|
||||||
|
@ -367,17 +413,31 @@ def main():
|
||||||
else:
|
else:
|
||||||
this_lv = None
|
this_lv = None
|
||||||
|
|
||||||
if state == 'present' and not size:
|
|
||||||
if this_lv is None:
|
|
||||||
module.fail_json(msg="No size given.")
|
|
||||||
|
|
||||||
msg = ''
|
msg = ''
|
||||||
if this_lv is None:
|
if this_lv is None:
|
||||||
if state == 'present':
|
if state == 'present':
|
||||||
|
# Require size argument except for snapshot of thin volumes
|
||||||
|
if (lv or thinpool) and not size:
|
||||||
|
for test_lv in lvs:
|
||||||
|
if test_lv['name'] == lv and test_lv['thinvol'] and snapshot:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
module.fail_json(msg="No size given.")
|
||||||
|
|
||||||
# create LV
|
# create LV
|
||||||
lvcreate_cmd = module.get_bin_path("lvcreate", required=True)
|
lvcreate_cmd = module.get_bin_path("lvcreate", required=True)
|
||||||
if snapshot is not None:
|
if snapshot is not None:
|
||||||
cmd = "%s %s %s -%s %s%s -s -n %s %s %s/%s" % (lvcreate_cmd, test_opt, yesopt, size_opt, size, size_unit, snapshot, opts, vg, lv)
|
if size:
|
||||||
|
cmd = "%s %s %s -%s %s%s -s -n %s %s %s/%s" % (lvcreate_cmd, test_opt, yesopt, size_opt, size, size_unit, snapshot, opts, vg, lv)
|
||||||
|
else:
|
||||||
|
cmd = "%s %s %s -s -n %s %s %s/%s" % (lvcreate_cmd, test_opt, yesopt, snapshot, opts, vg, lv)
|
||||||
|
elif thinpool and lv:
|
||||||
|
if size_opt == 'l':
|
||||||
|
module.fail_json(changed=False, msg="Thin volume sizing with percentage not supported.")
|
||||||
|
size_opt = 'V'
|
||||||
|
cmd = "%s %s -n %s -%s %s%s %s -T %s/%s" % (lvcreate_cmd, yesopt, lv, size_opt, size, size_unit, opts, vg, thinpool)
|
||||||
|
elif thinpool and not lv:
|
||||||
|
cmd = "%s %s -%s %s%s %s -T %s/%s" % (lvcreate_cmd, yesopt, size_opt, size, size_unit, opts, vg, thinpool)
|
||||||
else:
|
else:
|
||||||
cmd = "%s %s %s -n %s -%s %s%s %s %s %s" % (lvcreate_cmd, test_opt, yesopt, lv, size_opt, size, size_unit, opts, vg, pvs)
|
cmd = "%s %s %s -n %s -%s %s%s %s %s %s" % (lvcreate_cmd, test_opt, yesopt, lv, size_opt, size, size_unit, opts, vg, pvs)
|
||||||
rc, _, err = module.run_command(cmd)
|
rc, _, err = module.run_command(cmd)
|
||||||
|
|
Loading…
Reference in a new issue