Ansible: Detect if a Linux filesystem is mounted read-only

偶尔善良 提交于 2020-01-06 12:41:16

问题


I'm trying to detect if a particular filesystem is mounted read-only or read-write on Linux (Ubuntu 16.04). Using the stat module won't work because it always returns the posix permissions regardless of the actual ability to write into the directory. I'm able to accomplish this with the rather intrusive and cumbersome code below, which attempts to create a dot file. I'd appreciate a cleaner and more elegant alternative, that can also detect if the directory is not a mount point (which would be an error).

- name: Determine whether we have write access to the shared dir
    command: touch /mnt/shared-data/.WriteTest
    register: shared_dir_write_test
    failed_when: "shared_dir_write_test.rc != 0 and 'read-only' not in (shared_dir_write_test.stderr | lower)"
    changed_when: shared_dir_write_test.rc == 0

Ansible advised me to use instead the file module with state=touch, however the code below fails since there doesn't seem to be a way to examine the interim result of file.

  - name: Determine whether we have write access to the shared dir
    file: path=/mnt/shared-data/.WriteTest state=touch
    register: shared_dir_write_test
    failed_when: "shared_dir_write_test.failed and 'read-only' not in (shared_dir_write_test.msg | lower)"

The conditional check 'shared_dir_write_test.failed and 'read-only' not in (shared_dir_write_test.stderr | lower)' failed. The error was: error while evaluating conditional (shared_dir_write_test.failed and 'read-only' not in (shared_dir_write_test.stderr | lower)): 'dict object' has no attribute 'failed'


回答1:


You could gather Ansible facts, there are mount options for each mount:

ansible localhost -m setup -a "filter=ansible_mounts"

sample output:

[root@ansible ansible]# ansible localhost -m setup -a "filter=ansible_mounts"
localhost | SUCCESS => {
    "ansible_facts": {
        "ansible_mounts": [
            {
                "block_available": 3007928, 
                "block_size": 4096, 
                "block_total": 3929600, 
                "block_used": 921672, 
                "device": "/dev/mapper/fedora-root", 
                "fstype": "xfs", 
                "inode_available": 7787042, 
                "inode_total": 7864320, 
                "inode_used": 77278, 
                "mount": "/", 
                "options": "rw,relatime,attr2,inode64,noquota", 
                "size_available": 12320473088, 
                "size_total": 16095641600, 
                "uuid": "5faf23bb-281b-41d9-bd20-f8da6463eba0"
            }, 
            {
                "block_available": 185772, 
                "block_size": 4096, 
                "block_total": 249830, 
                "block_used": 64058, 
                "device": "/dev/sda1", 
                "fstype": "ext4", 
                "inode_available": 65179, 
                "inode_total": 65536, 
                "inode_used": 357, 
                "mount": "/boot", 
                "options": "rw,relatime,data=ordered", 
                "size_available": 760922112, 
                "size_total": 1023303680, 
                "uuid": "866845e7-6c62-41c9-bbd2-87b463326601"
            }
        ]
    }, 
    "changed": false
}
[root@ansible ansible]# ansible localhost -m setup -a "filter=ansible_mounts"



回答2:


The information can be obtained from Ansible facts. Ansible code that accomplishes this:

- name: Determine shared-dir mount point
command: "/usr/bin/env stat -c '%m' {{ shared_dir_real_path }}"
register: shared_dir_mount_point
changed_when: False

- name: Determine the mount point's filesystem type and mount options
set_fact:
    "shared_dir_mount_{{ item }}": "{{ ansible_mounts | selectattr('mount', 'equalto', shared_dir_mount_point.stdout) | map(attribute = item) | join(',') }}"
with_items:
    - fstype
    - options

- name: Determine the access to the shared-data directory
set_fact:
    shared_dir_access_flags: "{{ ['ro', 'rw']  | intersect( shared_dir_mount_options.split(',') )}}"

- name: Verify Access mode sanity
assert:
    that: shared_dir_access_flags | length == 1

Then to determine whether the mount is R/W or R/O I use:

when: "'rw' in shared_dir_access_flags"

or

when: "'ro' in shared_dir_access_flags"

Another, more terse but perhaps less clean approach that I used previously, was to obtain the information from /proc/self/mountinfo. A little more platform-specific than I hoped, but it only depends on documented intrefaces.

- name: Get Shared dir mount options
shell: "grep -F `stat -c '%m' {{ shared_dir_path }}` /proc/self/mountinfo | cut -d' ' -f 6"
register: shared_dir_mount_options
changed_when: False

Then the expressions to determine whether the mount is R/W or R/O I would become a bit more cumbersome:

when: "'rw' in shared_dir_mount_options.stdout.split(',')"

or

when: "'ro' in shared_dir_mount_options.stdout.split(',')"


来源:https://stackoverflow.com/questions/49609588/ansible-detect-if-a-linux-filesystem-is-mounted-read-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!