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