# -*- coding: utf-8 -*- # Copyright: Contributors to the Ansible project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import annotations DOCUMENTATION = """ --- module: mount_facts version_added: 2.18 short_description: Retrieve mount information. description: - Retrieve information about mounts from preferred sources and filter the results based on the filesystem type and device. options: devices: description: A list of fnmatch patterns to filter mounts by the special device or remote file system. default: ~ type: list elements: str fstypes: description: A list of fnmatch patterns to filter mounts by the type of the file system. default: ~ type: list elements: str sources: description: - A list of sources used to determine the mounts. Missing file sources (or empty files) are skipped. Repeat sources, including symlinks, are skipped. - The C(mount_points) return value contains the first definition found for a mount point. - Additional mounts to the same mount point are available from C(aggregate_mounts) (if enabled). - By default, mounts are retrieved from all of the standard locations, which have the predefined aliases V(all)/V(static)/V(dynamic). - V(all) contains V(dynamic) and V(static). - V(dynamic) contains V(/etc/mtab), V(/proc/mounts), V(/etc/mnttab), and the value of O(mount_binary) if it is not None. This allows platforms like BSD or AIX, which don't have an equivalent to V(/proc/mounts), to collect the current mounts by default. See the O(mount_binary) option to disable the fall back or configure a different executable. - V(static) contains V(/etc/fstab), V(/etc/vfstab), and V(/etc/filesystems). Note that V(/etc/filesystems) is specific to AIX. The Linux file by this name has a different format/purpose and is ignored. - The value of O(mount_binary) can be configured as a source, which will cause it to always execute. Depending on the other sources configured, this could be inefficient/redundant. For example, if V(/proc/mounts) and V(mount) are listed as O(sources), Linux hosts will retrieve the same mounts twice. default: ~ type: list elements: str mount_binary: description: - The O(mount_binary) is used if O(sources) contain the value "mount", or if O(sources) contains a dynamic source, and none were found (as can be expected on BSD or AIX hosts). - Set to V(null) to stop after no dynamic file source is found instead. type: raw default: mount timeout: description: - This is the maximum number of seconds to wait for each mount to complete. When this is V(null), wait indefinitely. - Configure in conjunction with O(on_timeout) to skip unresponsive mounts. - This timeout also applies to the O(mount_binary) command to list mounts. - If the module is configured to run during the play's fact gathering stage, set a timeout using module_defaults to prevent a hang (see example). type: float on_timeout: description: - The action to take when gathering mount information exceeds O(timeout). type: str default: error choices: - error - warn - ignore include_aggregate_mounts: description: - Whether or not the module should return the C(aggregate_mounts) list in C(ansible_facts). - When this is V(null), a warning will be emitted if multiple mounts for the same mount point are found. default: ~ type: bool extends_documentation_fragment: - action_common_attributes attributes: check_mode: support: full diff_mode: support: none platform: platforms: posix author: - Ansible Core Team - Sloane Hertel (@s-hertel) """ EXAMPLES = """ - name: Get non-local devices mount_facts: devices: "[!/]*" - name: Get FUSE subtype mounts mount_facts: fstypes: - "fuse.*" - name: Get NFS mounts during gather_facts with timeout hosts: all gather_facts: true vars: ansible_facts_modules: - ansible.builtin.mount_facts module_default: ansible.builtin.mount_facts: timeout: 10 fstypes: - nfs - nfs4 - name: Get mounts from a non-default location mount_facts: sources: - /usr/etc/fstab - name: Get mounts from the mount binary mount_facts: sources: - mount mount_binary: /sbin/mount """ RETURN = """ ansible_facts: description: - An ansible_facts dictionary containing a dictionary of C(mount_points) and list of C(aggregate_mounts) when enabled. - Each key in C(mount_points) is a mount point, and the value contains mount information (similar to C(ansible_facts["mounts"])). Each value also contains the key C(ansible_context), with details about the source and line(s) corresponding to the parsed mount point. - When C(aggregate_mounts) are included, the containing dictionaries are the same format as the C(mount_point) values. returned: on success type: dict sample: mount_points: /proc/sys/fs/binfmt_misc: ansible_context: source: /proc/mounts source_data: "systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime,fd=33,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=33850 0 0" block_available: 0 block_size: 4096 block_total: 0 block_used: 0 device: "systemd-1" dump: 0 fstype: "autofs" inode_available: 0 inode_total: 0 inode_used: 0 mount: "/proc/sys/fs/binfmt_misc" options: "rw,relatime,fd=33,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=33850" passno: 0 size_available: 0 size_total: 0 uuid: null aggregate_mounts: - ansible_context: source: /proc/mounts source_data: "systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime,fd=33,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=33850 0 0" block_available: 0 block_size: 4096 block_total: 0 block_used: 0 device: "systemd-1" dump: 0 fstype: "autofs" inode_available: 0 inode_total: 0 inode_used: 0 mount: "/proc/sys/fs/binfmt_misc" options: "rw,relatime,fd=33,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=33850" passno: 0 size_available: 0 size_total: 0 uuid: null - ansible_context: source: /proc/mounts source_data: "binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,nosuid,nodev,noexec,relatime 0 0" block_available: 0 block_size: 4096 block_total: 0 block_used: 0 device: binfmt_misc dump: 0 fstype: binfmt_misc inode_available: 0 inode_total: 0 inode_used: 0 mount: "/proc/sys/fs/binfmt_misc" options: "rw,nosuid,nodev,noexec,relatime" passno: 0 size_available: 0 size_total: 0 uuid: null """ from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.facts import timeout as _timeout from ansible.module_utils.facts.utils import get_mount_size, get_file_content from contextlib import suppress from dataclasses import astuple, dataclass from fnmatch import fnmatch import codecs import datetime import functools import os import re import subprocess import typing as t STATIC_SOURCES = ["/etc/fstab", "/etc/vfstab", "/etc/filesystems"] DYNAMIC_SOURCES = ["/etc/mtab", "/proc/mounts", "/etc/mnttab"] # AIX and BSD don't have a file-based dynamic source, so the module also supports running a mount binary to collect these. # Pattern for Linux, including OpenBSD and NetBSD LINUX_MOUNT_RE = re.compile(r"^(?P\S+) on (?P\S+) type (?P\S+) \((?P.+)\)$") # Pattern for other BSD including FreeBSD, DragonFlyBSD, and MacOS BSD_MOUNT_RE = re.compile(r"^(?P\S+) on (?P\S+) \((?P.+)\)$") # Pattern for AIX, example in https://www.ibm.com/docs/en/aix/7.2?topic=m-mount-command AIX_MOUNT_RE = re.compile(r"^(?P\S*)\s+(?P\S+)\s+(?P\S+)\s+(?P\S+)\s+(?P