Назад | Перейти на главную страницу

Установите параметр монтирования для данной точки монтирования с помощью ansible

Есть ли элегантный способ установить параметры монтирования для данной точки монтирования по UUID с помощью ansible?

Я хочу сделать такую ​​запись в fstab:

UUID=d5e3a2e2-a113-4a27-b8d7-801dbf4c6134 / ext4 errors=remount-ro,noatime,user_xattr,acl 0 1

В общем, я хочу сказать ansible: «Установите эти параметры для устройства на /». но src параметр модуль крепления требуется для текущего состояния, и я хочу использовать UUID в качестве источника.

Мое текущее решение опубликовано в виде ответа ниже, но оно будет перебирать все существующие монтирования и проверять, является ли путь / или нет и поэтому производит много skipping выходы.


Что я сейчас делаю:

- name: "mount options for /"
  mount:
    path: "/"
    src: "UUID={{ item.uuid }}"
    fstype: "ext4"
    opts: "errors=remount-ro,noatime,user_xattr,acl"
    state: "present"
  with_items:
    - "{{ ansible_mounts }}"
  when: "item.mount == '/'"

Это делает то, что я собираюсь сделать, но проверяет все точки монтирования хоста и поэтому производит много skipping выходы:

TASK [node : mount options for /] ************************************************************************************************************************
ok: [node001] => (item={u'uuid': u'N/A', u'size_total': 291684016128, u'mount': u'/', u'size_available': 215996313600, u'fstype': u'ext4', u'device': u'/dev/sda2', u'options': u'rw,noatime,nodiratime,errors=remount-ro,user_xattr,acl'})
skipping: [node001] => (item={u'uuid': u'N/A', u'size_total': 527433728, u'mount': u'/boot/efi', u'size_available': 523894784, u'fstype': u'vfat', u'device': u'/dev/sda1', u'options': u'rw'}) 
skipping: [node001] => (item={u'uuid': u'N/A', u'size_total': 10908480831488, u'mount': u'/scr', u'size_available': 2431928762368, u'fstype': u'nfs4', u'device': u'192.168.31.3:/scratch', u'options': u'rw,vers=4,sec=sys,addr=192.168.31.3,clientaddr=192.168.31.41,_netdev'}) 
skipping: [node001] => (item={u'uuid': u'N/A', u'size_total': 10908480831488, u'mount': u'/homes', u'size_available': 2431928762368, u'fstype': u'nfs4', u'device': u'192.168.31.3:/u', u'options': u'rw,vers=4,sec=sys,addr=192.168.31.3,clientaddr=192.168.31.41,_netdev'}) 
skipping: [node001] => (item={u'uuid': u'N/A', u'size_total': 48378511622144, u'mount': u'/mnt/bigdata3', u'size_available': 5786707165184, u'fstype': u'nfs', u'device': u'192.168.31.1:/DATA3/bigdata3', u'options': u'ro,noatime,vers=3,addr=192.168.31.1,_netdev'}) 
skipping: [node001] => (item={u'uuid': u'N/A', u'size_total': 48378511622144, u'mount': u'/mnt/bigdata4', u'size_available': 18173101342720, u'fstype': u'nfs', u'device': u'192.168.31.1:/DATA4/bigdata4', u'options': u'ro,noatime,vers=3,addr=192.168.31.1,_netdev'}) 
skipping: [node001] => (item={u'uuid': u'N/A', u'size_total': 38764865912832, u'mount': u'/mnt/groupdata2', u'size_available': 7847016398848, u'fstype': u'nfs', u'device': u'192.168.31.1:/DATA2/groupdata2', u'options': u'rw,noatime,vers=3,addr=192.168.31.1,_netdev'}) 
skipping: [node001] => (item={u'uuid': u'N/A', u'size_total': 14776486854656, u'mount': u'/mnt/bigdata1', u'size_available': 3801819906048, u'fstype': u'nfs', u'device': u'192.168.31.1:/DATA1/bigdata1', u'options': u'ro,noatime,vers=3,addr=192.168.31.1,_netdev'}) 
skipping: [node001] => (item={u'uuid': u'N/A', u'size_total': 23931377418240, u'mount': u'/mnt/groupdata', u'size_available': 3801819906048, u'fstype': u'nfs', u'device': u'192.168.31.1:/DATA1/groupdata', u'options': u'rw,noatime,vers=3,addr=192.168.31.1,_netdev'}) 
skipping: [node001] => (item={u'uuid': u'N/A', u'size_total': 12593077944320, u'mount': u'/mnt/transfer', u'size_available': 8260916609024, u'fstype': u'nfs', u'device': u'nas:/DATA5/transfer', u'options': u'ro,noatime,vers=4.1,acl,addr=192.168.31.2,clientaddr=192.168.31.41,_netdev'}) 
skipping: [node001] => (item={u'uuid': u'N/A', u'size_total': 40888277401600, u'mount': u'/mnt/transfer2', u'size_available': 25068068405248, u'fstype': u'nfs', u'device': u'nas:/DATA5/transfer2', u'options': u'ro,noatime,vers=4.1,acl,addr=192.168.31.2,clientaddr=192.168.31.41,_netdev'})

На мой взгляд, это некрасиво, и мне интересно, есть ли лучший способ сделать это.


РЕДАКТИРОВАТЬ

Я нашел фильтр json_query который должен уметь делать то, что я хочу. Однако я не мог заставить его работать.

На их пример веб-сайта Я пробовал эту структуру данных (скопировано из ansible_facts):

{
    "ansible_mounts": [
        {
            "device": "/dev/sda2", 
            "fstype": "ext4", 
            "mount": "/", 
            "options": "rw,noatime,nodiratime,errors=remount-ro,user_xattr,acl", 
            "size_available": 215995777024, 
            "size_total": 291684016128, 
            "uuid": "N/A"
        }, 
        {
            "device": "/dev/sda1", 
            "fstype": "vfat", 
            "mount": "/boot/efi", 
            "options": "rw", 
            "size_available": 523894784, 
            "size_total": 527433728, 
            "uuid": "N/A"
        }
    ]
}

с этим запросом:

ansible_mounts[?mount == `/`]

и получил желаемый результат:

[
  {
    "device": "/dev/sda2",
    "fstype": "ext4",
    "mount": "/",
    "options": "rw,noatime,nodiratime,errors=remount-ro,user_xattr,acl",
    "size_available": 215995777024,
    "size_total": 291684016128,
    "uuid": "N/A"
  }
]

Итак, я попробовал это в playbook:

    src: "UUID={{ item.uuid }}"
  with_items:
    - "{{ ansible_mounts|json_query('ansible_mounts[?mount == `/`]') }}"

но это не удается с этим сообщением:

The error was: 'ansible.vars.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'uuid'

Мне удалось получить то, что я хочу, с json_query фильтр:

- name: "mount options for /"
  mount:
    path: "/"
    src: "UUID={{ ansible_mounts | json_query('[?mount == `/`] | [0].uuid') }}"
    fstype: "ext4"
    opts: "errors=remount-ro,noatime,user_xattr,acl"
    state: "present"

Вам нужно будет установить пакет python-jmespath.

- name: add nodev mount option for all LVM mounts exept root part
  mount:
    name: '{{ item.mount }}'
    src: '{{ item.device }}' # UUID not needed when LVM
    state: mounted
    fstype: '{{ item.fstype }}'
    opts: "{{ item.options |regex_replace(',nodev','') }},nodev" # Fix duplicate
  when: item.options.find("nodev") != -1 and item.device.find("mapper") != -1 and not item.mount in [ "/" ]
  with_items: '{{ ansible_mounts }}'

- name: add nodev mount option for all non-LVM mounts exept root part
  mount:
    name: '{{ item.mount }}'
    src: 'UUID={{ item.uuid }}'
    state: mounted
    fstype: '{{ item.fstype }}'
    opts: "{{ item.options |regex_replace(',nodev','') }},nodev" # Fix duplicate
  when: item.options.find("nodev") != -1 and item.device.find("mapper") == -1 and not item.mount in [ "/" ]
  with_items: '{{ ansible_mounts }}'

Предполагается вывод Ansible. Вы даете команду Ansible перебрать монтировки, перечисленные в ansible_mounts. Единственный вариант, который я вижу, - это grep UUID корневого устройства и зарегистрируйте вывод. Что-то вроде этого должно помочь:

- name: Get root device UUID.
  shell: cat /etc/fstab | grep "/\s" | cut -f1 | cut -d = -f2
  register: root_uuid

- debug:
    msg: "{{ root_uuid.stdout }}"

- name: "mount options for /"
  mount:
    path: "/"
    src: "{{ root_uuid }}"
    fstype: "ext4"
    opts: "errors=remount-ro,noatime,user_xattr,acl"
    state: "present"

Но эта попытка, вероятно, нестабильна, и я бы не рекомендовал делать это ради менее шумного вывода Ansible.