bigboy-alma-deploy/ansible/roles/phase-3-filesystems/tasks/main.yml

151 lines
No EOL
5.3 KiB
YAML

---
# Phase 3: Filesystem Conversion (four SATA drives only)
# See ../../../tasks/TASK-phase2-3.md for full scope and reasoning.
#
# IMPORTANT: this replaces an earlier version of this role that assumed
# mounting *existing* btrfs volumes. That assumption no longer holds —
# RHEL10's kickstart cannot create btrfs at install time, so all four
# drives currently exist as xfs (per the kickstart's %packages/part
# commands). This role converts them: wipe, mkfs.btrfs, mount, fstab.
#
# Root is explicitly untouched by this role. There is no supported
# in-place xfs-to-btrfs conversion; root's eventual conversion is a
# separate, deferred full-reinstall task (clone/reformat/restore via
# debusb), not part of this playbook.
#
# Idempotent: checks each drive's actual current filesystem before
# acting, so re-running this role doesn't re-wipe an already-converted
# drive.
- name: Define the four SATA drives to convert
ansible.builtin.set_fact:
sata_drives:
- name: backup
byid: "{{ drive_backup_byid }}"
raw_mount: /srv/backup-raw
final_mount: /srv/backup
- name: rag-library
byid: "{{ drive_rag_byid }}"
raw_mount: /srv/rag-raw
final_mount: /srv/rag-library
- name: ai-logs
byid: "{{ drive_ai_logs_byid }}"
raw_mount: /srv/ai-raw
final_mount: /srv/ai-logs
- name: prompt-library
byid: "{{ drive_prompt_byid }}"
raw_mount: /srv/prompt-raw
final_mount: /srv/prompt-library
- name: Check current filesystem type on each drive
ansible.builtin.command: "blkid -o value -s TYPE /dev/disk/by-id/{{ item.byid }}-part1"
register: current_fstype
changed_when: false
failed_when: false
loop: "{{ sata_drives }}"
loop_control:
label: "{{ item.name }}"
- name: Build per-drive conversion status
ansible.builtin.set_fact:
drives_to_convert: >-
{{ sata_drives | zip(current_fstype.results)
| selectattr('1.stdout', 'ne', 'btrfs')
| map(attribute='0') | list }}
- name: Report drives already converted (skipped)
ansible.builtin.debug:
msg: "{{ item.0.name }} already btrfs — skipping conversion, will confirm mount only"
loop: "{{ sata_drives | zip(current_fstype.results) | list }}"
loop_control:
label: "{{ item.0.name }}"
when: item.1.stdout == 'btrfs'
# ---------------------------------------------------------------------------
# Conversion — only runs against drives not already btrfs
# ---------------------------------------------------------------------------
- name: Unmount existing xfs partition before conversion
ansible.posix.mount:
path: "{{ item.raw_mount }}"
state: absent
loop: "{{ drives_to_convert }}"
loop_control:
label: "{{ item.name }}"
- name: Format as btrfs with zstd compression
ansible.builtin.command: >
mkfs.btrfs -f
/dev/disk/by-id/{{ item.byid }}-part1
loop: "{{ drives_to_convert }}"
loop_control:
label: "{{ item.name }}"
- name: Discover the fresh filesystem UUID for each newly-converted drive
ansible.builtin.command: "blkid -o value -s UUID /dev/disk/by-id/{{ item.byid }}-part1"
register: new_uuids
changed_when: false
loop: "{{ drives_to_convert }}"
loop_control:
label: "{{ item.name }}"
- name: Create final mount point directories
ansible.builtin.file:
path: "{{ item.final_mount }}"
state: directory
owner: root
group: root
mode: "0755"
loop: "{{ drives_to_convert }}"
loop_control:
label: "{{ item.name }}"
- name: Remove stale -raw mount point directories (superseded by final_mount)
ansible.builtin.file:
path: "{{ item.raw_mount }}"
state: absent
loop: "{{ drives_to_convert }}"
loop_control:
label: "{{ item.name }}"
- name: Mount each converted drive at its final path with zstd + noatime
ansible.posix.mount:
path: "{{ item.0.final_mount }}"
src: "UUID={{ item.1.stdout }}"
fstype: btrfs
opts: "compress=zstd,noatime"
state: mounted
loop: "{{ drives_to_convert | zip(new_uuids.results) | list }}"
loop_control:
label: "{{ item.0.name }}"
# ---------------------------------------------------------------------------
# Confirm final state for ALL four drives, whether just-converted or
# already-converted on a prior run
# ---------------------------------------------------------------------------
- name: Confirm all four drives are mounted as btrfs at final paths
ansible.builtin.command: "findmnt -n -o FSTYPE {{ item.final_mount }}"
register: final_fstype_check
changed_when: false
loop: "{{ sata_drives }}"
loop_control:
label: "{{ item.name }}"
- name: Fail if any drive isn't btrfs at its final mount point
ansible.builtin.fail:
msg: "{{ item.0.name }} at {{ item.0.final_mount }} is '{{ item.1.stdout }}', expected 'btrfs'"
loop: "{{ sata_drives | zip(final_fstype_check.results) | list }}"
loop_control:
label: "{{ item.0.name }}"
when: item.1.stdout != 'btrfs'
- name: Confirm root is untouched — still xfs
ansible.builtin.command: "findmnt -n -o FSTYPE /"
register: root_fstype_check
changed_when: false
- name: Fail loudly if root is somehow not xfs (should never happen from this role)
ansible.builtin.fail:
msg: "Root filesystem is '{{ root_fstype_check.stdout }}', expected 'xfs' — this role should never have touched root"
when: root_fstype_check.stdout != 'xfs'