Merge pull request #267 from NeodymiumFerBore/ephemeral_state

Add ephemeral state to mount fs without altering fstab

SUMMARY
Add ephemeral possible value for state parameter.
The ephemeral state allows end-users to mount a volume on a given path, without altering an fstab file or creating a dummy one.
There have been debates about splitting this module into an fstab module and a mount module, but nothing has been done in 5 years. This is why I'd like to propose this feature.
Downside: the way the posix.mount module handles mount options prevents it to be able to check exactly if the given opts perfectly match the mount options of an already mounted volume. To achieve this, the module would have to be aware of every mount default options, for all platforms. This is why state=ephemeral always return changed=yes.
In other terms, a remount will always be triggered if the volume is already mounted, even if the options look to be the same. Using state=unmounted on a volume previously mounted with ephemeral behaves correctly.
ISSUE TYPE

Feature Pull Request

Related issues:

ansible/ansible#48134
#84

COMPONENT NAME
mount
ADDITIONAL INFORMATION
Example use case
Sometimes it is handy to be able to temporarily mount a volume. I've seen this in couple companies where Ansible is used to generate reports and put it on network shares. However, some admins don't look into mount options such as krb5 and multiuser for SMB shares. Being forced to use fstab-based mounts leads to clear text passwords being stored more or less temporarily on the host filesystem, requiring "manual" deletion (with the hassle of using blocks, rescues, always, etc.). This feature respond to this use case by providing a way to mount a volume without having to alter an fstab file.
Description of changes

Edit DOCUMENTATION section to add ephemeral state
Edit EXAMPLES section to add ephemeral state example
Add new function _set_ephemeral_args to use instead of _set_fstab_args when using ephemeral state
Add new function _is_same_mount_src to determine if the mounted volume on the destination path has the same source than the one supplied to the module
Add new function _get_mount_info to avoid redundant code between functions get_linux_mounts and _is_same_mount_src
Modify get_linux_mount to use the new function _get_mount_info. Original behavior is preserved.
Integrate ephemeral parameter treatment into mounted treatment, and add if statements to avoid IO from/to fstab
Add ephemeral as a possible value for the state parameter in main()
Add required_if dependencies for ephemeral state

Reviewed-by: None <None>
Reviewed-by: Hideki Saito <saito@fgrep.org>
Reviewed-by: Abhijeet Kasurde <None>
This commit is contained in:
softwarefactory-project-zuul[bot] 2022-12-15 06:22:17 +00:00 committed by GitHub
commit d537e7ded8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 416 additions and 22 deletions

View file

@ -0,0 +1,4 @@
---
minor_changes:
- mount - Add ``ephemeral`` value for the ``state`` parameter, that allows to mount a filesystem
without altering the ``fstab`` file (https://github.com/ansible-collections/ansible.posix/pull/267).

View file

@ -31,12 +31,12 @@ options:
src: src:
description: description:
- Device (or NFS volume, or something else) to be mounted on I(path). - Device (or NFS volume, or something else) to be mounted on I(path).
- Required when I(state) set to C(present) or C(mounted). - Required when I(state) set to C(present), C(mounted) or C(ephemeral).
type: path type: path
fstype: fstype:
description: description:
- Filesystem type. - Filesystem type.
- Required when I(state) is C(present) or C(mounted). - Required when I(state) is C(present), C(mounted) or C(ephemeral).
type: str type: str
opts: opts:
description: description:
@ -48,7 +48,7 @@ options:
- Note that if set to C(null) and I(state) set to C(present), - Note that if set to C(null) and I(state) set to C(present),
it will cease to work and duplicate entries will be made it will cease to work and duplicate entries will be made
with subsequent runs. with subsequent runs.
- Has no effect on Solaris systems. - Has no effect on Solaris systems or when used with C(ephemeral).
type: str type: str
default: '0' default: '0'
passno: passno:
@ -57,7 +57,7 @@ options:
- Note that if set to C(null) and I(state) set to C(present), - Note that if set to C(null) and I(state) set to C(present),
it will cease to work and duplicate entries will be made it will cease to work and duplicate entries will be made
with subsequent runs. with subsequent runs.
- Deprecated on Solaris systems. - Deprecated on Solaris systems. Has no effect when used with C(ephemeral).
type: str type: str
default: '0' default: '0'
state: state:
@ -68,6 +68,13 @@ options:
- If C(unmounted), the device will be unmounted without changing I(fstab). - If C(unmounted), the device will be unmounted without changing I(fstab).
- C(present) only specifies that the device is to be configured in - C(present) only specifies that the device is to be configured in
I(fstab) and does not trigger or require a mount. I(fstab) and does not trigger or require a mount.
- C(ephemeral) only specifies that the device is to be mounted, without changing
I(fstab). If it is already mounted, a remount will be triggered.
This will always return changed=True. If the mount point I(path)
has already a device mounted on, and its source is different than I(src),
the module will fail to avoid unexpected unmount or mount point override.
If the mount point is not present, the mount point will be created.
The I(fstab) is completely ignored. This option is added in version 1.5.0.
- C(absent) specifies that the device mount's entry will be removed from - C(absent) specifies that the device mount's entry will be removed from
I(fstab) and will also unmount the device and remove the mount I(fstab) and will also unmount the device and remove the mount
point. point.
@ -77,13 +84,15 @@ options:
applied to the remount, but will not change I(fstab). Additionally, applied to the remount, but will not change I(fstab). Additionally,
if I(opts) is set, and the remount command fails, the module will if I(opts) is set, and the remount command fails, the module will
error to prevent unexpected mount changes. Try using C(mounted) error to prevent unexpected mount changes. Try using C(mounted)
instead to work around this issue. instead to work around this issue. C(remounted) expects the mount point
to be present in the I(fstab). To remount a mount point not registered
in I(fstab), use C(ephemeral) instead, especially with BSD nodes.
- C(absent_from_fstab) specifies that the device mount's entry will be - C(absent_from_fstab) specifies that the device mount's entry will be
removed from I(fstab). This option does not unmount it or delete the removed from I(fstab). This option does not unmount it or delete the
mountpoint. mountpoint.
type: str type: str
required: true required: true
choices: [ absent, absent_from_fstab, mounted, present, unmounted, remounted ] choices: [ absent, absent_from_fstab, mounted, present, unmounted, remounted, ephemeral ]
fstab: fstab:
description: description:
- File to use instead of C(/etc/fstab). - File to use instead of C(/etc/fstab).
@ -92,6 +101,7 @@ options:
- OpenBSD does not allow specifying alternate fstab files with mount so do not - OpenBSD does not allow specifying alternate fstab files with mount so do not
use this on OpenBSD with any state that operates on the live filesystem. use this on OpenBSD with any state that operates on the live filesystem.
- This parameter defaults to /etc/fstab or /etc/vfstab on Solaris. - This parameter defaults to /etc/fstab or /etc/vfstab on Solaris.
- This parameter is ignored when I(state) is set to C(ephemeral).
type: str type: str
boot: boot:
description: description:
@ -103,6 +113,7 @@ options:
to mount options in I(/etc/fstab). to mount options in I(/etc/fstab).
- To avoid mount option conflicts, if C(noauto) specified in C(opts), - To avoid mount option conflicts, if C(noauto) specified in C(opts),
mount module will ignore C(boot). mount module will ignore C(boot).
- This parameter is ignored when I(state) is set to C(ephemeral).
type: bool type: bool
default: yes default: yes
backup: backup:
@ -187,6 +198,14 @@ EXAMPLES = r'''
boot: no boot: no
state: mounted state: mounted
fstype: nfs fstype: nfs
- name: Mount ephemeral SMB volume
ansible.posix.mount:
src: //192.168.1.200/share
path: /mnt/smb_share
opts: "rw,vers=3,file_mode=0600,dir_mode=0700,dom={{ ad_domain }},username={{ ad_username }},password={{ ad_password }}"
fstype: cifs
state: ephemeral
''' '''
import errno import errno
@ -433,6 +452,24 @@ def _set_fstab_args(fstab_file):
return result return result
def _set_ephemeral_args(args):
result = []
# Set fstype switch according to platform. SunOS/Solaris use -F
if platform.system().lower() == 'sunos':
result.append('-F')
else:
result.append('-t')
result.append(args['fstype'])
# Even if '-o remount' is already set, specifying multiple -o is valid
if args['opts'] != 'defaults':
result += ['-o', args['opts']]
result.append(args['src'])
return result
def mount(module, args): def mount(module, args):
"""Mount up a path or remount if needed.""" """Mount up a path or remount if needed."""
@ -449,7 +486,11 @@ def mount(module, args):
'OpenBSD does not support alternate fstab files. Do not ' 'OpenBSD does not support alternate fstab files. Do not '
'specify the fstab parameter for OpenBSD hosts')) 'specify the fstab parameter for OpenBSD hosts'))
else: else:
cmd += _set_fstab_args(args['fstab']) if module.params['state'] != 'ephemeral':
cmd += _set_fstab_args(args['fstab'])
if module.params['state'] == 'ephemeral':
cmd += _set_ephemeral_args(args)
cmd += [name] cmd += [name]
@ -501,18 +542,24 @@ def remount(module, args):
'OpenBSD does not support alternate fstab files. Do not ' 'OpenBSD does not support alternate fstab files. Do not '
'specify the fstab parameter for OpenBSD hosts')) 'specify the fstab parameter for OpenBSD hosts'))
else: else:
cmd += _set_fstab_args(args['fstab']) if module.params['state'] != 'ephemeral':
cmd += _set_fstab_args(args['fstab'])
if module.params['state'] == 'ephemeral':
cmd += _set_ephemeral_args(args)
cmd += [args['name']] cmd += [args['name']]
out = err = '' out = err = ''
try: try:
if platform.system().lower().endswith('bsd'): if module.params['state'] != 'ephemeral' and platform.system().lower().endswith('bsd'):
# Note: Forcing BSDs to do umount/mount due to BSD remount not # Note: Forcing BSDs to do umount/mount due to BSD remount not
# working as expected (suspect bug in the BSD mount command) # working as expected (suspect bug in the BSD mount command)
# Interested contributor could rework this to use mount options on # Interested contributor could rework this to use mount options on
# the CLI instead of relying on fstab # the CLI instead of relying on fstab
# https://github.com/ansible/ansible-modules-core/issues/5591 # https://github.com/ansible/ansible-modules-core/issues/5591
# Note: this does not affect ephemeral state as all options
# are set on the CLI and fstab is expected to be ignored.
rc = 1 rc = 1
else: else:
rc, out, err = module.run_command(cmd) rc, out, err = module.run_command(cmd)
@ -666,6 +713,47 @@ def get_linux_mounts(module, mntinfo_file="/proc/self/mountinfo"):
return mounts return mounts
def _is_same_mount_src(module, src, mountpoint, linux_mounts):
"""Return True if the mounted fs on mountpoint is the same source than src. Return False if mountpoint is not a mountpoint"""
# If the provided mountpoint is not a mountpoint, don't waste time
if (
not ismount(mountpoint) and
not is_bind_mounted(module, linux_mounts, mountpoint)):
return False
# Treat Linux bind mounts
if platform.system() == 'Linux' and linux_mounts is not None:
# For Linux bind mounts only: the mount command does not return
# the actual source for bind mounts, but the device of the source.
# is_bind_mounted() called with the 'src' parameter will return True if
# the mountpoint is a bind mount AND the source FS is the same than 'src'.
# is_bind_mounted() is not reliable on Solaris, NetBSD and OpenBSD.
# But we can rely on 'mount -v' on all other platforms, and Linux non-bind mounts.
if is_bind_mounted(module, linux_mounts, mountpoint, src):
return True
# mount with parameter -v has a close behavior on Linux, *BSD, SunOS
# Requires -v with SunOS. Without -v, source and destination are reversed
# Output format differs from a system to another, but field[0:3] are consistent: [src, 'on', dest]
cmd = '%s -v' % module.get_bin_path('mount', required=True)
rc, out, err = module.run_command(cmd)
mounts = []
if len(out):
mounts = to_native(out).strip().split('\n')
else:
module.fail_json(msg="Unable to retrieve mount info with command '%s'" % cmd)
for mnt in mounts:
fields = mnt.split()
mp_src = fields[0]
mp_dst = fields[2]
if mp_src == src and mp_dst == mountpoint:
return True
return False
def main(): def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=dict( argument_spec=dict(
@ -678,12 +766,13 @@ def main():
passno=dict(type='str', no_log=False, default='0'), passno=dict(type='str', no_log=False, default='0'),
src=dict(type='path'), src=dict(type='path'),
backup=dict(type='bool', default=False), backup=dict(type='bool', default=False),
state=dict(type='str', required=True, choices=['absent', 'absent_from_fstab', 'mounted', 'present', 'unmounted', 'remounted']), state=dict(type='str', required=True, choices=['absent', 'absent_from_fstab', 'mounted', 'present', 'unmounted', 'remounted', 'ephemeral']),
), ),
supports_check_mode=True, supports_check_mode=True,
required_if=( required_if=(
['state', 'mounted', ['src', 'fstype']], ['state', 'mounted', ['src', 'fstype']],
['state', 'present', ['src', 'fstype']], ['state', 'present', ['src', 'fstype']],
['state', 'ephemeral', ['src', 'fstype']]
), ),
) )
@ -754,15 +843,17 @@ def main():
# If fstab file does not exist, we first need to create it. This mainly # If fstab file does not exist, we first need to create it. This mainly
# happens when fstab option is passed to the module. # happens when fstab option is passed to the module.
if not os.path.exists(args['fstab']): # If state is 'ephemeral', we do not need fstab file
if not os.path.exists(os.path.dirname(args['fstab'])): if module.params['state'] != 'ephemeral':
os.makedirs(os.path.dirname(args['fstab'])) if not os.path.exists(args['fstab']):
try: if not os.path.exists(os.path.dirname(args['fstab'])):
open(args['fstab'], 'a').close() os.makedirs(os.path.dirname(args['fstab']))
except PermissionError as e: try:
module.fail_json(msg="Failed to open %s due to permission issue" % args['fstab']) open(args['fstab'], 'a').close()
except Exception as e: except PermissionError as e:
module.fail_json(msg="Failed to open %s due to %s" % (args['fstab'], to_native(e))) module.fail_json(msg="Failed to open %s due to permission issue" % args['fstab'])
except Exception as e:
module.fail_json(msg="Failed to open %s due to %s" % (args['fstab'], to_native(e)))
# absent: # absent:
# Remove from fstab and unmounted. # Remove from fstab and unmounted.
@ -773,6 +864,8 @@ def main():
# mounted: # mounted:
# Add to fstab if not there and make sure it is mounted. If it has # Add to fstab if not there and make sure it is mounted. If it has
# changed in fstab then remount it. # changed in fstab then remount it.
# ephemeral:
# Do not change fstab state, but mount.
state = module.params['state'] state = module.params['state']
name = module.params['path'] name = module.params['path']
@ -806,7 +899,7 @@ def main():
msg="Error unmounting %s: %s" % (name, msg)) msg="Error unmounting %s: %s" % (name, msg))
changed = True changed = True
elif state == 'mounted': elif state == 'mounted' or state == 'ephemeral':
dirs_created = [] dirs_created = []
if not os.path.exists(name) and not module.check_mode: if not os.path.exists(name) and not module.check_mode:
try: try:
@ -834,7 +927,11 @@ def main():
module.fail_json( module.fail_json(
msg="Error making dir %s: %s" % (name, to_native(e))) msg="Error making dir %s: %s" % (name, to_native(e)))
name, backup_lines, changed = _set_mount_save_old(module, args) # ephemeral: completely ignore fstab
if state != 'ephemeral':
name, backup_lines, changed = _set_mount_save_old(module, args)
else:
name, backup_lines, changed = args['name'], [], False
res = 0 res = 0
if ( if (
@ -844,7 +941,26 @@ def main():
if changed and not module.check_mode: if changed and not module.check_mode:
res, msg = remount(module, args) res, msg = remount(module, args)
changed = True changed = True
# When 'state' == 'ephemeral', we don't know what is in fstab, and 'changed' is always False
if state == 'ephemeral':
# If state == 'ephemeral', check if the mountpoint src == module.params['src']
# If it doesn't, fail to prevent unwanted unmount or unwanted mountpoint override
if _is_same_mount_src(module, args['src'], args['name'], linux_mounts):
changed = True
if not module.check_mode:
res, msg = remount(module, args)
else:
module.fail_json(
msg=(
'Ephemeral mount point is already mounted with a different '
'source than the specified one. Failing in order to prevent an '
'unwanted unmount or override operation. Try replacing this command with '
'a "state: unmounted" followed by a "state: ephemeral", or use '
'a different destination path.'))
else: else:
# If not already mounted, mount it
changed = True changed = True
if not module.check_mode: if not module.check_mode:
@ -856,7 +972,8 @@ def main():
# A non-working fstab entry may break the system at the reboot, # A non-working fstab entry may break the system at the reboot,
# so undo all the changes if possible. # so undo all the changes if possible.
try: try:
write_fstab(module, backup_lines, args['fstab']) if state != 'ephemeral':
write_fstab(module, backup_lines, args['fstab'])
except Exception: except Exception:
pass pass

View file

@ -1,3 +1,9 @@
- name: Install dependencies
ansible.builtin.package:
name: e2fsprogs
state: present
when: ansible_system == 'Linux'
- name: Create the mount point - name: Create the mount point
file: file:
state: directory state: directory
@ -406,3 +412,270 @@
- /tmp/myfs1 - /tmp/myfs1
- /tmp/test_fstab - /tmp/test_fstab
when: ansible_system in ('Linux') when: ansible_system in ('Linux')
- name: Block to test ephemeral option
environment:
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
block:
- name: Create empty file A
community.general.filesize:
path: /tmp/myfs_A.img
size: 20M
- name: Create empty file B
community.general.filesize:
path: /tmp/myfs_B.img
size: 20M
- name: Register facts on Linux
ansible.builtin.set_fact:
ephemeral_device_A: /tmp/myfs_A.img
ephemeral_device_B: /tmp/myfs_B.img
ephemeral_fstype: ext3
ephemeral_fstab: /etc/fstab
when: ansible_system == 'Linux'
- name: Register facts on Solaris/SunOS
ansible.builtin.set_fact:
ephemeral_device_A: /dev/lofi/1
ephemeral_device_B: /dev/lofi/2
ephemeral_create_loop_dev_cmd: >
lofiadm -a /tmp/myfs_A.img /dev/lofi/1 &&
lofiadm -a /tmp/myfs_B.img /dev/lofi/2
ephemeral_remove_loop_dev_cmd: >
lofiadm -d /dev/lofi/1 &&
lofiadm -d /dev/lofi/2 || true
ephemeral_fstype: ufs
ephemeral_fstab: /etc/vfstab
when: ansible_system == 'SunOS'
- name: Register facts on FreeBSD
ansible.builtin.set_fact:
ephemeral_device_A: /dev/md1
ephemeral_device_B: /dev/md2
ephemeral_create_loop_dev_cmd: >
mdconfig -a -t vnode -f /tmp/myfs_A.img -u /dev/md1 &&
mdconfig -a -t vnode -f /tmp/myfs_B.img -u /dev/md2
ephemeral_remove_loop_dev_cmd: >
mdconfig -d -u /dev/md1 &&
mdconfig -d -u /dev/md2
ephemeral_fstype: ufs
ephemeral_fstab: /etc/fstab
when: ansible_system == 'FreeBSD'
- name: Register facts on NetBSD
ansible.builtin.set_fact:
ephemeral_device_A: /dev/vnd1
ephemeral_device_B: /dev/vnd2
ephemeral_create_loop_dev_cmd: >
vnconfig /dev/vnd1 /tmp/myfs_A.img &&
vnconfig /dev/vnd2 /tmp/myfs_B.img
ephemeral_remove_loop_dev_cmd: >
vnconfig -u /dev/vnd1 &&
vnconfig -u /dev/vnd2
ephemeral_fstype: ufs
ephemeral_fstab: /etc/fstab
when: ansible_system == 'NetBSD'
- name: Register format fs command on Non-Linux and Non-OpenBSD
ansible.builtin.set_fact:
ephemeral_format_fs_cmd: >
yes | newfs {{ ephemeral_device_A }} &&
yes | newfs {{ ephemeral_device_B }}
when: ansible_system in ('SunOS', 'FreeBSD', 'NetBSD')
- name: Register facts on OpenBSD
ansible.builtin.set_fact:
ephemeral_device_A: /dev/vnd1c
ephemeral_device_B: /dev/vnd2c
ephemeral_create_loop_dev_cmd: >
vnconfig vnd1 /tmp/myfs_A.img &&
vnconfig vnd2 /tmp/myfs_B.img
ephemeral_remove_loop_dev_cmd: >
vnconfig -u vnd1 &&
vnconfig -u vnd2
ephemeral_format_fs_cmd: >
yes | newfs /dev/rvnd1c &&
yes | newfs /dev/rvnd2c
ephemeral_fstype: ffs
ephemeral_fstab: /etc/fstab
when: ansible_system == 'OpenBSD'
##### FORMAT FS ON LINUX
- name: Block to format FS on Linux
block:
- name: Format FS A on Linux
community.general.filesystem:
fstype: ext3
dev: /tmp/myfs_A.img
- name: Format FS B on Linux
community.general.filesystem:
fstype: ext3
dev: /tmp/myfs_B.img
when: ansible_system == 'Linux'
##### FORMAT FS ON SOLARIS AND BSD
- name: Create loop devices on Solaris and BSD
ansible.builtin.shell: "{{ ephemeral_create_loop_dev_cmd }}"
when: ephemeral_create_loop_dev_cmd is defined
- name: Format FS A and B on Solaris and BSD
ansible.builtin.shell: "{{ ephemeral_format_fs_cmd }}"
when: ephemeral_format_fs_cmd is defined
##### TESTS
- name: Create fstab if it does not exist
ansible.builtin.file:
path: "{{ ephemeral_fstab }}"
state: touch
- name: Get checksum of /etc/fstab before mounting anything
stat:
path: '{{ ephemeral_fstab }}'
register: fstab_stat_before_mount
- name: Mount the FS A with ephemeral state
mount:
path: /tmp/myfs
src: '{{ ephemeral_device_A }}'
fstype: '{{ ephemeral_fstype }}'
opts: rw
state: ephemeral
register: ephemeral_mount_info
- name: Put something in the directory so we can do additional checks later on
copy:
content: 'Testing'
dest: /tmp/myfs/test_file
- name: Get checksum of /etc/fstab after an ephemeral mount
stat:
path: '{{ ephemeral_fstab }}'
register: fstab_stat_after_mount
- name: Get mountinfo
shell: mount -v | awk '{print $3}' | grep '^/tmp/myfs$' | wc -l
register: check_mountinfo
changed_when: no
- name: Assert the mount occured and the fstab is unchanged
assert:
that:
- check_mountinfo.stdout|int == 1
- ephemeral_mount_info['changed']
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
- name: Get first mount record
shell: mount -v | grep '/tmp/myfs'
register: ephemeral_mount_record_1
changed_when: no
- name: Try to mount FS A where FS A is already mounted (should trigger remount and changed)
mount:
path: /tmp/myfs
src: '{{ ephemeral_device_A }}'
fstype: '{{ ephemeral_fstype }}'
opts: ro
state: ephemeral
register: ephemeral_mount_info
- name: Get second mount record (should be different than the first)
shell: mount -v | grep '/tmp/myfs'
register: ephemeral_mount_record_2
changed_when: no
- name: Get mountinfo
shell: mount -v | awk '{print $3}' | grep '^/tmp/myfs$' | wc -l
register: check_mountinfo
changed_when: no
- name: Assert the FS A is still mounted, the options changed and the fstab unchanged
assert:
that:
- check_mountinfo.stdout|int == 1
- ephemeral_mount_record_1.stdout != ephemeral_mount_record_2.stdout
- ephemeral_mount_info['changed']
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
- name: Try to mount file B on file A mountpoint (should fail)
mount:
path: /tmp/myfs
src: '{{ ephemeral_device_B }}'
fstype: '{{ ephemeral_fstype }}'
state: ephemeral
register: ephemeral_mount_b_info
ignore_errors: true
- name: Get third mount record (should be the same than the second)
shell: mount -v | grep '/tmp/myfs'
register: ephemeral_mount_record_3
changed_when: no
- name: Get mountinfo
shell: mount -v | awk '{print $3}' | grep '^/tmp/myfs$' | wc -l
register: check_mountinfo
changed_when: no
- name: Try to stat our test file
stat:
path: /tmp/myfs/test_file
register: test_file_stat
- name: Assert that mounting FS B over FS A failed
assert:
that:
- check_mountinfo.stdout|int == 1
- ephemeral_mount_record_2.stdout == ephemeral_mount_record_3.stdout
- test_file_stat['stat']['exists']
- ephemeral_mount_b_info is failed
- name: Unmount FS with state = unmounted
mount:
path: /tmp/myfs
state: unmounted
- name: Get fstab checksum after unmounting an ephemeral mount with state = unmounted
stat:
path: '{{ ephemeral_fstab }}'
register: fstab_stat_after_unmount
- name: Get mountinfo
shell: mount -v | awk '{print $3}' | grep '^/tmp/myfs$' | wc -l
register: check_mountinfo
changed_when: no
- name: Try to stat our test file
stat:
path: /tmp/myfs/test_file
register: test_file_stat
- name: Assert that fstab is unchanged after unmounting an ephemeral mount with state = unmounted
assert:
that:
- check_mountinfo.stdout|int == 0
- not test_file_stat['stat']['exists']
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_unmount['stat']['checksum']
always:
- name: Unmount potential failure relicas
mount:
path: /tmp/myfs
state: unmounted
- name: Remove loop devices on Solaris and BSD
ansible.builtin.shell: "{{ ephemeral_remove_loop_dev_cmd }}"
when: ephemeral_remove_loop_dev_cmd is defined
- name: Remove the test FS
file:
path: '{{ item }}'
state: absent
loop:
- /tmp/myfs_A.img
- /tmp/myfs_B.img
- /tmp/myfs
when: ansible_system in ('Linux', 'SunOS', 'FreeBSD', 'NetBSD', 'OpenBSD')