--- - name: "โœ… Assert the NFS server is configured" ansible.builtin.assert: that: - storage.nfs.server is defined - storage.nfs.server | length > 0 fail_msg: | svc-storage-nfs-client requires `storage.nfs.server` to be set in the inventory (see group_vars/all/15_storage.yml). A reachable NFS server IP/hostname is mandatory. - name: "๐Ÿ“ฆ Install the NFS client" package_install: id: nfs-client - name: "๐Ÿ”ง Match NFSv4 idmap to the ganesha test server" when: RUNTIME in ['dev', 'act'] block: - name: "๐Ÿ”ง Set idmapd.conf Domain = localdomain" ansible.builtin.lineinfile: path: /etc/idmapd.conf regexp: "^#?\\s*Domain\\s*=" line: "Domain = localdomain" insertafter: "^\\[General\\]" create: true owner: root group: root mode: "0644" - name: "๐Ÿงน Drop stale NFSv4 idmap cache entries" ansible.builtin.command: nfsidmap -c changed_when: false failed_when: false - name: "โœ… Ensure probe mount point exists" ansible.builtin.file: path: "{{ SVC_STORAGE_NFS_CLIENT_PROBE_DIR }}" state: directory owner: root group: root mode: "0700" - name: "๐Ÿ” Probe-mount the NFS export" ansible.posix.mount: path: "{{ SVC_STORAGE_NFS_CLIENT_PROBE_DIR }}" src: "{{ STORAGE_NFS_CLIENT_SRC }}" fstype: "{{ STORAGE_NFS_FSTYPE }}" opts: "{{ STORAGE_NFS_MOUNT_OPTS }},_netdev,noauto" state: ephemeral register: svc_storage_nfs_client_probe failed_when: - svc_storage_nfs_client_probe is failed - name: "๐Ÿ”ง Align the NFS client's directory delegations with the ganesha server" ansible.builtin.include_tasks: directory_delegations.yml when: lookup('nfs_flavor') == 'ganesha' - name: "๐Ÿ” Probe-write a marker to confirm the mount is RW" ansible.builtin.copy: dest: "{{ SVC_STORAGE_NFS_CLIENT_PROBE_DIR }}/.svc-storage-nfs-client-probe.{{ inventory_hostname }}" content: | probed-by={{ inventory_hostname }} probed-at={{ ansible_facts.date_time.iso8601 }} mode: "0644" - name: "๐Ÿ”— Unmount probe mount" ansible.posix.mount: path: "{{ SVC_STORAGE_NFS_CLIENT_PROBE_DIR }}" state: unmounted - name: "๐Ÿ” Detect {{ DIR_VAR_LIB }} pre-mount state" ansible.builtin.script: cmd: "{{ role_path }}/files/shell/premount_state.sh" executable: /bin/bash environment: DIR_VAR_LIB: "{{ DIR_VAR_LIB }}" register: _svc_storage_nfs_client_premount_state changed_when: false - name: "โœ… Assert no pre-existing local data at {{ DIR_VAR_LIB }} (mount would hide it)" ansible.builtin.assert: that: - >- 'STATE=mounted' in _svc_storage_nfs_client_premount_state.stdout or 'STATE=empty' in _svc_storage_nfs_client_premount_state.stdout fail_msg: >- Pre-existing local data found at {{ DIR_VAR_LIB }}; NFS mount-over would silently hide it. Migrate or remove the local tree manually, then re-run the deploy. Probe said: {{ _svc_storage_nfs_client_premount_state.stdout | trim }} - name: "โœ… Ensure infinito state mount point exists" ansible.builtin.file: path: "{{ DIR_VAR_LIB }}" state: directory owner: root group: root mode: "0755" - name: "๐Ÿ” Detect a pending change of the {{ DIR_VAR_LIB }} mount" ansible.posix.mount: path: "{{ DIR_VAR_LIB }}" src: "{{ STORAGE_NFS_CLIENT_SRC }}" fstype: "{{ STORAGE_NFS_FSTYPE }}" opts: "{{ STORAGE_NFS_MOUNT_OPTS }},_netdev" state: mounted check_mode: true register: svc_storage_nfs_client_state_pending - name: "๐Ÿ”Œ Release {{ DIR_BACKUPS }} so the state mount can be remounted" ansible.posix.mount: path: "{{ DIR_BACKUPS }}" state: unmounted when: svc_storage_nfs_client_state_pending is changed - name: "๐Ÿ”— Persistently mount cluster-shared infinito state from NFS" ansible.posix.mount: path: "{{ DIR_VAR_LIB }}" src: "{{ STORAGE_NFS_CLIENT_SRC }}" fstype: "{{ STORAGE_NFS_FSTYPE }}" opts: "{{ STORAGE_NFS_MOUNT_OPTS }},_netdev" state: mounted - name: "โœ… Ensure the node-local backup store exists" ansible.builtin.file: path: "{{ SVC_STORAGE_NFS_CLIENT_BACKUPS_DIR }}" state: directory mode: "0755" - name: "๐Ÿ”— Keep {{ DIR_BACKUPS }} node-local over the shared state" ansible.posix.mount: path: "{{ DIR_BACKUPS }}" src: "{{ SVC_STORAGE_NFS_CLIENT_BACKUPS_DIR }}" fstype: none opts: bind,_netdev state: mounted