mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-06-01 05:49:09 -07:00
Add vfat support for the filesystem module (#23527)
* Add fat filesystem support fatresize is temporarily disabled * Refactor Filesystem.get_dev_size For more sharing with vFAT class * Fix filesystem tests on some OSs I think this is due to older mke2fs on those systems. * Fix vFAT command on FreeBSD newfs doesn't seem to work on image files * Refactor filesystem.grow() Split out grow_cmd generation and Device operations * Use swap as unsupported filesystem Except FreeBSD, which doesn't have mkswap * Be consistent about str(dev) vs dev.path Prefer str(dev), this works transparently with '%s' formatting. * Enable vfat resize, only test fatresize >= 1.0.4 Lower versions have a segfault bug. * Only install fatresize where available FreeBSD, OpenSUSE, RHEL and CentOS < 7 don't ship it.
This commit is contained in:
parent
67c217398c
commit
f30a08d049
5 changed files with 83 additions and 37 deletions
|
@ -22,12 +22,13 @@ description:
|
|||
version_added: "1.2"
|
||||
options:
|
||||
fstype:
|
||||
choices: [ btrfs, ext2, ext3, ext4, ext4dev, lvm, reiserfs, xfs ]
|
||||
choices: [ btrfs, ext2, ext3, ext4, ext4dev, lvm, reiserfs, xfs, vfat ]
|
||||
description:
|
||||
- Filesystem type to be created.
|
||||
- reiserfs support was added in 2.2.
|
||||
- lvm support was added in 2.5.
|
||||
- since 2.5, I(dev) can be an image file.
|
||||
- vfat support was added in 2.5
|
||||
required: yes
|
||||
dev:
|
||||
description:
|
||||
|
@ -41,8 +42,9 @@ options:
|
|||
resizefs:
|
||||
description:
|
||||
- If C(yes), if the block device and filesytem size differ, grow the filesystem into the space.
|
||||
- Supported for C(ext2), C(ext3), C(ext4), C(ext4dev), C(lvm) and C(xfs) filesystems.
|
||||
- Supported for C(ext2), C(ext3), C(ext4), C(ext4dev), C(lvm), C(xfs) and C(vfat) filesystems.
|
||||
- XFS Will only grow if mounted.
|
||||
- vFAT will likely fail if fatresize < 1.04.
|
||||
type: bool
|
||||
default: 'no'
|
||||
version_added: "2.0"
|
||||
|
@ -74,8 +76,28 @@ import os
|
|||
import re
|
||||
import stat
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.six import viewkeys
|
||||
from ansible.module_utils.basic import AnsibleModule, get_platform
|
||||
|
||||
|
||||
class Device(object):
|
||||
def __init__(self, module, path):
|
||||
self.module = module
|
||||
self.path = path
|
||||
|
||||
def size(self):
|
||||
""" Return size in bytes of device. Returns int """
|
||||
statinfo = os.stat(self.path)
|
||||
if stat.S_ISBLK(statinfo.st_mode):
|
||||
blockdev_cmd = self.module.get_bin_path("blockdev", required=True)
|
||||
_, devsize_in_bytes, _ = self.module.run_command([blockdev_cmd, "--getsize64", self.path], check_rc=True)
|
||||
return int(devsize_in_bytes)
|
||||
elif os.path.isfile(self.path):
|
||||
return os.path.getsize(self.path)
|
||||
else:
|
||||
self.module.fail_json(changed=False, msg="Target device not supported: %s" % self)
|
||||
|
||||
def __str__(self):
|
||||
return self.path
|
||||
|
||||
|
||||
class Filesystem(object):
|
||||
|
@ -91,12 +113,6 @@ class Filesystem(object):
|
|||
def fstype(self):
|
||||
return type(self).__name__
|
||||
|
||||
def get_dev_size(self, dev):
|
||||
""" Return size in bytes of device. Returns int """
|
||||
blockdev_cmd = self.module.get_bin_path("blockdev", required=True)
|
||||
_, devsize_in_bytes, _ = self.module.run_command("%s %s %s" % (blockdev_cmd, "--getsize64", dev), check_rc=True)
|
||||
return int(devsize_in_bytes)
|
||||
|
||||
def get_fs_size(self, dev):
|
||||
""" Return size in bytes of filesystem on device. Returns int """
|
||||
raise NotImplementedError()
|
||||
|
@ -112,32 +128,26 @@ class Filesystem(object):
|
|||
cmd = "%s %s %s '%s'" % (mkfs, self.MKFS_FORCE_FLAGS, opts, dev)
|
||||
self.module.run_command(cmd, check_rc=True)
|
||||
|
||||
def grow_cmd(self, dev):
|
||||
cmd = self.module.get_bin_path(self.GROW, required=True)
|
||||
return [cmd, str(dev)]
|
||||
|
||||
def grow(self, dev):
|
||||
"""Get dev and fs size and compare. Returns stdout of used command."""
|
||||
statinfo = os.stat(dev)
|
||||
if stat.S_ISBLK(statinfo.st_mode):
|
||||
devsize_in_bytes = self.get_dev_size(dev)
|
||||
elif os.path.isfile(dev):
|
||||
devsize_in_bytes = os.path.getsize(dev)
|
||||
else:
|
||||
self.module.fail_json(changed=False, msg="Target device not supported: %r." % dev)
|
||||
devsize_in_bytes = dev.size()
|
||||
|
||||
try:
|
||||
fssize_in_bytes = self.get_fs_size(dev)
|
||||
except NotImplementedError:
|
||||
self.module.fail_json(changed=False, msg="module does not support resizing %s filesystem yet." % self.fstype)
|
||||
fs_smaller = fssize_in_bytes < devsize_in_bytes
|
||||
|
||||
if self.module.check_mode and fs_smaller:
|
||||
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))
|
||||
elif self.module.check_mode:
|
||||
self.module.exit_json(changed=True, msg="Resizing filesystem %s on device %s" % (self.fstype, dev))
|
||||
elif self.module.check_mode and not fs_smaller:
|
||||
self.module.exit_json(changed=False, msg="%s filesystem is using the whole device %s" % (self.fstype, dev))
|
||||
elif fs_smaller:
|
||||
cmd = self.module.get_bin_path(self.GROW, required=True)
|
||||
_, out, _ = self.module.run_command("%s %s" % (cmd, dev), check_rc=True)
|
||||
return out
|
||||
else:
|
||||
self.module.exit_json(changed=False, msg="%s filesystem is using the whole device %s" % (self.fstype, dev))
|
||||
_, out, _ = self.module.run_command(self.grow_cmd(dev), check_rc=True)
|
||||
return out
|
||||
|
||||
|
||||
class Ext(Filesystem):
|
||||
|
@ -147,7 +157,7 @@ class Ext(Filesystem):
|
|||
def get_fs_size(self, dev):
|
||||
cmd = self.module.get_bin_path('tune2fs', required=True)
|
||||
# Get Block count and Block size
|
||||
_, size, _ = self.module.run_command([cmd, '-l', dev], check_rc=True)
|
||||
_, size, _ = self.module.run_command([cmd, '-l', str(dev)], check_rc=True)
|
||||
for line in size.splitlines():
|
||||
if 'Block count:' in line:
|
||||
block_count = int(line.split(':')[1].strip())
|
||||
|
@ -175,7 +185,7 @@ class XFS(Filesystem):
|
|||
|
||||
def get_fs_size(self, dev):
|
||||
cmd = self.module.get_bin_path('xfs_growfs', required=True)
|
||||
_, size, _ = self.module.run_command([cmd, '-n', dev], check_rc=True)
|
||||
_, size, _ = self.module.run_command([cmd, '-n', str(dev)], check_rc=True)
|
||||
for line in size.splitlines():
|
||||
col = line.split('=')
|
||||
if col[0].strip() == 'data':
|
||||
|
@ -215,6 +225,27 @@ class Btrfs(Filesystem):
|
|||
self.module.warn('Unable to identify mkfs.btrfs version (%r, %r)' % (stdout, stderr))
|
||||
|
||||
|
||||
class VFAT(Filesystem):
|
||||
if get_platform() == 'FreeBSD':
|
||||
MKFS = "newfs_msdos"
|
||||
else:
|
||||
MKFS = 'mkfs.vfat'
|
||||
GROW = 'fatresize'
|
||||
|
||||
def get_fs_size(self, dev):
|
||||
cmd = self.module.get_bin_path(self.GROW, required=True)
|
||||
_, output, _ = self.module.run_command([cmd, '--info', str(dev)], check_rc=True)
|
||||
for line in output.splitlines()[1:]:
|
||||
param, value = line.split(':', 1)
|
||||
if param.strip() == 'Size':
|
||||
return int(value.strip())
|
||||
self.module.fail_json(msg="fatresize failed to provide filesystem size for %s" % dev)
|
||||
|
||||
def grow_cmd(self, dev):
|
||||
cmd = self.module.get_bin_path(self.GROW)
|
||||
return [cmd, "-s", str(dev.size()), str(dev.path)]
|
||||
|
||||
|
||||
class LVM(Filesystem):
|
||||
MKFS = 'pvcreate'
|
||||
MKFS_FORCE_FLAGS = '-f'
|
||||
|
@ -222,7 +253,7 @@ class LVM(Filesystem):
|
|||
|
||||
def get_fs_size(self, dev):
|
||||
cmd = self.module.get_bin_path('pvs', required=True)
|
||||
_, size, _ = self.module.run_command([cmd, '--noheadings', '-o', 'pv_size', '--units', 'b', dev], check_rc=True)
|
||||
_, size, _ = self.module.run_command([cmd, '--noheadings', '-o', 'pv_size', '--units', 'b', str(dev)], check_rc=True)
|
||||
block_count = int(size[:-1]) # block size is 1
|
||||
return block_count
|
||||
|
||||
|
@ -235,6 +266,7 @@ FILESYSTEMS = {
|
|||
'reiserfs': Reiserfs,
|
||||
'xfs': XFS,
|
||||
'btrfs': Btrfs,
|
||||
'vfat': VFAT,
|
||||
'LVM2_member': LVM,
|
||||
}
|
||||
|
||||
|
@ -275,6 +307,7 @@ def main():
|
|||
|
||||
if not os.path.exists(dev):
|
||||
module.fail_json(msg="Device %s not found." % dev)
|
||||
dev = Device(module, dev)
|
||||
|
||||
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))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue