Ansible: Определить, монтирована ли файловая система Linux только для чтения

Я пытаюсь определить, смонтирована ли конкретная файловая система только для чтения или для чтения и записи в Linux (Ubuntu 16.04). Использование модуля stat не будет работать, потому что он всегда возвращает разрешения posix независимо от реальной возможности записи в каталог. Я могу сделать это с помощью довольно навязчивого и громоздкого кода ниже, который пытается создать точечный файл. Я был бы признателен за более чистую и элегантную альтернативу, которая также может определить, не является ли каталог точкой монтирования (что было бы ошибкой).

- 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 посоветовал мне использовать вместо этого файловый модуль с state = touch, однако приведенный ниже код завершился ошибкой, поскольку, похоже, нет способа проверить промежуточный результат файла.

  - 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)"

Не удалось выполнить условную проверку "shared_dir_write_test.failed и" только для чтения "(shared_dir_write_test.stderr | lower)". Ошибка была: ошибка при оценке условия (shared_dir_write_test.failed и "только для чтения" не включено (shared_dir_write_test.stderr | lower)): "объект dict" не имеет атрибута "fail"

2 ответа

Решение

Информация может быть получена из Ansible фактов. Ansible код, который выполняет это:

- 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

Затем, чтобы определить, является ли монтирование R/W или R/O I, используйте:

when: "'rw' in shared_dir_access_flags"

или же

when: "'ro' in shared_dir_access_flags"

Другой, более краткий, но, возможно, менее чистый подход, который я использовал ранее, заключался в получении информации из / proc / self / mountinfo. Чуть более специфичный для платформы, чем я ожидал, но это зависит только от документированных интерфейсов.

- 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

Тогда выражения, определяющие, является ли монтирование R/W или R/O I, станут немного более громоздкими:

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

или же

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

Вы можете собрать факты Ansible, для каждого монтирования есть опции монтирования:

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

образец вывода:

[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"
Другие вопросы по тегам