151 lines
No EOL
5.3 KiB
YAML
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-logs-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 }}1"
|
|
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: unmounted
|
|
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 }}1
|
|
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 }}1"
|
|
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' |