prole/infrastructure/roles/iscsi/tasks/iscsi_mount.yml
chrisfu 2244d6acd6 Refactor iSCSI Synology mounts to /synology/d00x
- Rename host mount namespace from /prole/d00x to /synology/d00x

- Make LUN ownership explicit per host in inventory (myrddin=d001; merlin=d002,d004; pi=d003)

- Add safe migration cleanup for legacy /prole/d00x mounts and stale /etc/fstab entries

- Update k3s/ArgoCD/OpenTofu manifests and PV node affinities to match new mount paths

- Improve iSCSI role check-mode behavior and add quiesce/detach flow in ansible.sh
2026-03-21 10:43:06 -07:00

339 lines
10 KiB
YAML

---
- name: Ensure mountpoint exists
ansible.builtin.file:
path: "{{ m.path }}"
state: directory
mode: "0755"
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Reset computed mount source
ansible.builtin.set_fact:
_iscsi_mount_src: ""
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Decide whether a block device is required for this mount
ansible.builtin.set_fact:
_iscsi_need_blockdev: >-
{{ (m.mkfs_once | default(false) | bool)
or (m.mkfs_if_missing | default(false) | bool)
or (m.device is defined and (m.device | string | length) > 0)
or (m.src is not defined) or ((m.src | default('') | string | length) == 0) }}
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Parse iSCSI portal (host/port)
ansible.builtin.set_fact:
_iscsi_portal_host: "{{ (iscsi_portal | string).split(':')[0] }}"
_iscsi_portal_port: "{{ ((iscsi_portal | string).split(':') | length > 1) | ternary((iscsi_portal | string).split(':')[1], '3260') }}"
when:
- _iscsi_need_blockdev | default(false) | bool
- iscsi_portal is defined
- (iscsi_portal | string | length) > 0
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Use explicitly provided block device (if any)
ansible.builtin.set_fact:
_iscsi_blockdev: "{{ m.device }}"
when:
- _iscsi_need_blockdev | default(false) | bool
- m.device is defined
- (m.device | string | length) > 0
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Compute iSCSI by-path pattern
ansible.builtin.set_fact:
_iscsi_by_path_pattern: >-
ip-{{ _iscsi_portal_host }}:{{ _iscsi_portal_port }}-iscsi-{{ iscsi_target.iqn }}-lun-{{ (m.lun is defined) | ternary((m.lun | string), '*') }}
when:
- _iscsi_need_blockdev | default(false) | bool
- (_iscsi_blockdev is not defined) or ((_iscsi_blockdev | string | length) == 0)
- iscsi_target is defined
- iscsi_target.iqn is defined
- _iscsi_portal_host is defined
- (_iscsi_portal_host | string | length) > 0
- _iscsi_portal_port is defined
- (_iscsi_portal_port | string | length) > 0
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Wait for iSCSI by-path device to appear
ansible.builtin.find:
paths:
- /dev/disk/by-path
patterns:
- "{{ _iscsi_by_path_pattern }}"
file_type: any
register: _iscsi_by_path_find
until: (_iscsi_by_path_find.matched | default(0) | int) > 0
retries: "{{ ((m.device_timeout | default(60)) | int // 5) + 1 }}"
delay: 5
when:
- _iscsi_need_blockdev | default(false) | bool
- (_iscsi_blockdev is not defined) or ((_iscsi_blockdev | string | length) == 0)
- _iscsi_by_path_pattern is defined
- (_iscsi_by_path_pattern | string | length) > 0
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Select iSCSI block device from by-path matches
ansible.builtin.set_fact:
_iscsi_blockdev: "{{ (_iscsi_by_path_find.files | map(attribute='path') | list | sort | first) }}"
when:
- _iscsi_need_blockdev | default(false) | bool
- (_iscsi_blockdev is not defined) or ((_iscsi_blockdev | string | length) == 0)
- _iscsi_by_path_find is defined
- (_iscsi_by_path_find.matched | default(0) | int) > 0
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Read existing filesystem type (if any)
ansible.builtin.command: "blkid -o value -s TYPE {{ _iscsi_blockdev }}"
register: _iscsi_blkid_type
changed_when: false
failed_when: false
check_mode: no
when:
- _iscsi_need_blockdev | default(false) | bool
- _iscsi_blockdev is defined
- (_iscsi_blockdev | string | length) > 0
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Ensure marker directory exists (mkfs_once)
ansible.builtin.file:
path: /var/lib/prole/iscsi
state: directory
owner: root
group: root
mode: "0755"
when: m.mkfs_once | default(false) | bool
tags:
- iscsi
- iscsi_mkfs
- iscsi_storage
- name: Compute mkfs marker path (mkfs_once)
ansible.builtin.set_fact:
_iscsi_mkfs_marker: >-
/var/lib/prole/iscsi/mkfs-
{{ (((iscsi_target.iqn | default('unknown-iqn')) ~ '-' ~ (m.path | default('unknown-path')))
| regex_replace('[^A-Za-z0-9_.-]', '_')) }}
.done
when: m.mkfs_once | default(false) | bool
tags:
- iscsi
- iscsi_mkfs
- iscsi_storage
- name: Check mkfs marker presence (mkfs_once)
ansible.builtin.stat:
path: "{{ _iscsi_mkfs_marker }}"
register: _iscsi_mkfs_marker_stat
when: m.mkfs_once | default(false) | bool
tags:
- iscsi
- iscsi_mkfs
- iscsi_storage
- name: Fail if mountpoint is already mounted but mkfs_once requested
ansible.builtin.command: "findmnt -n {{ m.path }}"
register: _iscsi_findmnt_before_mkfs
changed_when: false
failed_when: false
when:
- m.mkfs_once | default(false) | bool
- _iscsi_mkfs_marker_stat.stat.exists is not defined or not _iscsi_mkfs_marker_stat.stat.exists
tags:
- iscsi
- iscsi_mkfs
- iscsi_storage
- name: Refuse to mkfs when mountpoint is mounted
ansible.builtin.fail:
msg: "Refusing to mkfs for {{ m.path }} because it is already mounted ({{ _iscsi_findmnt_before_mkfs.stdout | default('') }})."
when:
- m.mkfs_once | default(false) | bool
- _iscsi_mkfs_marker_stat.stat.exists is not defined or not _iscsi_mkfs_marker_stat.stat.exists
- _iscsi_findmnt_before_mkfs.rc == 0
tags:
- iscsi
- iscsi_mkfs
- iscsi_storage
- name: Require iSCSI block device path for mkfs_once
ansible.builtin.assert:
that:
- _iscsi_blockdev is defined
- (_iscsi_blockdev | string | length) > 0
fail_msg: "mkfs_once requested for {{ m.path }} but no block device was computed (set m.device or ensure iscsi_target+iscsi_portal are available)."
when:
- m.mkfs_once | default(false) | bool
- _iscsi_mkfs_marker_stat.stat.exists is not defined or not _iscsi_mkfs_marker_stat.stat.exists
tags:
- iscsi
- iscsi_mkfs
- iscsi_storage
- name: Re-initialize filesystem (mkfs_once)
ansible.builtin.command: >-
{{ ((m.fstype | default('ext4')) == 'xfs')
| ternary(
'mkfs.xfs -f ' ~ _iscsi_blockdev,
(((m.fstype | default('ext4')) == 'ext4')
| ternary(
'mkfs.ext4 -F ' ~ _iscsi_blockdev,
'mkfs -t ' ~ (m.fstype | default('ext4')) ~ ' ' ~ _iscsi_blockdev
)
)
) }}
changed_when: true
when:
- m.mkfs_once | default(false) | bool
- _iscsi_mkfs_marker_stat.stat.exists is not defined or not _iscsi_mkfs_marker_stat.stat.exists
tags:
- iscsi
- iscsi_mkfs
- iscsi_storage
- name: Create filesystem when missing (mkfs_if_missing)
ansible.builtin.command: >-
{{ ((m.fstype | default('ext4')) == 'xfs')
| ternary(
'mkfs.xfs -f ' ~ _iscsi_blockdev,
(((m.fstype | default('ext4')) == 'ext4')
| ternary(
'mkfs.ext4 -F ' ~ _iscsi_blockdev,
'mkfs -t ' ~ (m.fstype | default('ext4')) ~ ' ' ~ _iscsi_blockdev
)
)
) }}
changed_when: true
when:
- m.mkfs_if_missing | default(false) | bool
- _iscsi_blockdev is defined
- (_iscsi_blockdev | string | length) > 0
- _iscsi_blkid_type is not defined or (_iscsi_blkid_type.stdout | default('') | trim) == ''
tags:
- iscsi
- iscsi_mkfs
- iscsi_storage
- name: Refuse to mount when existing filesystem type does not match
ansible.builtin.fail:
msg: >-
Existing filesystem type on {{ _iscsi_blockdev }} is
'{{ _iscsi_blkid_type.stdout | default('') | trim }}' but mount {{ m.path }}
requests fstype='{{ m.fstype | default('ext4') }}'.
Wipe the device signature (e.g. wipefs) or set mkfs_once=true if you intend
to reformat this LUN.
when:
- _iscsi_blkid_type is defined
- (_iscsi_blkid_type.stdout | default('') | trim) != ''
- (_iscsi_blkid_type.stdout | trim) != (m.fstype | default('ext4'))
- not (m.mkfs_once | default(false) | bool)
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Write mkfs marker (mkfs_once)
ansible.builtin.file:
path: "{{ _iscsi_mkfs_marker }}"
state: touch
owner: root
group: root
mode: "0644"
when:
- m.mkfs_once | default(false) | bool
- _iscsi_mkfs_marker_stat.stat.exists is not defined or not _iscsi_mkfs_marker_stat.stat.exists
tags:
- iscsi
- iscsi_mkfs
- iscsi_storage
- name: Resolve mount source
ansible.builtin.set_fact:
_iscsi_mount_src: "{{ m.src }}"
when:
- m.src is defined
- (m.src | string | length) > 0
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Resolve mount source UUID from block device
ansible.builtin.command: "blkid -o value -s UUID {{ _iscsi_blockdev }}"
register: _iscsi_blkid_uuid
changed_when: false
check_mode: no
when:
- (_iscsi_mount_src | default('') | string | length) == 0
- _iscsi_blockdev is defined
- (_iscsi_blockdev | string | length) > 0
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Require resolved UUID for mounting
ansible.builtin.assert:
that:
- _iscsi_blkid_uuid is defined
- (_iscsi_blkid_uuid.stdout | default('') | trim) != ''
fail_msg: "Unable to resolve a filesystem UUID for {{ m.path }} from {{ _iscsi_blockdev }}."
when:
- (_iscsi_mount_src | default('') | string | length) == 0
- not (ansible_check_mode and ((m.mkfs_once | default(false) | bool) or (m.mkfs_if_missing | default(false) | bool)))
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Set mount source to UUID
ansible.builtin.set_fact:
_iscsi_mount_src: "UUID={{ _iscsi_blkid_uuid.stdout | trim }}"
when:
- (_iscsi_mount_src | default('') | string | length) == 0
- _iscsi_blkid_uuid is defined
- (_iscsi_blkid_uuid.stdout | default('') | trim) != ''
tags:
- iscsi
- iscsi_mount
- iscsi_storage
- name: Mount {{ m.path }}
ansible.builtin.mount:
path: "{{ m.path }}"
src: "{{ _iscsi_mount_src }}"
fstype: "{{ m.fstype | default('ext4') }}"
opts: "{{ m.opts | default('_netdev,noatime') }}"
state: mounted
when: (_iscsi_mount_src | default('') | string | trim | length) > 0
tags:
- iscsi
- iscsi_mount
- iscsi_storage