diff options
Diffstat (limited to 'ansible_collections/community/general/plugins/modules/filesystem.py')
-rw-r--r-- | ansible_collections/community/general/plugins/modules/filesystem.py | 132 |
1 files changed, 110 insertions, 22 deletions
diff --git a/ansible_collections/community/general/plugins/modules/filesystem.py b/ansible_collections/community/general/plugins/modules/filesystem.py index 0e6b815b4..ec361245b 100644 --- a/ansible_collections/community/general/plugins/modules/filesystem.py +++ b/ansible_collections/community/general/plugins/modules/filesystem.py @@ -29,12 +29,12 @@ attributes: options: state: description: - - If I(state=present), the filesystem is created if it doesn't already - exist, that is the default behaviour if I(state) is omitted. - - If I(state=absent), filesystem signatures on I(dev) are wiped if it + - If O(state=present), the filesystem is created if it doesn't already + exist, that is the default behaviour if O(state) is omitted. + - If O(state=absent), filesystem signatures on O(dev) are wiped if it contains a filesystem (as known by C(blkid)). - - When I(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. + - When O(state=absent), all other options but O(dev) are ignored, and the + module does not fail if the device O(dev) doesn't actually exist. type: str choices: [ present, absent ] default: present @@ -43,7 +43,7 @@ options: choices: [ btrfs, ext2, ext3, ext4, ext4dev, f2fs, lvm, ocfs2, reiserfs, xfs, vfat, swap, ufs ] description: - Filesystem type to be created. This option is required with - I(state=present) (or if I(state) is omitted). + O(state=present) (or if O(state) is omitted). - ufs support has been added in community.general 3.4.0. type: str aliases: [type] @@ -53,50 +53,68 @@ options: regular file (both). - When setting Linux-specific filesystem types on FreeBSD, this module only works when applying to regular files, aka disk images. - - Currently C(lvm) (Linux-only) and C(ufs) (FreeBSD-only) don't support - a regular file as their target I(dev). + - Currently V(lvm) (Linux-only) and V(ufs) (FreeBSD-only) do not support + a regular file as their target O(dev). - Support for character devices on FreeBSD has been added in community.general 3.4.0. type: path required: true aliases: [device] force: description: - - If C(true), allows to create new filesystem on devices that already has filesystem. + - If V(true), allows to create new filesystem on devices that already has filesystem. type: bool default: false resizefs: description: - - If C(true), if the block device and filesystem size differ, grow the filesystem into the space. + - If V(true), if the block device and filesystem size differ, grow the filesystem into the space. - Supported for C(btrfs), C(ext2), C(ext3), C(ext4), C(ext4dev), C(f2fs), C(lvm), C(xfs), C(ufs) and C(vfat) filesystems. Attempts to resize other filesystem types will fail. - 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 not supported on FreeBSD systems. - vFAT will likely fail if C(fatresize < 1.04). + - Mutually exclusive with O(uuid). type: bool default: false opts: description: - List of options to be passed to C(mkfs) command. type: str + uuid: + description: + - Set filesystem's UUID to the given value. + - The UUID options specified in O(opts) take precedence over this value. + - See xfs_admin(8) (C(xfs)), tune2fs(8) (C(ext2), C(ext3), C(ext4), C(ext4dev)) for possible values. + - For O(fstype=lvm) the value is ignored, it resets the PV UUID if set. + - Supported for O(fstype) being one of C(ext2), C(ext3), C(ext4), C(ext4dev), C(lvm), or C(xfs). + - This is B(not idempotent). Specifying this option will always result in a change. + - Mutually exclusive with O(resizefs). + type: str + version_added: 7.1.0 requirements: - - Uses specific tools related to the I(fstype) for creating or resizing a + - Uses specific tools related to the O(fstype) for creating or resizing a filesystem (from packages e2fsprogs, xfsprogs, dosfstools, and so on). - Uses generic tools mostly related to the Operating System (Linux or FreeBSD) or available on both, as C(blkid). - On FreeBSD, either C(util-linux) or C(e2fsprogs) package is required. notes: - - Potential filesystems on I(dev) are checked using C(blkid). In case C(blkid) + - Potential filesystems on O(dev) are checked using C(blkid). In case C(blkid) is unable to detect a filesystem (and in case C(fstyp) on FreeBSD is also unable to detect a filesystem), this filesystem is overwritten even if - I(force) is C(false). + O(force) is V(false). - On FreeBSD systems, both C(e2fsprogs) and C(util-linux) packages provide a C(blkid) command that is compatible with this module. However, these packages conflict with each other, and only the C(util-linux) package - provides the command required to not fail when I(state=absent). + provides the command required to not fail when O(state=absent). seealso: - module: community.general.filesize - module: ansible.posix.mount + - name: xfs_admin(8) manpage for Linux + description: Manual page of the GNU/Linux's xfs_admin implementation + link: https://man7.org/linux/man-pages/man8/xfs_admin.8.html + - name: tune2fs(8) manpage for Linux + description: Manual page of the GNU/Linux's tune2fs implementation + link: https://man7.org/linux/man-pages/man8/tune2fs.8.html ''' EXAMPLES = ''' @@ -120,6 +138,24 @@ EXAMPLES = ''' community.general.filesystem: dev: /path/to/disk.img fstype: vfat + +- name: Reset an xfs filesystem UUID on /dev/sdb1 + community.general.filesystem: + fstype: xfs + dev: /dev/sdb1 + uuid: generate + +- name: Reset an ext4 filesystem UUID on /dev/sdb1 + community.general.filesystem: + fstype: ext4 + dev: /dev/sdb1 + uuid: random + +- name: Reset an LVM filesystem (PV) UUID on /dev/sdc + community.general.filesystem: + fstype: lvm + dev: /dev/sdc + uuid: random ''' import os @@ -178,10 +214,15 @@ class Filesystem(object): MKFS = None MKFS_FORCE_FLAGS = [] + MKFS_SET_UUID_OPTIONS = None + MKFS_SET_UUID_EXTRA_OPTIONS = [] INFO = None GROW = None GROW_MAX_SPACE_FLAGS = [] GROW_MOUNTPOINT_ONLY = False + CHANGE_UUID = None + CHANGE_UUID_OPTION = None + CHANGE_UUID_OPTION_HAS_ARG = True LANG_ENV = {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'} @@ -200,13 +241,19 @@ class Filesystem(object): """ raise NotImplementedError() - def create(self, opts, dev): + def create(self, opts, dev, uuid=None): if self.module.check_mode: return + if uuid and self.MKFS_SET_UUID_OPTIONS: + if not (set(self.MKFS_SET_UUID_OPTIONS) & set(opts)): + opts += [self.MKFS_SET_UUID_OPTIONS[0], uuid] + self.MKFS_SET_UUID_EXTRA_OPTIONS + mkfs = self.module.get_bin_path(self.MKFS, required=True) cmd = [mkfs] + self.MKFS_FORCE_FLAGS + opts + [str(dev)] self.module.run_command(cmd, check_rc=True) + if uuid and self.CHANGE_UUID and self.MKFS_SET_UUID_OPTIONS is None: + self.change_uuid(new_uuid=uuid, dev=dev) def wipefs(self, dev): if self.module.check_mode: @@ -255,11 +302,31 @@ class Filesystem(object): dummy, out, dummy = self.module.run_command(self.grow_cmd(grow_target), check_rc=True) return out + def change_uuid_cmd(self, new_uuid, target): + """Build and return the UUID change command line as list.""" + cmdline = [self.module.get_bin_path(self.CHANGE_UUID, required=True)] + if self.CHANGE_UUID_OPTION_HAS_ARG: + cmdline += [self.CHANGE_UUID_OPTION, new_uuid, target] + else: + cmdline += [self.CHANGE_UUID_OPTION, target] + return cmdline + + def change_uuid(self, new_uuid, dev): + """Change filesystem UUID. Returns stdout of used command""" + if self.module.check_mode: + self.module.exit_json(change=True, msg='Changing %s filesystem UUID on device %s' % (self.fstype, dev)) + + dummy, out, dummy = self.module.run_command(self.change_uuid_cmd(new_uuid=new_uuid, target=str(dev)), check_rc=True) + return out + class Ext(Filesystem): MKFS_FORCE_FLAGS = ['-F'] + MKFS_SET_UUID_OPTIONS = ['-U'] INFO = 'tune2fs' GROW = 'resize2fs' + CHANGE_UUID = 'tune2fs' + CHANGE_UUID_OPTION = "-U" def get_fs_size(self, dev): """Get Block count and Block size and return their product.""" @@ -298,6 +365,8 @@ class XFS(Filesystem): INFO = 'xfs_info' GROW = 'xfs_growfs' GROW_MOUNTPOINT_ONLY = True + CHANGE_UUID = "xfs_admin" + CHANGE_UUID_OPTION = "-U" def get_fs_size(self, dev): """Get bsize and blocks and return their product.""" @@ -451,8 +520,13 @@ class VFAT(Filesystem): class LVM(Filesystem): MKFS = 'pvcreate' MKFS_FORCE_FLAGS = ['-f'] + MKFS_SET_UUID_OPTIONS = ['-u', '--uuid'] + MKFS_SET_UUID_EXTRA_OPTIONS = ['--norestorefile'] INFO = 'pvs' GROW = 'pvresize' + CHANGE_UUID = 'pvchange' + CHANGE_UUID_OPTION = '-u' + CHANGE_UUID_OPTION_HAS_ARG = False def get_fs_size(self, dev): """Get and return PV size, in bytes.""" @@ -525,10 +599,14 @@ def main(): opts=dict(type='str'), force=dict(type='bool', default=False), resizefs=dict(type='bool', default=False), + uuid=dict(type='str', required=False), ), required_if=[ ('state', 'present', ['fstype']) ], + mutually_exclusive=[ + ('resizefs', 'uuid'), + ], supports_check_mode=True, ) @@ -538,6 +616,7 @@ def main(): opts = module.params['opts'] force = module.params['force'] resizefs = module.params['resizefs'] + uuid = module.params['uuid'] mkfs_opts = [] if opts is not None: @@ -576,21 +655,30 @@ def main(): filesystem = klass(module) + if uuid and not (filesystem.CHANGE_UUID or filesystem.MKFS_SET_UUID_OPTIONS): + module.fail_json(changed=False, msg="module does not support UUID option for this filesystem (%s) yet." % fstype) + same_fs = fs and FILESYSTEMS.get(fs) == FILESYSTEMS[fstype] - if same_fs and not resizefs and not force: + if same_fs and not resizefs and not uuid and not force: module.exit_json(changed=False) - elif same_fs and resizefs: - if not filesystem.GROW: - module.fail_json(changed=False, msg="module does not support resizing %s filesystem yet." % fstype) + elif same_fs: + if resizefs: + if not filesystem.GROW: + module.fail_json(changed=False, msg="module does not support resizing %s filesystem yet." % fstype) + + out = filesystem.grow(dev) + + module.exit_json(changed=True, msg=out) + elif uuid: - out = filesystem.grow(dev) + out = filesystem.change_uuid(new_uuid=uuid, dev=dev) - module.exit_json(changed=True, msg=out) + module.exit_json(changed=True, msg=out) elif fs and not force: module.fail_json(msg="'%s' is already used as %s, use force=true to overwrite" % (dev, fs), rc=rc, err=err) # create fs - filesystem.create(mkfs_opts, dev) + filesystem.create(opts=mkfs_opts, dev=dev, uuid=uuid) changed = True elif fs: |