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

filesystem: revamp module (#2472) (#2550)

* revamp filesystem module to prepare next steps

* pass all commands to module.run_command() as lists
* refactor grow() and grow_cmd() to not need to override them so much
* refactor all existing get_fs_size() overrides to raise a ValueError if
  not able to parse command output and return an integer.
* override MKFS_FORCE_FLAGS the same way for all fstypes that require it
* improve documentation of limitations of the module regarding FreeBSD
* fix indentation in DOCUMENTATION
* add/update function/method docstrings
* fix pylint hints

filesystem: refactor integration tests

* Include *reiserfs* and *swap* in tests.
* Fix reiserfs related code and tests accordingly.
* Replace "other fs" (unhandled by this module), from *swap* to *minix*
  (both mkswap and mkfs.minix being provided by util-linux).
* Replace *dd* commands by *filesize* dedicated module.
* Use FQCNs and name the tasks.
* Update main tests conditionals.

* add a changelog fragment

* Apply suggestions from code review

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

* declare variables as lists when lists are needed

* fix construction without useless conversion

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit f6db0745fc)

Co-authored-by: quidame <quidame@poivron.org>
This commit is contained in:
patchback[bot] 2021-05-18 10:49:12 +02:00 committed by GitHub
parent de2feb2567
commit d43764da79
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 434 additions and 288 deletions

View file

@ -0,0 +1,9 @@
---
minor_changes:
- "filesystem - cleanup and revamp module, tests and doc. Pass all commands to
``module.run_command()`` as lists. Move the device-vs-mountpoint logic to
``grow()`` method. Give to all ``get_fs_size()`` the same logic and error
handling. (https://github.com/ansible-collections/community.general/pull/2472)."
bugfixes:
- "filesystem - repair ``reiserfs`` fstype support after adding it to integration
tests (https://github.com/ansible-collections/community.general/pull/2472)."

View file

@ -7,10 +7,11 @@
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
author: author:
- Alexander Bulimov (@abulimov) - Alexander Bulimov (@abulimov)
module: filesystem module: filesystem
short_description: Makes a filesystem short_description: Makes a filesystem
description: description:
@ -18,13 +19,12 @@ description:
options: options:
state: state:
description: description:
- If C(state=present), the filesystem is created if it doesn't already - If C(state=present), the filesystem is created if it doesn't already
exist, that is the default behaviour if I(state) is omitted. exist, that is the default behaviour if I(state) is omitted.
- If C(state=absent), filesystem signatures on I(dev) are wiped if it - If C(state=absent), filesystem signatures on I(dev) are wiped if it
contains a filesystem (as known by C(blkid)). contains a filesystem (as known by C(blkid)).
- When C(state=absent), all other options but I(dev) are ignored, and the - When C(state=absent), all other options but I(dev) are ignored, and the
module doesn't fail if the device I(dev) doesn't actually exist. module doesn't fail if the device I(dev) doesn't actually exist.
- C(state=absent) is not supported and will fail on FreeBSD systems.
type: str type: str
choices: [ present, absent ] choices: [ present, absent ]
default: present default: present
@ -32,48 +32,56 @@ options:
fstype: fstype:
choices: [ btrfs, ext2, ext3, ext4, ext4dev, f2fs, lvm, ocfs2, reiserfs, xfs, vfat, swap ] choices: [ btrfs, ext2, ext3, ext4, ext4dev, f2fs, lvm, ocfs2, reiserfs, xfs, vfat, swap ]
description: description:
- Filesystem type to be created. This option is required with - Filesystem type to be created. This option is required with
C(state=present) (or if I(state) is omitted). C(state=present) (or if I(state) is omitted).
- reiserfs support was added in 2.2. - reiserfs support was added in 2.2.
- lvm support was added in 2.5. - lvm support was added in 2.5.
- since 2.5, I(dev) can be an image file. - since 2.5, I(dev) can be an image file.
- vfat support was added in 2.5 - vfat support was added in 2.5
- ocfs2 support was added in 2.6 - ocfs2 support was added in 2.6
- f2fs support was added in 2.7 - f2fs support was added in 2.7
- swap support was added in 2.8 - swap support was added in 2.8
type: str type: str
aliases: [type] aliases: [type]
dev: dev:
description: description:
- Target path to device or image file. - Target path to block device or regular file.
- On systems not using block devices but character devices instead (as
FreeBSD), this module only works when applying to regular files, aka
disk images.
type: path type: path
required: yes required: yes
aliases: [device] aliases: [device]
force: force:
description: description:
- If C(yes), allows to create new filesystem on devices that already has filesystem. - If C(yes), allows to create new filesystem on devices that already has filesystem.
type: bool type: bool
default: 'no' default: 'no'
resizefs: resizefs:
description: description:
- If C(yes), if the block device and filesystem size differ, grow the filesystem into the space. - If C(yes), if the block device and filesystem size differ, grow the filesystem into the space.
- Supported for C(ext2), C(ext3), C(ext4), C(ext4dev), C(f2fs), C(lvm), C(xfs) and C(vfat) filesystems. - Supported for C(ext2), C(ext3), C(ext4), C(ext4dev), C(f2fs), C(lvm), C(xfs) and C(vfat) filesystems.
Attempts to resize other filesystem types will fail. Attempts to resize other filesystem types will fail.
- XFS Will only grow if mounted. Currently, the module is based on commands - XFS Will only grow if mounted. Currently, the module is based on commands
from C(util-linux) package to perform operations, so resizing of XFS is from C(util-linux) package to perform operations, so resizing of XFS is
not supported on FreeBSD systems. not supported on FreeBSD systems.
- vFAT will likely fail if fatresize < 1.04. - vFAT will likely fail if fatresize < 1.04.
type: bool type: bool
default: 'no' default: 'no'
opts: opts:
description: description:
- List of options to be passed to mkfs command. - List of options to be passed to mkfs command.
type: str type: str
requirements: requirements:
- Uses tools related to the I(fstype) (C(mkfs)) and C(blkid) command. When I(resizefs) is enabled, C(blockdev) command is required too. - Uses tools related to the I(fstype) (C(mkfs)) and the C(blkid) command.
- When I(resizefs) is enabled, C(blockdev) command is required too.
notes: notes:
- Potential filesystem on I(dev) are checked using C(blkid), in case C(blkid) isn't able to detect an existing filesystem, - Potential filesystem on I(dev) are checked using C(blkid). In case C(blkid)
this filesystem is overwritten even if I(force) is C(no). isn't able to detect an existing filesystem, this filesystem is overwritten
even if I(force) is C(no).
- On FreeBSD systems, either C(e2fsprogs) or C(util-linux) packages provide
a C(blkid) command that is compatible with this module, when applied to
regular files.
- This module supports I(check_mode). - This module supports I(check_mode).
''' '''
@ -102,6 +110,7 @@ import re
import stat import stat
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_native
class Device(object): class Device(object):
@ -114,13 +123,15 @@ class Device(object):
statinfo = os.stat(self.path) statinfo = os.stat(self.path)
if stat.S_ISBLK(statinfo.st_mode): if stat.S_ISBLK(statinfo.st_mode):
blockdev_cmd = self.module.get_bin_path("blockdev", required=True) blockdev_cmd = self.module.get_bin_path("blockdev", required=True)
dummy, devsize_in_bytes, dummy = self.module.run_command([blockdev_cmd, "--getsize64", self.path], check_rc=True) dummy, out, dummy = self.module.run_command([blockdev_cmd, "--getsize64", self.path], check_rc=True)
return int(devsize_in_bytes) devsize_in_bytes = int(out)
elif os.path.isfile(self.path): elif os.path.isfile(self.path):
return os.path.getsize(self.path) devsize_in_bytes = os.path.getsize(self.path)
else: else:
self.module.fail_json(changed=False, msg="Target device not supported: %s" % self) self.module.fail_json(changed=False, msg="Target device not supported: %s" % self)
return devsize_in_bytes
def get_mountpoint(self): def get_mountpoint(self):
"""Return (first) mountpoint of device. Returns None when not mounted.""" """Return (first) mountpoint of device. Returns None when not mounted."""
cmd_findmnt = self.module.get_bin_path("findmnt", required=True) cmd_findmnt = self.module.get_bin_path("findmnt", required=True)
@ -141,9 +152,12 @@ class Device(object):
class Filesystem(object): class Filesystem(object):
GROW = None
MKFS = None MKFS = None
MKFS_FORCE_FLAGS = '' MKFS_FORCE_FLAGS = []
INFO = None
GROW = None
GROW_MAX_SPACE_FLAGS = []
GROW_MOUNTPOINT_ONLY = False
LANG_ENV = {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'} LANG_ENV = {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}
@ -155,7 +169,11 @@ class Filesystem(object):
return type(self).__name__ return type(self).__name__
def get_fs_size(self, dev): def get_fs_size(self, dev):
""" Return size in bytes of filesystem on device. Returns int """ """Return size in bytes of filesystem on device (integer).
Should query the info with a per-fstype command that can access the
device whenever it is mounted or not, and parse the command output.
Parser must ensure to return an integer, or raise a ValueError.
"""
raise NotImplementedError() raise NotImplementedError()
def create(self, opts, dev): def create(self, opts, dev):
@ -163,31 +181,27 @@ class Filesystem(object):
return return
mkfs = self.module.get_bin_path(self.MKFS, required=True) mkfs = self.module.get_bin_path(self.MKFS, required=True)
if opts is None: cmd = [mkfs] + self.MKFS_FORCE_FLAGS + opts + [str(dev)]
cmd = "%s %s '%s'" % (mkfs, self.MKFS_FORCE_FLAGS, dev)
else:
cmd = "%s %s %s '%s'" % (mkfs, self.MKFS_FORCE_FLAGS, opts, dev)
self.module.run_command(cmd, check_rc=True) self.module.run_command(cmd, check_rc=True)
def wipefs(self, dev): def wipefs(self, dev):
if platform.system() == 'FreeBSD':
msg = "module param state=absent is currently not supported on this OS (FreeBSD)."
self.module.fail_json(msg=msg)
if self.module.check_mode: if self.module.check_mode:
return return
# wipefs comes with util-linux package (as 'blockdev' & 'findmnt' above) # wipefs comes with util-linux package (as 'blockdev' & 'findmnt' above)
# so it is not supported on FreeBSD. Even the use of dd as a fallback is # that is ported to FreeBSD. The use of dd as a portable fallback is
# not doable here if it needs get_mountpoint() (to prevent corruption of # not doable here if it needs get_mountpoint() (to prevent corruption of
# a mounted filesystem), since 'findmnt' is not available on FreeBSD. # a mounted filesystem), since 'findmnt' is not available on FreeBSD,
# even in util-linux port for this OS.
wipefs = self.module.get_bin_path('wipefs', required=True) wipefs = self.module.get_bin_path('wipefs', required=True)
cmd = [wipefs, "--all", dev.__str__()] cmd = [wipefs, "--all", str(dev)]
self.module.run_command(cmd, check_rc=True) self.module.run_command(cmd, check_rc=True)
def grow_cmd(self, dev): def grow_cmd(self, target):
cmd = self.module.get_bin_path(self.GROW, required=True) """Build and return the resizefs commandline as list."""
return [cmd, str(dev)] cmdline = [self.module.get_bin_path(self.GROW, required=True)]
cmdline += self.GROW_MAX_SPACE_FLAGS + [target]
return cmdline
def grow(self, dev): def grow(self, dev):
"""Get dev and fs size and compare. Returns stdout of used command.""" """Get dev and fs size and compare. Returns stdout of used command."""
@ -196,31 +210,50 @@ class Filesystem(object):
try: try:
fssize_in_bytes = self.get_fs_size(dev) fssize_in_bytes = self.get_fs_size(dev)
except NotImplementedError: except NotImplementedError:
self.module.fail_json(changed=False, msg="module does not support resizing %s filesystem yet." % self.fstype) self.module.fail_json(msg="module does not support resizing %s filesystem yet" % self.fstype)
except ValueError as err:
self.module.warn("unable to process %s output '%s'" % (self.INFO, to_native(err)))
self.module.fail_json(msg="unable to process %s output for %s" % (self.INFO, dev))
if not fssize_in_bytes < devsize_in_bytes: if not fssize_in_bytes < devsize_in_bytes:
self.module.exit_json(changed=False, msg="%s filesystem is using the whole device %s" % (self.fstype, dev)) self.module.exit_json(changed=False, msg="%s filesystem is using the whole device %s" % (self.fstype, dev))
elif self.module.check_mode: elif self.module.check_mode:
self.module.exit_json(changed=True, msg="Resizing filesystem %s on device %s" % (self.fstype, dev)) self.module.exit_json(changed=True, msg="resizing filesystem %s on device %s" % (self.fstype, dev))
if self.GROW_MOUNTPOINT_ONLY:
mountpoint = dev.get_mountpoint()
if not mountpoint:
self.module.fail_json(msg="%s needs to be mounted for %s operations" % (dev, self.fstype))
grow_target = mountpoint
else: else:
dummy, out, dummy = self.module.run_command(self.grow_cmd(dev), check_rc=True) grow_target = str(dev)
return out
dummy, out, dummy = self.module.run_command(self.grow_cmd(grow_target), check_rc=True)
return out
class Ext(Filesystem): class Ext(Filesystem):
MKFS_FORCE_FLAGS = '-F' MKFS_FORCE_FLAGS = ['-F']
INFO = 'tune2fs'
GROW = 'resize2fs' GROW = 'resize2fs'
def get_fs_size(self, dev): def get_fs_size(self, dev):
cmd = self.module.get_bin_path('tune2fs', required=True) """Get Block count and Block size and return their product."""
# Get Block count and Block size cmd = self.module.get_bin_path(self.INFO, required=True)
dummy, size, dummy = self.module.run_command([cmd, '-l', str(dev)], check_rc=True, environ_update=self.LANG_ENV) dummy, out, dummy = self.module.run_command([cmd, '-l', str(dev)], check_rc=True, environ_update=self.LANG_ENV)
for line in size.splitlines():
block_count = block_size = None
for line in out.splitlines():
if 'Block count:' in line: if 'Block count:' in line:
block_count = int(line.split(':')[1].strip()) block_count = int(line.split(':')[1].strip())
elif 'Block size:' in line: elif 'Block size:' in line:
block_size = int(line.split(':')[1].strip()) block_size = int(line.split(':')[1].strip())
return block_size * block_count if None not in (block_size, block_count):
break
else:
raise ValueError(out)
return block_size * block_count
class Ext2(Ext): class Ext2(Ext):
@ -237,52 +270,46 @@ class Ext4(Ext):
class XFS(Filesystem): class XFS(Filesystem):
MKFS = 'mkfs.xfs' MKFS = 'mkfs.xfs'
MKFS_FORCE_FLAGS = '-f' MKFS_FORCE_FLAGS = ['-f']
INFO = 'xfs_info'
GROW = 'xfs_growfs' GROW = 'xfs_growfs'
GROW_MOUNTPOINT_ONLY = True
def get_fs_size(self, dev): def get_fs_size(self, dev):
cmd = self.module.get_bin_path('xfs_info', required=True) """Get bsize and blocks and return their product."""
cmdline = [self.module.get_bin_path(self.INFO, required=True)]
# Depending on the versions, xfs_info is able to get info from the
# device, whenever it is mounted or not, or only if unmounted, or
# only if mounted, or not at all. For any version until now, it is
# able to query info from the mountpoint. So try it first, and use
# device as the last resort: it may or may not work.
mountpoint = dev.get_mountpoint() mountpoint = dev.get_mountpoint()
if mountpoint: if mountpoint:
rc, out, err = self.module.run_command([cmd, str(mountpoint)], environ_update=self.LANG_ENV) cmdline += [mountpoint]
else: else:
# Recent GNU/Linux distros support access to unmounted XFS filesystems cmdline += [str(dev)]
rc, out, err = self.module.run_command([cmd, str(dev)], environ_update=self.LANG_ENV) dummy, out, dummy = self.module.run_command(cmdline, check_rc=True, environ_update=self.LANG_ENV)
if rc != 0:
self.module.fail_json(msg="Error while attempting to query size of XFS filesystem: %s" % err)
block_size = block_count = None
for line in out.splitlines(): for line in out.splitlines():
col = line.split('=') col = line.split('=')
if col[0].strip() == 'data': if col[0].strip() == 'data':
if col[1].strip() != 'bsize': if col[1].strip() == 'bsize':
self.module.fail_json(msg='Unexpected output format from xfs_info (could not locate "bsize")') block_size = int(col[2].split()[0])
if col[2].split()[1] != 'blocks': if col[2].split()[1] == 'blocks':
self.module.fail_json(msg='Unexpected output format from xfs_info (could not locate "blocks")') block_count = int(col[3].split(',')[0])
block_size = int(col[2].split()[0]) if None not in (block_size, block_count):
block_count = int(col[3].split(',')[0]) break
return block_size * block_count else:
raise ValueError(out)
def grow_cmd(self, dev): return block_size * block_count
# Check first if growing is needed, and then if it is doable or not.
devsize_in_bytes = dev.size()
fssize_in_bytes = self.get_fs_size(dev)
if not fssize_in_bytes < devsize_in_bytes:
self.module.exit_json(changed=False, msg="%s filesystem is using the whole device %s" % (self.fstype, dev))
mountpoint = dev.get_mountpoint()
if not mountpoint:
# xfs filesystem needs to be mounted
self.module.fail_json(msg="%s needs to be mounted for xfs operations" % dev)
cmd = self.module.get_bin_path(self.GROW, required=True)
return [cmd, str(mountpoint)]
class Reiserfs(Filesystem): class Reiserfs(Filesystem):
MKFS = 'mkfs.reiserfs' MKFS = 'mkfs.reiserfs'
MKFS_FORCE_FLAGS = '-f' MKFS_FORCE_FLAGS = ['-q']
class Btrfs(Filesystem): class Btrfs(Filesystem):
@ -290,7 +317,8 @@ class Btrfs(Filesystem):
def __init__(self, module): def __init__(self, module):
super(Btrfs, self).__init__(module) super(Btrfs, self).__init__(module)
dummy, stdout, stderr = self.module.run_command('%s --version' % self.MKFS, check_rc=True) mkfs = self.module.get_bin_path(self.MKFS, required=True)
dummy, stdout, stderr = self.module.run_command([mkfs, '--version'], check_rc=True)
match = re.search(r" v([0-9.]+)", stdout) match = re.search(r" v([0-9.]+)", stdout)
if not match: if not match:
# v0.20-rc1 use stderr # v0.20-rc1 use stderr
@ -298,29 +326,27 @@ class Btrfs(Filesystem):
if match: if match:
# v0.20-rc1 doesn't have --force parameter added in following version v3.12 # v0.20-rc1 doesn't have --force parameter added in following version v3.12
if LooseVersion(match.group(1)) >= LooseVersion('3.12'): if LooseVersion(match.group(1)) >= LooseVersion('3.12'):
self.MKFS_FORCE_FLAGS = '-f' self.MKFS_FORCE_FLAGS = ['-f']
else:
self.MKFS_FORCE_FLAGS = ''
else: else:
# assume version is greater or equal to 3.12 # assume version is greater or equal to 3.12
self.MKFS_FORCE_FLAGS = '-f' self.MKFS_FORCE_FLAGS = ['-f']
self.module.warn('Unable to identify mkfs.btrfs version (%r, %r)' % (stdout, stderr)) self.module.warn('Unable to identify mkfs.btrfs version (%r, %r)' % (stdout, stderr))
class Ocfs2(Filesystem): class Ocfs2(Filesystem):
MKFS = 'mkfs.ocfs2' MKFS = 'mkfs.ocfs2'
MKFS_FORCE_FLAGS = '-Fx' MKFS_FORCE_FLAGS = ['-Fx']
class F2fs(Filesystem): class F2fs(Filesystem):
MKFS = 'mkfs.f2fs' MKFS = 'mkfs.f2fs'
INFO = 'dump.f2fs'
GROW = 'resize.f2fs' GROW = 'resize.f2fs'
@property def __init__(self, module):
def MKFS_FORCE_FLAGS(self): super(F2fs, self).__init__(module)
mkfs = self.module.get_bin_path(self.MKFS, required=True) mkfs = self.module.get_bin_path(self.MKFS, required=True)
cmd = "%s %s" % (mkfs, os.devnull) dummy, out, dummy = self.module.run_command([mkfs, os.devnull], check_rc=False, environ_update=self.LANG_ENV)
dummy, out, dummy = self.module.run_command(cmd, check_rc=False, environ_update=self.LANG_ENV)
# Looking for " F2FS-tools: mkfs.f2fs Ver: 1.10.0 (2018-01-30)" # Looking for " F2FS-tools: mkfs.f2fs Ver: 1.10.0 (2018-01-30)"
# mkfs.f2fs displays version since v1.2.0 # mkfs.f2fs displays version since v1.2.0
match = re.search(r"F2FS-tools: mkfs.f2fs Ver: ([0-9.]+) \(", out) match = re.search(r"F2FS-tools: mkfs.f2fs Ver: ([0-9.]+) \(", out)
@ -328,69 +354,73 @@ class F2fs(Filesystem):
# Since 1.9.0, mkfs.f2fs check overwrite before make filesystem # Since 1.9.0, mkfs.f2fs check overwrite before make filesystem
# before that version -f switch wasn't used # before that version -f switch wasn't used
if LooseVersion(match.group(1)) >= LooseVersion('1.9.0'): if LooseVersion(match.group(1)) >= LooseVersion('1.9.0'):
return '-f' self.MKFS_FORCE_FLAGS = ['-f']
return ''
def get_fs_size(self, dev): def get_fs_size(self, dev):
cmd = self.module.get_bin_path('dump.f2fs', required=True) """Get sector size and total FS sectors and return their product."""
# Get sector count and sector size cmd = self.module.get_bin_path(self.INFO, required=True)
dummy, dump, dummy = self.module.run_command([cmd, str(dev)], check_rc=True, environ_update=self.LANG_ENV) dummy, out, dummy = self.module.run_command([cmd, str(dev)], check_rc=True, environ_update=self.LANG_ENV)
sector_size = None sector_size = sector_count = None
sector_count = None for line in out.splitlines():
for line in dump.splitlines():
if 'Info: sector size = ' in line: if 'Info: sector size = ' in line:
# expected: 'Info: sector size = 512' # expected: 'Info: sector size = 512'
sector_size = int(line.split()[4]) sector_size = int(line.split()[4])
elif 'Info: total FS sectors = ' in line: elif 'Info: total FS sectors = ' in line:
# expected: 'Info: total FS sectors = 102400 (50 MB)' # expected: 'Info: total FS sectors = 102400 (50 MB)'
sector_count = int(line.split()[5]) sector_count = int(line.split()[5])
if None not in (sector_size, sector_count): if None not in (sector_size, sector_count):
break break
else: else:
self.module.warn("Unable to process dump.f2fs output '%s'", '\n'.join(dump)) raise ValueError(out)
self.module.fail_json(msg="Unable to process dump.f2fs output for %s" % dev)
return sector_size * sector_count return sector_size * sector_count
class VFAT(Filesystem): class VFAT(Filesystem):
if platform.system() == 'FreeBSD': INFO = 'fatresize'
MKFS = "newfs_msdos"
else:
MKFS = 'mkfs.vfat'
GROW = 'fatresize' GROW = 'fatresize'
GROW_MAX_SPACE_FLAGS = ['-s', 'max']
def __init__(self, module):
super(VFAT, self).__init__(module)
if platform.system() == 'FreeBSD':
self.MKFS = 'newfs_msdos'
else:
self.MKFS = 'mkfs.vfat'
def get_fs_size(self, dev): def get_fs_size(self, dev):
cmd = self.module.get_bin_path(self.GROW, required=True) """Get and return size of filesystem, in bytes."""
dummy, output, dummy = self.module.run_command([cmd, '--info', str(dev)], check_rc=True, environ_update=self.LANG_ENV) cmd = self.module.get_bin_path(self.INFO, required=True)
for line in output.splitlines()[1:]: dummy, out, dummy = self.module.run_command([cmd, '--info', str(dev)], check_rc=True, environ_update=self.LANG_ENV)
fssize = None
for line in out.splitlines()[1:]:
param, value = line.split(':', 1) param, value = line.split(':', 1)
if param.strip() == 'Size': if param.strip() == 'Size':
return int(value.strip()) fssize = int(value.strip())
self.module.fail_json(msg="fatresize failed to provide filesystem size for %s" % dev) break
else:
raise ValueError(out)
def grow_cmd(self, dev): return fssize
cmd = self.module.get_bin_path(self.GROW)
return [cmd, "-s", str(dev.size()), str(dev.path)]
class LVM(Filesystem): class LVM(Filesystem):
MKFS = 'pvcreate' MKFS = 'pvcreate'
MKFS_FORCE_FLAGS = '-f' MKFS_FORCE_FLAGS = ['-f']
INFO = 'pvs'
GROW = 'pvresize' GROW = 'pvresize'
def get_fs_size(self, dev): def get_fs_size(self, dev):
cmd = self.module.get_bin_path('pvs', required=True) """Get and return PV size, in bytes."""
cmd = self.module.get_bin_path(self.INFO, required=True)
dummy, size, dummy = self.module.run_command([cmd, '--noheadings', '-o', 'pv_size', '--units', 'b', '--nosuffix', str(dev)], check_rc=True) dummy, size, dummy = self.module.run_command([cmd, '--noheadings', '-o', 'pv_size', '--units', 'b', '--nosuffix', str(dev)], check_rc=True)
block_count = int(size) pv_size = int(size)
return block_count return pv_size
class Swap(Filesystem): class Swap(Filesystem):
MKFS = 'mkswap' MKFS = 'mkswap'
MKFS_FORCE_FLAGS = '-f' MKFS_FORCE_FLAGS = ['-f']
FILESYSTEMS = { FILESYSTEMS = {
@ -439,6 +469,10 @@ def main():
force = module.params['force'] force = module.params['force']
resizefs = module.params['resizefs'] resizefs = module.params['resizefs']
mkfs_opts = []
if opts is not None:
mkfs_opts = opts.split()
changed = False changed = False
if not os.path.exists(dev): if not os.path.exists(dev):
@ -451,7 +485,7 @@ def main():
dev = Device(module, dev) dev = Device(module, dev)
cmd = module.get_bin_path('blkid', required=True) cmd = module.get_bin_path('blkid', required=True)
rc, raw_fs, err = module.run_command("%s -c /dev/null -o value -s TYPE %s" % (cmd, dev)) rc, raw_fs, err = module.run_command([cmd, '-c', os.devnull, '-o', 'value', '-s', 'TYPE', str(dev)])
# In case blkid isn't able to identify an existing filesystem, device is considered as empty, # In case blkid isn't able to identify an existing filesystem, device is considered as empty,
# then this existing filesystem would be overwritten even if force isn't enabled. # then this existing filesystem would be overwritten even if force isn't enabled.
fs = raw_fs.strip() fs = raw_fs.strip()
@ -481,7 +515,7 @@ def main():
module.fail_json(msg="'%s' is already used as %s, use force=yes to overwrite" % (dev, fs), rc=rc, err=err) module.fail_json(msg="'%s' is already used as %s, use force=yes to overwrite" % (dev, fs), rc=rc, err=err)
# create fs # create fs
filesystem.create(opts, dev) filesystem.create(mkfs_opts, dev)
changed = True changed = True
elif fs: elif fs:

View file

@ -17,7 +17,9 @@ tested_filesystems:
ext2: {fssize: 10, grow: True} ext2: {fssize: 10, grow: True}
xfs: {fssize: 20, grow: False} # grow requires a mounted filesystem xfs: {fssize: 20, grow: False} # grow requires a mounted filesystem
btrfs: {fssize: 150, grow: False} # grow not implemented btrfs: {fssize: 150, grow: False} # grow not implemented
reiserfs: {fssize: 33, grow: False} # grow not implemented
vfat: {fssize: 20, grow: True} vfat: {fssize: 20, grow: True}
ocfs2: {fssize: '{{ ocfs2_fssize }}', grow: False} # grow not implemented ocfs2: {fssize: '{{ ocfs2_fssize }}', grow: False} # grow not implemented
f2fs: {fssize: '{{ f2fs_fssize|default(60) }}', grow: 'f2fs_version is version("1.10.0", ">=")'} f2fs: {fssize: '{{ f2fs_fssize|default(60) }}', grow: 'f2fs_version is version("1.10.0", ">=")'}
lvm: {fssize: 20, grow: True} lvm: {fssize: 20, grow: True}
swap: {fssize: 10, grow: False} # grow not implemented

View file

@ -1,6 +1,9 @@
--- ---
- name: 'Create a "disk" file' - name: 'Create a "disk" file'
command: 'dd if=/dev/zero of={{ image_file }} bs=1M count={{ fssize }}' community.general.filesize:
path: '{{ image_file }}'
size: '{{ fssize }}M'
force: true
- vars: - vars:
dev: '{{ image_file }}' dev: '{{ image_file }}'
@ -8,26 +11,29 @@
- when: fstype == 'lvm' - when: fstype == 'lvm'
block: block:
- name: 'Create a loop device for LVM' - name: 'Create a loop device for LVM'
command: 'losetup --show -f {{ dev }}' ansible.builtin.command:
cmd: 'losetup --show -f {{ dev }}'
register: loop_device_cmd register: loop_device_cmd
- set_fact: - name: 'Switch to loop device target for further tasks'
ansible.builtin.set_fact:
dev: "{{ loop_device_cmd.stdout }}" dev: "{{ loop_device_cmd.stdout }}"
- include_tasks: '{{ action }}.yml' - include_tasks: '{{ action }}.yml'
always: always:
- name: 'Detach loop device used for LVM' - name: 'Detach loop device used for LVM'
command: 'losetup -d {{ dev }}' ansible.builtin.command:
args: cmd: 'losetup -d {{ dev }}'
removes: '{{ dev }}' removes: '{{ dev }}'
when: fstype == 'lvm' when: fstype == 'lvm'
- name: 'Clean correct device for LVM' - name: 'Clean correct device for LVM'
set_fact: ansible.builtin.set_fact:
dev: '{{ image_file }}' dev: '{{ image_file }}'
when: fstype == 'lvm' when: fstype == 'lvm'
- file: - name: 'Remove disk image file'
ansible.builtin.file:
name: '{{ image_file }}' name: '{{ image_file }}'
state: absent state: absent

View file

@ -1,43 +1,58 @@
- name: filesystem creation ---
filesystem: - name: "Create filesystem"
community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
fstype: '{{ fstype }}' fstype: '{{ fstype }}'
register: fs_result register: fs_result
- assert: - name: "Assert that results are as expected"
ansible.builtin.assert:
that: that:
- 'fs_result is changed' - 'fs_result is changed'
- 'fs_result is success' - 'fs_result is success'
- command: 'blkid -c /dev/null -o value -s UUID {{ dev }}' - name: "Get UUID of created filesystem"
ansible.builtin.command:
cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}'
changed_when: false
register: uuid register: uuid
- name: "Check that filesystem isn't created if force isn't used" - name: "Check that filesystem isn't created if force isn't used"
filesystem: community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
fstype: '{{ fstype }}' fstype: '{{ fstype }}'
register: fs2_result register: fs2_result
- command: 'blkid -c /dev/null -o value -s UUID {{ dev }}' - name: "Get UUID of the filesystem"
ansible.builtin.command:
cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}'
changed_when: false
register: uuid2 register: uuid2
- assert: - name: "Assert that filesystem UUID is not changed"
ansible.builtin.assert:
that: that:
- 'not (fs2_result is changed)' - 'fs2_result is not changed'
- 'fs2_result is success' - 'fs2_result is success'
- 'uuid.stdout == uuid2.stdout' - 'uuid.stdout == uuid2.stdout'
- name: Check that filesystem is recreated if force is used - name: "Check that filesystem is recreated if force is used"
filesystem: community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
fstype: '{{ fstype }}' fstype: '{{ fstype }}'
force: yes force: yes
register: fs3_result register: fs3_result
- command: 'blkid -c /dev/null -o value -s UUID {{ dev }}' - name: "Get UUID of the new filesystem"
ansible.builtin.command:
cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}'
changed_when: false
register: uuid3 register: uuid3
- assert: - name: "Assert that filesystem UUID is changed"
# libblkid gets no UUID at all for this fstype on FreeBSD
when: not (ansible_system == 'FreeBSD' and fstype == 'reiserfs')
ansible.builtin.assert:
that: that:
- 'fs3_result is changed' - 'fs3_result is changed'
- 'fs3_result is success' - 'fs3_result is success'
@ -46,24 +61,31 @@
- when: 'grow|bool and (fstype != "vfat" or resize_vfat)' - when: 'grow|bool and (fstype != "vfat" or resize_vfat)'
block: block:
- name: increase fake device - name: "Increase fake device"
shell: 'dd if=/dev/zero bs=1M count=1 >> {{ image_file }}' community.general.filesize:
path: '{{ image_file }}'
size: '{{ fssize | int + 1 }}M'
- name: Resize loop device for LVM - name: "Resize loop device for LVM"
command: losetup -c {{ dev }} ansible.builtin.command:
cmd: 'losetup -c {{ dev }}'
when: fstype == 'lvm' when: fstype == 'lvm'
- name: Expand filesystem - name: "Expand filesystem"
filesystem: community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
fstype: '{{ fstype }}' fstype: '{{ fstype }}'
resizefs: yes resizefs: yes
register: fs4_result register: fs4_result
- command: 'blkid -c /dev/null -o value -s UUID {{ dev }}' - name: "Get UUID of the filesystem"
ansible.builtin.command:
cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}'
changed_when: false
register: uuid4 register: uuid4
- assert: - name: "Assert that filesystem UUID is not changed"
ansible.builtin.assert:
that: that:
- 'fs4_result is changed' - 'fs4_result is changed'
- 'fs4_result is success' - 'fs4_result is success'
@ -74,14 +96,15 @@
(fstype == "xfs" and ansible_system == "Linux" and (fstype == "xfs" and ansible_system == "Linux" and
ansible_distribution not in ["CentOS", "Ubuntu"]) ansible_distribution not in ["CentOS", "Ubuntu"])
block: block:
- name: Check that resizefs does nothing if device size is not changed - name: "Check that resizefs does nothing if device size is not changed"
filesystem: community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
fstype: '{{ fstype }}' fstype: '{{ fstype }}'
resizefs: yes resizefs: yes
register: fs5_result register: fs5_result
- assert: - name: "Assert that the state did not change"
ansible.builtin.assert:
that: that:
- 'fs5_result is not changed' - 'fs5_result is not changed'
- 'fs5_result is succeeded' - 'fs5_result is succeeded'

View file

@ -4,9 +4,9 @@
# and should not be used as examples of how to write Ansible roles # # and should not be used as examples of how to write Ansible roles #
#################################################################### ####################################################################
- debug: - ansible.builtin.debug:
msg: '{{ role_name }}' msg: '{{ role_name }}'
- debug: - ansible.builtin.debug:
msg: '{{ role_path|basename }}' msg: '{{ role_path|basename }}'
- import_tasks: setup.yml - import_tasks: setup.yml
@ -27,29 +27,35 @@
grow: '{{ item.0.value.grow }}' grow: '{{ item.0.value.grow }}'
action: '{{ item.1 }}' action: '{{ item.1 }}'
when: when:
- 'not (item.0.key == "btrfs" and ansible_system == "FreeBSD")' # btrfs not available on FreeBSD # FreeBSD limited support
# On Ubuntu trusty, blkid is unable to identify filesystem smaller than 256Mo, see # Not available: btrfs, lvm, f2fs, ocfs2
# https://www.kernel.org/pub/linux/utils/util-linux/v2.21/v2.21-ChangeLog # All BSD systems use swap fs, but only Linux needs mkswap
# https://anonscm.debian.org/cgit/collab-maint/pkg-util-linux.git/commit/?id=04f7020eadf31efc731558df92daa0a1c336c46c # Supported: ext2/3/4 (e2fsprogs), xfs (xfsprogs), reiserfs (progsreiserfs), vfat
- 'not (item.0.key == "btrfs" and (ansible_distribution == "Ubuntu" and ansible_distribution_release == "trusty"))' - 'not (ansible_system == "FreeBSD" and item.0.key in ["btrfs", "f2fs", "swap", "lvm", "ocfs2"])'
- 'not (item.0.key == "btrfs" and (ansible_facts.os_family == "RedHat" and ansible_facts.distribution_major_version is version("8", ">=")))' # Available on FreeBSD but not on testbed (util-linux conflicts with e2fsprogs): wipefs, mkfs.minix
- 'not (item.0.key == "lvm" and ansible_system == "FreeBSD")' # LVM not available on FreeBSD - 'not (ansible_system == "FreeBSD" and item.1 in ["overwrite_another_fs", "remove_fs"])'
- 'not (item.0.key == "lvm" and ansible_virtualization_type in ["docker", "container", "containerd"])' # Tests use losetup which can not be used inside unprivileged container
- 'not (item.0.key == "ocfs2" and ansible_os_family != "Debian")' # ocfs2 only available on Debian based distributions # Other limitations and corner cases
- 'not (item.0.key == "f2fs" and ansible_system == "FreeBSD")'
# f2fs-tools package not available with RHEL/CentOS # f2fs-tools and reiserfs-utils packages not available with RHEL/CentOS on CI
- 'not (item.0.key == "f2fs" and ansible_distribution in ["CentOS", "RedHat"])' - 'not (ansible_distribution in ["CentOS", "RedHat"] and item.0.key in ["f2fs", "reiserfs"])'
# On Ubuntu trusty, blkid (2.20.1) is unable to identify F2FS filesystem. blkid handles F2FS since v2.23, see: - 'not (ansible_os_family == "RedHat" and ansible_distribution_major_version is version("8", ">=") and
# https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.23/v2.23-ReleaseNotes item.0.key == "btrfs")'
- 'not (item.0.key == "f2fs" and ansible_distribution == "Ubuntu" and ansible_distribution_version is version("14.04", "<="))' # ocfs2 only available on Debian based distributions
- 'not (item.1 == "overwrite_another_fs" and ansible_system == "FreeBSD")' - 'not (item.0.key == "ocfs2" and ansible_os_family != "Debian")'
# Tests use losetup which can not be used inside unprivileged container
- 'not (item.0.key == "lvm" and ansible_virtualization_type in ["docker", "container", "containerd"])'
- 'not (item.1 == "remove_fs" and ansible_system == "FreeBSD")' # util-linux not available on FreeBSD
# On CentOS 6 shippable containers, wipefs seems unable to remove vfat signatures # On CentOS 6 shippable containers, wipefs seems unable to remove vfat signatures
- 'not (item.1 == "remove_fs" and item.0.key == "vfat" and ansible_distribution == "CentOS" and - 'not (ansible_distribution == "CentOS" and ansible_distribution_version is version("7.0", "<") and
ansible_distribution_version is version("7.0", "<"))' item.1 == "remove_fs" and item.0.key == "vfat")'
# On same systems, mkfs.minix (unhandled by the module) can't find the device/file
- 'not (ansible_distribution == "CentOS" and ansible_distribution_version is version("7.0", "<") and
item.1 == "overwrite_another_fs")'
# The xfsprogs package on newer versions of OpenSUSE (15+) require Python 3, we skip this on our Python 2 container # The xfsprogs package on newer versions of OpenSUSE (15+) require Python 3, we skip this on our Python 2 container
# OpenSUSE 42.3 Python2 and the other py3 containers are not affected so we will continue to run that # OpenSUSE 42.3 Python2 and the other py3 containers are not affected so we will continue to run that
- 'not (item.0.key == "xfs" and ansible_os_family == "Suse" and ansible_python.version.major == 2 and ansible_distribution_major_version|int != 42)' - 'not (ansible_os_family == "Suse" and ansible_distribution_major_version|int != 42 and
item.0.key == "xfs" and ansible_python.version.major == 2)'
loop: "{{ query('dict', tested_filesystems)|product(['create_fs', 'overwrite_another_fs', 'remove_fs'])|list }}" loop: "{{ query('dict', tested_filesystems)|product(['create_fs', 'overwrite_another_fs', 'remove_fs'])|list }}"

View file

@ -1,40 +1,55 @@
--- ---
- name: 'Recreate "disk" file' - name: 'Recreate "disk" file'
command: 'dd if=/dev/zero of={{ image_file }} bs=1M count={{ fssize }}' community.general.filesize:
path: '{{ image_file }}'
size: '{{ fssize }}M'
force: true
- name: 'Create a swap filesystem' - name: 'Create a minix filesystem'
command: 'mkswap {{ dev }}' ansible.builtin.command:
cmd: 'mkfs.minix {{ dev }}'
- command: 'blkid -c /dev/null -o value -s UUID {{ dev }}' - name: 'Get UUID of the new filesystem'
ansible.builtin.command:
cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}'
changed_when: false
register: uuid register: uuid
- name: "Check that an existing filesystem (not handled by this module) isn't overwritten when force isn't used" - name: "Check that an existing filesystem (not handled by this module) isn't overwritten when force isn't used"
filesystem: community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
fstype: '{{ fstype }}' fstype: '{{ fstype }}'
register: fs_result register: fs_result
ignore_errors: True ignore_errors: True
- command: 'blkid -c /dev/null -o value -s UUID {{ dev }}' - name: 'Get UUID of the filesystem'
ansible.builtin.command:
cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}'
changed_when: false
register: uuid2 register: uuid2
- assert: - name: 'Assert that module failed and filesystem UUID is not changed'
ansible.builtin.assert:
that: that:
- 'fs_result is failed' - 'fs_result is failed'
- 'uuid.stdout == uuid2.stdout' - 'uuid.stdout == uuid2.stdout'
- name: "Check that an existing filesystem (not handled by this module) is overwritten when force is used" - name: "Check that an existing filesystem (not handled by this module) is overwritten when force is used"
filesystem: community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
fstype: '{{ fstype }}' fstype: '{{ fstype }}'
force: yes force: yes
register: fs_result2 register: fs_result2
- command: 'blkid -c /dev/null -o value -s UUID {{ dev }}' - name: 'Get UUID of the new filesystem'
ansible.builtin.command:
cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}'
changed_when: false
register: uuid3 register: uuid3
- assert: - name: 'Assert that module succeeded and filesystem UUID is changed'
ansible.builtin.assert:
that: that:
- 'fs_result2 is successful' - 'fs_result2 is success'
- 'fs_result2 is changed' - 'fs_result2 is changed'
- 'uuid2.stdout != uuid3.stdout' - 'uuid2.stdout != uuid3.stdout'

View file

@ -1,98 +1,98 @@
--- ---
# We assume 'create_fs' tests have passed. # We assume 'create_fs' tests have passed.
- name: filesystem creation - name: "Create filesystem"
filesystem: community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
fstype: '{{ fstype }}' fstype: '{{ fstype }}'
- name: get filesystem UUID with 'blkid' - name: "Get filesystem UUID with 'blkid'"
command: ansible.builtin.command:
cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}' cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}'
changed_when: false changed_when: false
register: blkid_ref register: blkid_ref
- name: Assert that a filesystem exists on top of the device - name: "Assert that a filesystem exists on top of the device"
assert: ansible.builtin.assert:
that: that:
- blkid_ref.stdout | length > 0 - blkid_ref.stdout | length > 0
# Test check_mode first # Test check_mode first
- name: filesystem removal (check mode) - name: "Remove filesystem (check mode)"
filesystem: community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
state: absent state: absent
register: wipefs register: wipefs
check_mode: yes check_mode: yes
- name: get filesystem UUID with 'blkid' (should remain the same) - name: "Get filesystem UUID with 'blkid' (should remain the same)"
command: ansible.builtin.command:
cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}' cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}'
changed_when: false changed_when: false
register: blkid register: blkid
- name: Assert that the state changed but the filesystem still exists - name: "Assert that the state changed but the filesystem still exists"
assert: ansible.builtin.assert:
that: that:
- wipefs is changed - wipefs is changed
- blkid.stdout == blkid_ref.stdout - blkid.stdout == blkid_ref.stdout
# Do it # Do it
- name: filesystem removal - name: "Remove filesystem"
filesystem: community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
state: absent state: absent
register: wipefs register: wipefs
- name: get filesystem UUID with 'blkid' (should be empty) - name: "Get filesystem UUID with 'blkid' (should be empty)"
command: ansible.builtin.command:
cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}' cmd: 'blkid -c /dev/null -o value -s UUID {{ dev }}'
changed_when: false changed_when: false
failed_when: false failed_when: false
register: blkid register: blkid
- name: Assert that the state changed and the device has no filesystem - name: "Assert that the state changed and the device has no filesystem"
assert: ansible.builtin.assert:
that: that:
- wipefs is changed - wipefs is changed
- blkid.stdout | length == 0 - blkid.stdout | length == 0
- blkid.rc == 2 - blkid.rc == 2
# Do it again # Do it again
- name: filesystem removal (idempotency) - name: "Remove filesystem (idempotency)"
filesystem: community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
state: absent state: absent
register: wipefs register: wipefs
- name: Assert that the state did not change - name: "Assert that the state did not change"
assert: ansible.builtin.assert:
that: that:
- wipefs is not changed - wipefs is not changed
# and again # and again
- name: filesystem removal (idempotency, check mode) - name: "Remove filesystem (idempotency, check mode)"
filesystem: community.general.filesystem:
dev: '{{ dev }}' dev: '{{ dev }}'
state: absent state: absent
register: wipefs register: wipefs
check_mode: yes check_mode: yes
- name: Assert that the state did not change - name: "Assert that the state did not change"
assert: ansible.builtin.assert:
that: that:
- wipefs is not changed - wipefs is not changed
# By the way, test removal of a filesystem on unexistent device # By the way, test removal of a filesystem on unexistent device
- name: filesystem removal (unexistent device) - name: "Remove filesystem (unexistent device)"
filesystem: community.general.filesystem:
dev: '/dev/unexistent_device' dev: '/dev/unexistent_device'
state: absent state: absent
register: wipefs register: wipefs
- name: Assert that the state did not change - name: "Assert that the state did not change"
assert: ansible.builtin.assert:
that: that:
- wipefs is not changed - wipefs is not changed

View file

@ -1,6 +1,9 @@
--- ---
- name: install filesystem tools # By installing e2fsprogs on FreeBSD, we get a usable blkid command, but this
package: # package conflicts with util-linux, that provides blkid too, but also wipefs
# (required for filesystem state=absent).
- name: "Install filesystem tools"
ansible.builtin.package:
name: '{{ item }}' name: '{{ item }}'
state: present state: present
# xfsprogs on OpenSUSE requires Python 3, skip this for our newer Py2 OpenSUSE builds # xfsprogs on OpenSUSE requires Python 3, skip this for our newer Py2 OpenSUSE builds
@ -9,86 +12,134 @@
- e2fsprogs - e2fsprogs
- xfsprogs - xfsprogs
- block: - name: "Install btrfs progs"
- name: install btrfs progs ansible.builtin.package:
package: name: btrfs-progs
name: btrfs-progs state: present
state: present when:
when: - ansible_os_family != 'Suse'
- ansible_os_family != 'Suse' - not (ansible_distribution == 'Ubuntu' and ansible_distribution_version is version('16.04', '<='))
- not (ansible_distribution == 'Ubuntu' and ansible_distribution_version is version('16.04', '<=')) - ansible_system != "FreeBSD"
- ansible_system != "FreeBSD" - not (ansible_facts.os_family == "RedHat" and ansible_facts.distribution_major_version is version('8', '>='))
- not (ansible_facts.os_family == "RedHat" and ansible_facts.distribution_major_version is version('8', '>='))
- name: install btrfs progs (Ubuntu <= 16.04) - name: "Install btrfs tools (Ubuntu <= 16.04)"
package: ansible.builtin.package:
name: btrfs-tools name: btrfs-tools
state: present state: present
when: ansible_distribution == 'Ubuntu' and ansible_distribution_version is version('16.04', '<=') when:
- ansible_distribution == 'Ubuntu'
- ansible_distribution_version is version('16.04', '<=')
- name: install btrfs progs (OpenSuse) - name: "Install btrfs progs (OpenSuse)"
package: ansible.builtin.package:
name: '{{ item }}' name: '{{ item }}'
state: present state: present
when: ansible_os_family == 'Suse' when: ansible_os_family == 'Suse'
with_items: with_items:
- python{{ ansible_python.version.major }}-xml - python{{ ansible_python.version.major }}-xml
- btrfsprogs - btrfsprogs
- name: install ocfs2 (Debian) - name: "Install reiserfs utils (Fedora)"
package: ansible.builtin.package:
name: ocfs2-tools name: reiserfs-utils
state: present state: present
when: ansible_os_family == 'Debian' when:
- ansible_distribution == 'Fedora'
- when: - name: "Install reiserfs (OpenSuse)"
- ansible_os_family != 'RedHat' or ansible_distribution == 'Fedora' ansible.builtin.package:
- ansible_distribution != 'Ubuntu' or ansible_distribution_version is version('16.04', '>=') name: reiserfs
- ansible_system != "FreeBSD" state: present
block: when:
- name: install f2fs - ansible_os_family == 'Suse'
package:
name: f2fs-tools
state: present
- name: fetch f2fs version - name: "Install reiserfs progs (Debian and more)"
command: mkfs.f2fs /dev/null ansible.builtin.package:
ignore_errors: yes name: reiserfsprogs
register: mkfs_f2fs state: present
when:
- ansible_system == 'Linux'
- ansible_os_family not in ['Suse', 'RedHat']
- set_fact: - name: "Install reiserfs progs (FreeBSD)"
f2fs_version: '{{ mkfs_f2fs.stdout | regex_search("F2FS-tools: mkfs.f2fs Ver:.*") | regex_replace("F2FS-tools: mkfs.f2fs Ver: ([0-9.]+) .*", "\1") }}' ansible.builtin.package:
name: progsreiserfs
state: present
when:
- ansible_system == 'FreeBSD'
- name: install dosfstools and lvm2 (Linux) - name: "Install ocfs2 (Debian)"
package: ansible.builtin.package:
name: '{{ item }}' name: ocfs2-tools
with_items: state: present
- dosfstools when: ansible_os_family == 'Debian'
- lvm2
when: ansible_system == 'Linux'
- block: - name: "Install f2fs tools and get version"
- name: install fatresize when:
package: - ansible_os_family != 'RedHat' or ansible_distribution == 'Fedora'
name: fatresize - ansible_distribution != 'Ubuntu' or ansible_distribution_version is version('16.04', '>=')
state: present - ansible_system != "FreeBSD"
- command: fatresize --help block:
register: fatresize - name: "Install f2fs tools"
- set_fact: ansible.builtin.package:
fatresize_version: '{{ fatresize.stdout_lines[0] | regex_search("[0-9]+\.[0-9]+\.[0-9]+") }}' name: f2fs-tools
state: present
- name: "Fetch f2fs version"
ansible.builtin.command:
cmd: mkfs.f2fs /dev/null
changed_when: false
ignore_errors: true
register: mkfs_f2fs
- name: "Record f2fs_version"
ansible.builtin.set_fact:
f2fs_version: '{{ mkfs_f2fs.stdout
| regex_search("F2FS-tools: mkfs.f2fs Ver:.*")
| regex_replace("F2FS-tools: mkfs.f2fs Ver: ([0-9.]+) .*", "\1") }}'
- name: "Install dosfstools and lvm2 (Linux)"
ansible.builtin.package:
name: '{{ item }}'
with_items:
- dosfstools
- lvm2
when: ansible_system == 'Linux'
- name: "Install fatresize and get version"
when: when:
- ansible_system == 'Linux' - ansible_system == 'Linux'
- ansible_os_family != 'Suse' - ansible_os_family != 'Suse'
- ansible_os_family != 'RedHat' or (ansible_distribution == 'CentOS' and ansible_distribution_version is version('7.0', '==')) - ansible_os_family != 'RedHat' or (ansible_distribution == 'CentOS' and ansible_distribution_version is version('7.0', '=='))
block:
- name: "Install fatresize"
ansible.builtin.package:
name: fatresize
state: present
- command: mke2fs -V - name: "Fetch fatresize version"
ansible.builtin.command:
cmd: fatresize --help
changed_when: false
register: fatresize
- name: "Record fatresize_version"
ansible.builtin.set_fact:
fatresize_version: '{{ fatresize.stdout_lines[0] | regex_search("[0-9]+\.[0-9]+\.[0-9]+") }}'
- name: "Fetch e2fsprogs version"
ansible.builtin.command:
cmd: mke2fs -V
changed_when: false
register: mke2fs register: mke2fs
- set_fact: - name: "Record e2fsprogs_version"
ansible.builtin.set_fact:
# mke2fs 1.43.6 (29-Aug-2017) # mke2fs 1.43.6 (29-Aug-2017)
e2fsprogs_version: '{{ mke2fs.stderr_lines[0] | regex_search("[0-9]{1,2}\.[0-9]{1,2}(\.[0-9]{1,2})?") }}' e2fsprogs_version: '{{ mke2fs.stderr_lines[0] | regex_search("[0-9]{1,2}\.[0-9]{1,2}(\.[0-9]{1,2})?") }}'
- set_fact: - name: "Set version-related facts to skip further tasks"
ansible.builtin.set_fact:
# http://e2fsprogs.sourceforge.net/e2fsprogs-release.html#1.43 # http://e2fsprogs.sourceforge.net/e2fsprogs-release.html#1.43
# Mke2fs no longer complains if the user tries to create a file system # Mke2fs no longer complains if the user tries to create a file system
# using the entire block device. # using the entire block device.