Ansible: Detect if a Linux filesystem is mounted r

2019-08-18 02:44发布

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'

2条回答
趁早两清
2楼-- · 2019-08-18 03:20

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"
查看更多
Bombasti
3楼-- · 2019-08-18 03:45

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(',')"
查看更多
登录 后发表回答