feat: add system-upgrade role for kernel/nvidia migration
Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
# Role-local defaults for system-upgrade.
|
||||
# Project-wide kernel/NVIDIA package lists live in ansible/vars/main.yml so
|
||||
# they can be reused by future roles (e.g. hyprland) without re-declaration.
|
||||
# Override here only if you need a different value when running this role
|
||||
# stand-alone (ansible-playbook ... -e @custom-vars.yml).
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
# Handlers for system-upgrade role.
|
||||
# Currently the role uses explicit gated tasks (when: ... .changed) rather
|
||||
# than notify/handler chains, because every kernel/driver change must trigger
|
||||
# both mkinitcpio AND grub-mkconfig in a strict order. If you later split
|
||||
# tasks across files, prefer the standard notify pattern here.
|
||||
@@ -0,0 +1,289 @@
|
||||
---
|
||||
# system-upgrade role — full system upgrade + kernel/NVIDIA preparation
|
||||
# for the upcoming Hyprland/Wayland migration. Idempotent: a clean re-run
|
||||
# on an already-upgraded box performs no destructive action.
|
||||
#
|
||||
# Sections:
|
||||
# 1. Pre-flight checks (OS guard, free space, summary)
|
||||
# 2. Full system upgrade (pacman -Syu) — added in Step 2
|
||||
# 3. NVIDIA branch migration + kernel install — added in Step 3
|
||||
# 4. Initramfs + GRUB refresh + final reboot notice — added in Step 4
|
||||
#
|
||||
# Run as:
|
||||
# ansible-playbook ansible/workstation.yml --check --tags system-upgrade
|
||||
# ansible-playbook ansible/workstation.yml --tags system-upgrade
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1. Pre-flight checks
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
- name: Pre-flight - announce role start
|
||||
debug:
|
||||
msg:
|
||||
- "system-upgrade: preparing baseline for Hyprland/Wayland migration"
|
||||
- "kernels to ensure installed: {{ kernel_packages | join(', ') }}"
|
||||
- "nvidia modules to ensure installed: {{ nvidia_kernel_modules | join(', ') }}"
|
||||
- "nvidia legacy packages to remove: {{ nvidia_packages_to_remove | join(', ') }}"
|
||||
tags: [system-upgrade, preflight]
|
||||
|
||||
- name: Pre-flight - capture free space on / (GiB)
|
||||
shell: |
|
||||
set -o pipefail
|
||||
df --output=avail -BG / | tail -1 | tr -dc '0-9'
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: root_free_gb
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
tags: [system-upgrade, preflight]
|
||||
|
||||
- name: Pre-flight - fail if free space on / < {{ min_free_root_gb }} GiB
|
||||
fail:
|
||||
msg: >-
|
||||
Only {{ root_free_gb.stdout }} GiB free on /, need at least
|
||||
{{ min_free_root_gb }} GiB before running pacman -Syu and installing
|
||||
a second kernel. Run `paccache -rk2` and clear ~/.cache before retrying.
|
||||
when: (root_free_gb.stdout | int) < (min_free_root_gb | int)
|
||||
tags: [system-upgrade, preflight]
|
||||
|
||||
- name: Pre-flight - record currently running kernel
|
||||
command: uname -r
|
||||
register: running_kernel
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
tags: [system-upgrade, preflight]
|
||||
|
||||
- name: Pre-flight - summary
|
||||
debug:
|
||||
msg:
|
||||
- "running kernel: {{ running_kernel.stdout }}"
|
||||
- "free space on /: {{ root_free_gb.stdout }} GiB (min required {{ min_free_root_gb }})"
|
||||
- "OS guard: os_type == '{{ os_type }}' (must be 'archlinux')"
|
||||
tags: [system-upgrade, preflight]
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2. Full system upgrade (pacman -Syu)
|
||||
# ---------------------------------------------------------------------------
|
||||
# Bring the box to current Manjaro Stable before touching kernels/drivers.
|
||||
# `community.general.pacman` runs the equivalent of `pacman -Syu`:
|
||||
# - update_cache: yes -> pacman -Sy
|
||||
# - upgrade: yes -> pacman -Su
|
||||
# It reports changed=True iff packages were actually upgraded, which we use
|
||||
# below to gate the kernel/driver migration so an already-current box is a
|
||||
# true no-op.
|
||||
|
||||
- name: Upgrade - full system upgrade (pacman -Syu)
|
||||
community.general.pacman:
|
||||
update_cache: yes
|
||||
upgrade: yes
|
||||
register: pacman_syu
|
||||
tags: [system-upgrade, upgrade, pacman]
|
||||
|
||||
- name: Upgrade - summary
|
||||
debug:
|
||||
msg:
|
||||
- "pacman -Syu changed: {{ pacman_syu.changed | default(false) }}"
|
||||
- "packages touched: {{ (pacman_syu.packages | default([])) | length }}"
|
||||
- "first 10 packages: {{ (pacman_syu.packages | default([]))[:10] | join(', ') }}"
|
||||
tags: [system-upgrade, upgrade]
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 3. NVIDIA branch migration + kernel install
|
||||
# ---------------------------------------------------------------------------
|
||||
# Goal: end up with BOTH linux618 (LTS/Fallback) and linux70 (stable) installed, each
|
||||
# with matching *-nvidia kernel modules on the 580xx branch.
|
||||
# in the same transaction so the GPU never has a "no driver" window of more
|
||||
# than ~1 second on a local pacman cache.
|
||||
#
|
||||
# Safety guarantees:
|
||||
# - linux618 (currently running kernel) is in `kernel_packages`, never in
|
||||
# `nvidia_packages_to_remove` — asserted below.
|
||||
# - The remove step uses the list of 575xx packages that are *actually*
|
||||
# installed, so re-running the role after a successful migration is a
|
||||
# true no-op (LEGACY is empty -> pacman -Rdd is skipped).
|
||||
# - The install step uses --needed so already-current packages are not
|
||||
# touched a second time.
|
||||
|
||||
- name: Migration - safety assertion (Fallback kernel must NOT be removed)
|
||||
assert:
|
||||
that:
|
||||
- "'linux618' in kernel_packages"
|
||||
- "'linux618' not in nvidia_packages_to_remove"
|
||||
- "kernel_packages | length > 0"
|
||||
- "nvidia_kernel_modules | length > 0"
|
||||
fail_msg: >-
|
||||
Refusing to migrate: configuration would remove the running fallback kernel.
|
||||
Check ansible/vars/main.yml: 'linux618' must stay in kernel_packages.
|
||||
tags: [system-upgrade, migration]
|
||||
|
||||
- name: Migration - detect which legacy 575xx packages are currently installed
|
||||
shell: |
|
||||
set -o pipefail
|
||||
pacman -Qq {{ nvidia_packages_to_remove | join(' ') }} 2>/dev/null || true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: nvidia_legacy_installed
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
tags: [system-upgrade, migration]
|
||||
|
||||
- name: Migration - check-mode dry-run (pacman -S --print)
|
||||
shell: |
|
||||
set -o pipefail
|
||||
pacman -S --needed --print {{ (kernel_packages + nvidia_kernel_modules + nvidia_userspace_packages) | join(' ') }} 2>&1 | head -40 || true
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: nvidia_dryrun
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
when: ansible_check_mode
|
||||
tags: [system-upgrade, migration]
|
||||
|
||||
- name: Migration - check-mode preview output
|
||||
debug:
|
||||
msg:
|
||||
- "legacy 575xx packages currently installed:"
|
||||
- "{{ nvidia_legacy_installed.stdout_lines | default([]) }}"
|
||||
- "pacman would install (first 40 lines of --print):"
|
||||
- "{{ nvidia_dryrun.stdout_lines | default([]) }}"
|
||||
when: ansible_check_mode
|
||||
tags: [system-upgrade, migration]
|
||||
|
||||
- name: Migration - swap NVIDIA branch (575xx -> 580xx) and install kernels
|
||||
shell: |
|
||||
set -eo pipefail
|
||||
LEGACY="{{ nvidia_legacy_installed.stdout_lines | default([]) | join(' ') }}"
|
||||
if [ -n "$LEGACY" ]; then
|
||||
echo ">>> dropping legacy 575xx packages: $LEGACY"
|
||||
pacman -Rdd --noconfirm $LEGACY
|
||||
else
|
||||
echo ">>> no legacy 575xx packages present — skipping drop step"
|
||||
fi
|
||||
echo ">>> ensuring target packages are present (kernels + nvidia modules + userspace)"
|
||||
pacman -S --needed --noconfirm {{ (kernel_packages + nvidia_kernel_modules + nvidia_userspace_packages) | join(' ') }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: nvidia_migration
|
||||
become: yes
|
||||
when: not ansible_check_mode
|
||||
# Detect REAL pacman activity (not our own echo lines): pacman prints
|
||||
# progress lines like "(3/4) installing linux70" / "(1/4) upgrading foo" /
|
||||
# "(2/4) removing nvidia-575xx-utils". Match exactly that format so re-runs
|
||||
# on an already-current box report changed=false.
|
||||
changed_when: >-
|
||||
(nvidia_migration.stdout | default('')) is search('\([0-9]+/[0-9]+\)\s+(installing|upgrading|removing)\s')
|
||||
tags: [system-upgrade, migration]
|
||||
|
||||
- name: Migration - verify all target packages are present after install
|
||||
command: pacman -Q {{ item }}
|
||||
loop: "{{ kernel_packages + nvidia_kernel_modules + nvidia_userspace_packages }}"
|
||||
register: pkg_verify
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
failed_when: (pkg_verify.rc | default(0)) != 0 and not ansible_check_mode
|
||||
tags: [system-upgrade, migration]
|
||||
|
||||
- name: Migration - recovery notice
|
||||
debug:
|
||||
msg:
|
||||
- "Recovery if linux70 fails to boot:"
|
||||
- " 1. Reboot, hold SHIFT (or ESC) at POST to open the GRUB menu."
|
||||
- " 2. Pick 'Advanced options for Manjaro Linux' -> 'linux618-x86_64'."
|
||||
- " 3. linux618 + linux618-nvidia (580xx) modules are kept intact"
|
||||
- " so the fallback path is always bootable."
|
||||
tags: [system-upgrade, migration]
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 4. Initramfs refresh + GRUB regenerate + final reboot notice
|
||||
# ---------------------------------------------------------------------------
|
||||
# Manjaro's pacman post-install hooks normally invoke mkinitcpio and update-grub
|
||||
# automatically. We re-run them explicitly here as a belt-and-suspenders safety
|
||||
# net: if a hook was missed (e.g. interrupted transaction), the system still
|
||||
# ends up bootable. Both tasks are gated on "did pacman actually change
|
||||
# anything?" so an idempotent re-run is a true no-op.
|
||||
|
||||
- name: Boot - rebuild initramfs for all installed kernels (mkinitcpio -P)
|
||||
command: mkinitcpio -P
|
||||
become: yes
|
||||
register: mkinitcpio_result
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
- (pacman_syu.changed | default(false)) or (nvidia_migration.changed | default(false))
|
||||
tags: [system-upgrade, boot, initramfs]
|
||||
|
||||
- name: Boot - regenerate GRUB config (-> /boot/grub/grub.cfg)
|
||||
command: grub-mkconfig -o /boot/grub/grub.cfg
|
||||
become: yes
|
||||
register: grub_mkconfig_result
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
- (pacman_syu.changed | default(false)) or (nvidia_migration.changed | default(false))
|
||||
tags: [system-upgrade, boot, grub]
|
||||
|
||||
- name: Boot - stat both initramfs images
|
||||
stat:
|
||||
path: "{{ item }}"
|
||||
loop:
|
||||
- /boot/initramfs-6.18-x86_64.img
|
||||
- /boot/initramfs-7.0-x86_64.img
|
||||
register: initramfs_stat
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
tags: [system-upgrade, boot, initramfs]
|
||||
|
||||
- name: Boot - assert both initramfs images are present after install
|
||||
assert:
|
||||
that:
|
||||
- item.stat.exists
|
||||
fail_msg: >-
|
||||
Missing initramfs image: {{ item.item }} — investigate the mkinitcpio
|
||||
output above before rebooting. linux618 path may still be usable
|
||||
if only the linux70 image is missing.
|
||||
loop: "{{ initramfs_stat.results }}"
|
||||
loop_control:
|
||||
label: "{{ item.item }}"
|
||||
when: not ansible_check_mode
|
||||
tags: [system-upgrade, boot, initramfs]
|
||||
|
||||
- name: Boot - assert GRUB menu lists both kernels (linux618 + linux70)
|
||||
shell: |
|
||||
# Manjaro grub.cfg uses 'Manjaro Linux (Kernel: X.Y.Z-MANJARO x64)' format,
|
||||
# NOT 'linux618'/'linux70' package-name tokens. Count menuentries for each
|
||||
# kernel family separately so we fail if one is missing (a simple total
|
||||
# count would mask a missing kernel if the other family has 2+ entries).
|
||||
K618=$(grep -cE "menuentry .*Kernel: 6\.18\." /boot/grub/grub.cfg)
|
||||
K70=$(grep -cE "menuentry .*Kernel: 7\.0\." /boot/grub/grub.cfg)
|
||||
echo "linux618 (Kernel: 6.18.x) menuentries: ${K618}"
|
||||
echo "linux70 (Kernel: 7.0.x) menuentries: ${K70}"
|
||||
if [ "${K618}" -lt 1 ] || [ "${K70}" -lt 1 ]; then
|
||||
echo "FAIL: missing menuentry for one or both kernels" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: both kernels are listed in /boot/grub/grub.cfg"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: grub_menu_check
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
failed_when:
|
||||
- grub_menu_check.rc != 0
|
||||
- not ansible_check_mode
|
||||
tags: [system-upgrade, boot, grub]
|
||||
|
||||
- name: Boot - final reboot notice
|
||||
debug:
|
||||
msg:
|
||||
- "================================================================"
|
||||
- "system-upgrade role finished successfully."
|
||||
- ""
|
||||
- "NEXT STEP: reboot and select 'linux70' from the GRUB menu."
|
||||
- " 1. sudo reboot"
|
||||
- " 2. At the GRUB menu, choose 'Advanced options for Manjaro Linux'"
|
||||
- " -> 'Manjaro Linux on /dev/... linux70-x86_64'."
|
||||
- " 3. After login, verify with:"
|
||||
- " uname -r # expect 7.0.x"
|
||||
- " nvidia-smi # expect driver 580.159.03 on GTX 1050 Ti"
|
||||
- ""
|
||||
- "Only AFTER a successful linux70 boot, run the upcoming Hyprland role."
|
||||
- "================================================================"
|
||||
tags: [system-upgrade, notice]
|
||||
Reference in New Issue
Block a user