arch installation mostly works with zfsbootmgr

This commit is contained in:
Mark Riedesel 2024-11-20 09:12:19 -06:00
commit 1444f05d9c
19 changed files with 496 additions and 0 deletions

View file

@ -0,0 +1,11 @@
---
- name: Inspect EFI boot partitions
become: true
command: "blkid {{ item }}"
loop: "{{ base_efi_partitions | default([]) }}"
register: blkid
- name: Format EFI partitions fat32
command: "mkfs.vfat -v -F 32 -n EFI {{ item.item }}"
loop: "{{ blkid.results | rejectattr('stdout', 'contains', 'TYPE=\"vfat\"') }}"
register: mkfs_vfat_efi

View file

@ -0,0 +1,67 @@
---
- name: Check for existing zroot zfs volume
command: zpool list -Ho name zroot
register: zroot_check
ignore_errors: true
- block:
- name: Initialize disk device to id table
set_fact:
partition_device_to_ids: {}
- name: Create disk device to id table
set_fact:
partition_device_to_ids: >-
{{
partition_device_to_ids
| combine({ item.value: (partition_device_to_ids[item.value] | default([])) + [item.key] })
}}
with_items: "{{ base_partitions_by_id | dict2items }}"
- name: Create zroot volume
become: true
command: >-
zpool create -f -o ashift=12
-o autotrim=on
-O devices=off
-O relatime=on
-O xattr=sa
-O acltype=posixacl
-O normalization=formD
-O compression=lz4
-O canmount=off
-O mountpoint=none
-R /mnt
zroot {{ mirror }} {{ base_root_partitions | map('extract', partition_device_to_ids) | flatten | list | join(' ') }}
vars:
mirror: "{{ 'mirror' if base_root_partitions | length > 1 else '' }}"
when: zroot_check.rc != 0
- name: Create zroot/ROOT and zroot/DATA volumes
community.general.zfs:
name: "zroot/{{ item }}"
state: present
register: zfs_zroot_root_volume
with_items: [ROOT, DATA]
- name: Create zroot/ROOT/arch
community.general.zfs:
name: zroot/ROOT/arch
state: present
extra_zfs_properties:
canmount: noauto
mountpoint: /
when: zfs_zroot_root_volume.changed
- name: Create zroot/home
community.general.zfs:
name: zroot/DATA/home
state: present
extra_zfs_properties:
mountpoint: /home
- name: Export zroot pool
command: zpool export zroot
- name: Import zroot pool (-R /mnt)
command: zpool import -R /mnt zroot -N

View file

@ -0,0 +1,12 @@
---
- name: Initialize swap space
become: true
command: "blkid {{item}}"
loop: "{{ base_swap_partitions | default([]) }}"
register: blkid
- name: Swap devices without swap filesystems present
become: true
command: "mkswap --verbose {{item.item}}"
loop: "{{ blkid.results | rejectattr('stdout', 'contains', 'TYPE=\"swap\"') }}"
register: mkswap

View file

@ -0,0 +1,80 @@
---
- name: archinstall | install os | check for presence of previously pacstrapped /mnt
stat:
path: /mnt/usr/lib
register: existing_pacstrap
- debug:
var: existing_pacstrap
- name: archinstall | install os | pacstrap
shell: "pacstrap /mnt {{ packages | join(' ') }}"
vars:
packages:
- base
- base-devel
- efibootmgr
- git
- iwd
- linux-firmware
- linux-lts
- linux-lts-headers
- openssh
when: not existing_pacstrap.stat.exists
- name: archinstall | install os | copy pacman mirrorlist
copy:
remote_src: true
src: /etc/pacman.d/mirrorlist
dest: /mnt/etc/pacman.d/mirrorlist
- name: archinstall | install os | propagate root authorized keys
copy:
remote_src: true
src: /root/.ssh/authorized_keys
dest: /mnt/root/.ssh/authorized_keys
- name: archinstall | install os | passwordless sudo for group wheel
copy:
content: "%wheel ALL=(ALL) NOPASSWD: ALL"
dest: /mnt/etc/sudoers.d/wheel-group-nopasswd
- name: archinstall | install os | set timezone
file:
src: /usr/share/zoneinfo/US/Central
dest: /mnt/etc/localtime
state: link
- name: archinstall | install os | enable en_US locales
command: sed -i 's/^#en_US/en_US/' /mnt/etc/locale.gen
- name: archinstall | install os | generate locales
command: arch-chroot /mnt locale-gen
- name: archinstall | install os | generate template for arch-chroot installation
template:
src: arch_chroot_install.sh
dest: /mnt/arch_chroot_install.sh
mode: "0755"
- name: archinstall | install os | set hostname
copy:
dest: /mnt/etc/hostname
content: |
{{ inventory_hostname }}
- name: archinstall | install os | run installation script in arch-chroot
command: arch-chroot /mnt /arch_chroot_install.sh
register: chroot
- name: archinstall | install os | arch-chroot install output
debug:
msg: "{{ chroot.stdout_lines }}"
- name: archinstall | install os | remove arch-chroot installation script
file:
path: /mnt/arch_chroot_install.sh
state: absent
# TODO
# - name: archinstall | install os | create fstab

View file

@ -0,0 +1,4 @@
---
- name: Select fastest Arch repository mirrors
command:
cmd: reflector --country US --latest 5 --sort rate --save /etc/pacman.d/mirrorlist

View file

@ -0,0 +1,138 @@
---
- name: Get details about rootfs disks
community.general.parted:
device: "{{ item }}"
unit: MiB
register: base_root_disks_info
loop: "{{ base_root_disks | list }}"
- name: Calculate maximum usable disk space
ansible.builtin.set_fact:
base_root_usable_mib: "{{ (base_root_disks_info.results | map(attribute='disk.size') | min | int) - 1 }}"
- debug: var=base_root_usable_mib
- name: Calculate disk utilization percentage
ansible.builtin.set_fact:
base_root_usable_mib: "{{ base_root_usable_mib|int - ((base_root_usable_mib|float) * (0.01 * (base_root_free_percent|float))) | round(method='floor') | int }}"
- name: Calculate zfs volume size
set_fact:
base_root_zpool_mib: "{{ base_root_usable_mib|int - fixed_size_partitions|int }}"
vars:
fixed_size_partitions: "{{ base_root_swap_mib|int + base_root_efi_mib|int }}"
#
- name: Calculate partition layouts
set_fact:
partition_ranges: >-
{{
(partition_ranges|d([])) + [{
'begin': base_root_partitions[:(loop_index|int)] | map(attribute='size_mib') | map('int') | sum(),
'end': base_root_partitions[:(loop_index|int+1)] | map(attribute='size_mib') | map('int') | sum(),
}]
}}
vars:
loop_index: "{{ item }}"
base_root_partitions:
- name: efi
size_mib: "{{ base_root_efi_mib }}"
- name: root
size_mib: "{{ base_root_zpool_mib }}"
- name: swap
size_mib: "{{ base_root_swap_mib }}"
with_sequence: start=0 end="{{ base_root_partitions | length - 1}}"
- debug:
var: partition_ranges
- name: Initialize partition facts
set_fact:
base_efi_partitions: []
base_root_partitions: []
base_swap_partitions: []
- name: Create EFI partition
become: true
vars:
part_index: 0
parted:
label: gpt
unit: MiB
name: EFI Boot
device: "{{ item.disk.dev }}"
number: "{{ part_index + 1 }}"
flags: [ boot, esp ]
part_start: "{{ [partition_ranges[part_index].begin, 1]|max }}MiB"
part_end: "{{ partition_ranges[part_index].end }}MiB"
state: present
fs_type: fat32
loop: "{{ base_root_disks_info.results }}"
register: parted_create
- name: Store EFI partition details
set_fact:
base_efi_partitions: "{{ parted_create.results | map(attribute='disk.dev') | product([1]) | map('join') | list }}"
- name: Create root zvol partition
become: true
vars:
part_index: 1
parted:
label: gpt
unit: MiB
name: ArchLinux ZFS Root
device: "{{ item.disk.dev }}"
number: "{{ part_index + 1 }}"
part_start: "{{ partition_ranges[part_index].begin }}MiB"
part_end: "{{ partition_ranges[part_index].end }}MiB"
state: present
loop: "{{ parted_create.results }}"
register: parted_create
- name: Store root zvol partition details
set_fact:
base_root_partitions: "{{ parted_create.results | map(attribute='disk.dev') | product([2]) | map('join') | list }}"
- name: Create swap partition
become: true
vars:
part_index: 2
parted:
label: gpt
unit: MiB
device: "{{ item.disk.dev }}"
number: "{{ part_index + 1 }}"
part_start: "{{ partition_ranges[part_index].begin }}MiB"
part_end: "{{ partition_ranges[part_index].end }}MiB"
state: present
fs_type: linux-swap
loop: "{{ parted_create.results }}"
register: parted_create
when: base_root_swap_mib is defined and base_root_swap_mib > 0
- name: Store swap partition details
set_fact:
base_swap_partitions: "{{ parted_create.results | map(attribute='disk.dev') | product([3]) | map('join') | list }}"
when: base_root_swap_mib is defined and base_root_swap_mib > 0
- name: Analyze resulting partition layouts
parted:
unit: MiB
device: "{{ item }}"
register: base_root_disks_info
loop: "{{ base_root_disks | list }}"
- name: Collect disk device identifiers
shell: "for x in /dev/disk/by-id/*; do echo $x $(realpath $x); done"
register: disk_realpaths
- name: Collect disk device identifiers into a base_partitions_by_id dictionary
set_fact:
base_partitions_by_id: >-
{{
dict(
disk_realpaths.stdout_lines
| map('split', ' ')
| map('list')
)
}}

View file

@ -0,0 +1,11 @@
- name: archinstall | re-create post-installation snapshot of zroot/ROOT/arch
community.general.zfs:
name: zroot/ROOT/arch@post-installation
state: "{{ item }}"
with_items: [absent, present]
- name: archinstall | re-create post-installation snapshot of zroot/DATA/home
community.general.zfs:
name: zroot/DATA/home@post-installation
state: "{{ item }}"
with_items: [absent, present]

View file

@ -0,0 +1,30 @@
---
- name: Mount arch zroot
command: zfs mount zroot/ROOT/arch
- name: Mount all other zroot mountpoints
command: zfs mount -a
- name: Create zroot destination directories
ansible.builtin.file:
path: "/mnt{{ item }}"
state: directory
loop:
- /etc/zfs
- /boot/efi
- name: Mount EFI
ansible.posix.mount:
path: /mnt/boot/efi
src: "{{ base_efi_partitions | first }}"
fstype: vfat
state: mounted
- name: zfs | set zroot bootfs to arch
command: zpool set bootfs=zroot/ROOT/arch zroot
- name: zfs | set cachefile
command: zpool set cachefile=/etc/zfs/zpool.cache zroot
- name: zfs | copy cache file to chroot
command: cp /etc/zfs/zpool.cache /mnt/etc/zfs

View file

@ -0,0 +1,12 @@
---
- block:
# - import_tasks: archinstall/mirrorlist.yaml
- import_tasks: archinstall/partition.yaml
- import_tasks: archinstall/initialize_root_zvol.yaml
- import_tasks: archinstall/initialize_swap.yaml
- import_tasks: archinstall/initialize_efi.yaml
- import_tasks: archinstall/prepare_chroot.yaml
- import_tasks: archinstall/install_os.yaml
- import_tasks: archinstall/postinstall_snapshot.yaml
when: base_root_disks is defined and ansible_hostname == 'archiso'