Compare commits
75
Commits
master
..
6240217318
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6240217318 | ||
|
|
1c00ec9370 | ||
|
|
371d5a0acd | ||
|
|
41ccf2a5b9 | ||
|
|
8f9cfe3b2f | ||
|
|
6a75237197 | ||
|
|
b04aad12fb | ||
|
|
4fff9f8d80 | ||
|
|
7f12a0f3d8 | ||
|
|
ceb2237bbb | ||
|
|
477c8379c4 | ||
|
|
579c499c02 | ||
|
|
89e366d0f0 | ||
|
|
6fe843355e | ||
|
|
441876fab9 | ||
|
|
00acd4d200 | ||
|
|
d922efd2e4 | ||
|
|
939c5c741f | ||
|
|
2c35409519 | ||
|
|
d2a19cfd5c | ||
|
|
44f5adc682 | ||
|
|
0185797af9 | ||
|
|
e0ecf628cd | ||
|
|
37df881daa | ||
|
|
55b21eae5d | ||
|
|
b1e938b7f0 | ||
|
|
c843f5289b | ||
|
|
9757ed3785 | ||
|
|
876e90ce2b | ||
|
|
7c44cb1ff0 | ||
|
|
5d0630a386 | ||
|
|
3eaf918a53 | ||
|
|
382e82ff85 | ||
|
|
db7dc53bd7 | ||
|
|
7d45f25a7e | ||
|
|
3880b8f41e | ||
|
|
dc3c4a901f | ||
|
|
6bfaa0aa2b | ||
|
|
5dc0424acb | ||
|
|
c12332a853 | ||
|
|
5ace4577a2 | ||
|
|
c0ff01ef40 | ||
|
|
57417514e3 | ||
|
|
0928588c1f | ||
|
|
6d622f2db4 | ||
|
|
b11d65a6f3 | ||
|
|
3623fc292c | ||
|
|
dfca7ec94b | ||
|
|
e8be84bf49 | ||
|
|
322cc0b1ce | ||
|
|
4b38754f8b | ||
|
|
a6bc7ffe04 | ||
|
|
c529e71ebc | ||
|
|
cb46de2b6d | ||
|
|
9169117b25 | ||
|
|
6c94c519fb | ||
|
|
efd96a42b8 | ||
|
|
68661c3cca | ||
|
|
1db20c7ac0 | ||
|
|
7b155b427b | ||
|
|
ca8721e98f | ||
|
|
cdb2559d8f | ||
|
|
443f6623df | ||
|
|
6cf418fe00 | ||
|
|
47ec5fe621 | ||
|
|
240f945cce | ||
|
|
663a04556f | ||
|
|
6febd1acf1 | ||
|
|
008187860c | ||
|
|
cd1be6b5e1 | ||
|
|
15be6149fd | ||
|
|
ca29ad200d | ||
|
|
8079099cee | ||
|
|
9e79185b07 | ||
|
|
b88bf2860f |
@@ -183,7 +183,7 @@ Top-level variables outside `system`/`hypervisor`.
|
|||||||
|
|
||||||
#### `system.content`
|
#### `system.content`
|
||||||
|
|
||||||
Uniform package content source, family-resolved. `source: ''` defaults to `dvd` on `rhel` and to `mirror` everywhere else, AlmaLinux, Rocky and Fedora included: they have public mirrors, RHEL does not. Satellite values come from inventory/vault only, never committed code.
|
Uniform package content source, family-resolved. `source: ''` defaults to `dvd` on EL and `mirror` on Debian/Ubuntu/Arch. Satellite values come from inventory/vault only, never committed code.
|
||||||
|
|
||||||
| Key | Type | Default | Description |
|
| Key | Type | Default | Description |
|
||||||
| -------------------------- | ------ | -------------- | ----------------------------------------------------------------- |
|
| -------------------------- | ------ | -------------- | ----------------------------------------------------------------- |
|
||||||
@@ -538,8 +538,6 @@ When `hypervisor.type: vmware` uses the `vmware_tools` connection:
|
|||||||
|
|
||||||
`system.disks[0]` is the OS disk (no `mount.path`). Additional entries define data disks.
|
`system.disks[0]` is the OS disk (no `mount.path`). Additional entries define data disks.
|
||||||
|
|
||||||
On VMware, `device` is resolved on the target from the SCSI address instead: entry N is the disk at target N on the first SCSI controller (N+1 from index 7 on, since unit 7 is reserved). The kernel's `sdX` order is not stable between the install environment and the installed system, so a letter-derived path can point at another disk.
|
|
||||||
|
|
||||||
| Key | Type | Description |
|
| Key | Type | Description |
|
||||||
| ------------- | ------ | ------------------------------------------------------ |
|
| ------------- | ------ | ------------------------------------------------------ |
|
||||||
| `size` | number | Disk size in GB (required for virtual) |
|
| `size` | number | Disk size in GB (required for virtual) |
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ bootstrap_hardware_packages:
|
|||||||
amd: [amd-ucode]
|
amd: [amd-ucode]
|
||||||
firmware_base: []
|
firmware_base: []
|
||||||
firmware:
|
firmware:
|
||||||
intel: [linux-firmware-intel] # iwlwifi (WiFi) + i915/xe (GPU) + ibt (BT) firmware live here
|
intel: [linux-firmware-other] # iwlwifi + i915 firmware live here
|
||||||
amd: [linux-firmware-amdgpu]
|
amd: [linux-firmware-amdgpu]
|
||||||
nvidia: [linux-firmware-nvidia]
|
nvidia: [linux-firmware-nvidia]
|
||||||
atheros: [linux-firmware-atheros]
|
atheros: [linux-firmware-atheros]
|
||||||
|
|||||||
@@ -206,7 +206,6 @@ bootstrap_debian:
|
|||||||
- openssh-server
|
- openssh-server
|
||||||
- python3
|
- python3
|
||||||
- xfsprogs
|
- xfsprogs
|
||||||
- xz-utils
|
|
||||||
extra:
|
extra:
|
||||||
- bat
|
- bat
|
||||||
- curl
|
- curl
|
||||||
@@ -259,7 +258,6 @@ bootstrap_ubuntu:
|
|||||||
- openssh-server
|
- openssh-server
|
||||||
- python3
|
- python3
|
||||||
- xfsprogs
|
- xfsprogs
|
||||||
- xz-utils
|
|
||||||
extra:
|
extra:
|
||||||
- bash-completion
|
- bash-completion
|
||||||
- bat
|
- bat
|
||||||
|
|||||||
@@ -3,5 +3,3 @@
|
|||||||
cleanup_verify_boot: true
|
cleanup_verify_boot: true
|
||||||
cleanup_boot_timeout: 300
|
cleanup_boot_timeout: 300
|
||||||
cleanup_remove_on_failure: true
|
cleanup_remove_on_failure: true
|
||||||
cleanup_poweroff_retries: 24
|
|
||||||
cleanup_poweroff_delay: 5
|
|
||||||
|
|||||||
@@ -6,30 +6,7 @@
|
|||||||
module_defaults:
|
module_defaults:
|
||||||
community.proxmox.proxmox_disk: "{{ _proxmox_auth }}"
|
community.proxmox.proxmox_disk: "{{ _proxmox_auth }}"
|
||||||
community.proxmox.proxmox_kvm: "{{ _proxmox_auth_node }}"
|
community.proxmox.proxmox_kvm: "{{ _proxmox_auth_node }}"
|
||||||
community.proxmox.proxmox_vm_info: "{{ _proxmox_auth_node }}"
|
|
||||||
block:
|
block:
|
||||||
- name: Wait for the installer environment to power off
|
|
||||||
community.proxmox.proxmox_vm_info:
|
|
||||||
vmid: "{{ system_cfg.id }}"
|
|
||||||
register: cleanup_proxmox_power
|
|
||||||
until: >-
|
|
||||||
((cleanup_proxmox_power.proxmox_vms | default([]) | first | default({})).status
|
|
||||||
| default('')) == 'stopped'
|
|
||||||
retries: "{{ cleanup_poweroff_retries }}"
|
|
||||||
delay: "{{ cleanup_poweroff_delay }}"
|
|
||||||
failed_when: false
|
|
||||||
no_log: true
|
|
||||||
|
|
||||||
- name: Force the installer environment off when it did not shut down
|
|
||||||
when: >-
|
|
||||||
((cleanup_proxmox_power.proxmox_vms | default([]) | first | default({})).status
|
|
||||||
| default('')) != 'stopped'
|
|
||||||
community.proxmox.proxmox_kvm:
|
|
||||||
vmid: "{{ system_cfg.id }}"
|
|
||||||
state: stopped
|
|
||||||
force: true
|
|
||||||
no_log: true
|
|
||||||
|
|
||||||
- name: Cleanup Setup Disks
|
- name: Cleanup Setup Disks
|
||||||
community.proxmox.proxmox_disk:
|
community.proxmox.proxmox_disk:
|
||||||
name: "{{ hostname }}"
|
name: "{{ hostname }}"
|
||||||
@@ -44,6 +21,13 @@
|
|||||||
failed_when: false
|
failed_when: false
|
||||||
no_log: true
|
no_log: true
|
||||||
|
|
||||||
|
- name: Ensure the installer environment is powered off
|
||||||
|
community.proxmox.proxmox_kvm:
|
||||||
|
vmid: "{{ system_cfg.id }}"
|
||||||
|
state: stopped
|
||||||
|
force: true
|
||||||
|
no_log: true
|
||||||
|
|
||||||
- name: Boot the installed OS
|
- name: Boot the installed OS
|
||||||
community.proxmox.proxmox_kvm:
|
community.proxmox.proxmox_kvm:
|
||||||
vmid: "{{ system_cfg.id }}"
|
vmid: "{{ system_cfg.id }}"
|
||||||
|
|||||||
@@ -5,26 +5,9 @@
|
|||||||
become: false
|
become: false
|
||||||
module_defaults:
|
module_defaults:
|
||||||
community.vmware.vmware_guest: "{{ _vmware_auth }}"
|
community.vmware.vmware_guest: "{{ _vmware_auth }}"
|
||||||
community.vmware.vmware_guest_info: "{{ _vmware_auth }}"
|
|
||||||
vmware.vmware.vm_powerstate: "{{ _vmware_auth }}"
|
vmware.vmware.vm_powerstate: "{{ _vmware_auth }}"
|
||||||
no_log: true
|
no_log: true
|
||||||
block:
|
block:
|
||||||
- name: Wait for the installer environment to power off
|
|
||||||
community.vmware.vmware_guest_info:
|
|
||||||
name: "{{ hostname }}"
|
|
||||||
register: cleanup_vmware_power
|
|
||||||
until: (cleanup_vmware_power.instance.hw_power_status | default('') | lower) == 'poweredoff'
|
|
||||||
retries: "{{ cleanup_poweroff_retries }}"
|
|
||||||
delay: "{{ cleanup_poweroff_delay }}"
|
|
||||||
failed_when: false
|
|
||||||
|
|
||||||
- name: Force the installer environment off when it did not shut down
|
|
||||||
when: (cleanup_vmware_power.instance.hw_power_status | default('') | lower) != 'poweredoff'
|
|
||||||
vmware.vmware.vm_powerstate:
|
|
||||||
name: "{{ hostname }}"
|
|
||||||
state: powered-off
|
|
||||||
force: true
|
|
||||||
|
|
||||||
- name: Remove CD-ROM from VM in vCenter
|
- name: Remove CD-ROM from VM in vCenter
|
||||||
community.vmware.vmware_guest:
|
community.vmware.vmware_guest:
|
||||||
name: "{{ hostname }}"
|
name: "{{ hostname }}"
|
||||||
@@ -58,7 +41,7 @@
|
|||||||
}}
|
}}
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
- name: Boot the installed OS
|
- name: Start VM in vCenter
|
||||||
vmware.vmware.vm_powerstate:
|
vmware.vmware.vm_powerstate:
|
||||||
name: "{{ hostname }}"
|
name: "{{ hostname }}"
|
||||||
state: powered-on
|
state: powered-on
|
||||||
|
|||||||
@@ -18,24 +18,13 @@
|
|||||||
register: configuration_bootloader_result
|
register: configuration_bootloader_result
|
||||||
changed_when: configuration_bootloader_result.rc == 0
|
changed_when: configuration_bootloader_result.rc == 0
|
||||||
|
|
||||||
- name: Remove stale EFI boot entries for this OS
|
- name: Check existing EFI boot entries
|
||||||
# UEFI NVRAM entries survive a disk wipe (they live in firmware, not on disk).
|
ansible.builtin.command: efibootmgr
|
||||||
# A prior install leaves a dead entry, and a case-insensitive duplicate label
|
register: configuration_efi_entries
|
||||||
# ("ArchLinux" vs "archlinux") would otherwise win the boot order - the firmware
|
changed_when: false
|
||||||
# then falls through to removable media. Delete every entry carrying our label,
|
|
||||||
# then recreate exactly one clean entry.
|
|
||||||
ansible.builtin.shell:
|
|
||||||
cmd: >-
|
|
||||||
set -o pipefail;
|
|
||||||
efibootmgr | grep -iP '^Boot[0-9A-F]{4}\*?\s+{{ _efi_vendor }}\s*$'
|
|
||||||
| grep -oP '^Boot\K[0-9A-F]{4}'
|
|
||||||
| xargs -r -I{} efibootmgr -b {} -B
|
|
||||||
executable: /bin/bash
|
|
||||||
register: _efi_gc_result
|
|
||||||
changed_when: _efi_gc_result.stdout | length > 0
|
|
||||||
failed_when: false
|
|
||||||
|
|
||||||
- name: Create EFI boot entry (efibootmgr -c prepends it to BootOrder)
|
- name: Ensure EFI boot entry exists
|
||||||
|
when: ('* ' + _efi_vendor) not in configuration_efi_entries.stdout
|
||||||
ansible.builtin.command: >-
|
ansible.builtin.command: >-
|
||||||
efibootmgr -c
|
efibootmgr -c
|
||||||
-L '{{ _efi_vendor }}'
|
-L '{{ _efi_vendor }}'
|
||||||
@@ -45,16 +34,15 @@
|
|||||||
register: configuration_efi_entry_result
|
register: configuration_efi_entry_result
|
||||||
changed_when: configuration_efi_entry_result.rc == 0
|
changed_when: configuration_efi_entry_result.rc == 0
|
||||||
|
|
||||||
- name: Install removable EFI fallback loader
|
- name: Set installed OS as first EFI boot entry
|
||||||
# Firmware-agnostic fallback (\EFI\BOOT\BOOTX64.EFI): many consumer firmwares
|
ansible.builtin.shell:
|
||||||
# ignore or reset custom NVRAM entries and boot only the removable path.
|
cmd: >-
|
||||||
when: _configuration_platform.grub_install
|
set -o pipefail &&
|
||||||
ansible.builtin.command: >-
|
efibootmgr | grep -i '{{ _efi_vendor }}' | grep -oP 'Boot\K[0-9A-F]+' | head -1
|
||||||
{{ chroot_command }} /usr/bin/install -Dm644
|
| xargs -I{} efibootmgr -o {}
|
||||||
{{ partitioning_efi_mountpoint }}/EFI/{{ _efi_vendor }}/{{ _efi_loader }}
|
executable: /bin/bash
|
||||||
{{ partitioning_efi_mountpoint }}/EFI/BOOT/BOOTX64.EFI
|
register: _efi_bootorder_result
|
||||||
register: _efi_fallback_result
|
changed_when: _efi_bootorder_result.rc == 0
|
||||||
changed_when: _efi_fallback_result.rc == 0
|
|
||||||
|
|
||||||
- name: Ensure lvm2 for non btrfs filesystems
|
- name: Ensure lvm2 for non btrfs filesystems
|
||||||
when: os == "archlinux" and system_cfg.filesystem != "btrfs"
|
when: os == "archlinux" and system_cfg.filesystem != "btrfs"
|
||||||
|
|||||||
@@ -12,21 +12,6 @@
|
|||||||
and 'No such file or directory' not in (_firewall_enable.stderr | default(''))
|
and 'No such file or directory' not in (_firewall_enable.stderr | default(''))
|
||||||
and 'does not exist' not in (_firewall_enable.stderr | default(''))
|
and 'does not exist' not in (_firewall_enable.stderr | default(''))
|
||||||
|
|
||||||
# Distro base sets ship the daemon preset-enabled (RHEL @core pulls firewalld in),
|
|
||||||
# so opting out has to disable the unit, not merely skip enabling it.
|
|
||||||
- name: Disable the firewall daemon in the install chroot
|
|
||||||
when:
|
|
||||||
- firewall_phase == 'install'
|
|
||||||
- _configuration_platform.init_system == 'systemd'
|
|
||||||
- not system_cfg.features.firewall.enabled | bool
|
|
||||||
ansible.builtin.command: "{{ chroot_command }} systemctl disable {{ system_cfg.features.firewall.backend }}"
|
|
||||||
register: _firewall_disable
|
|
||||||
changed_when: "'Removed' in (_firewall_disable.stderr | default(''))"
|
|
||||||
failed_when: >-
|
|
||||||
_firewall_disable.rc != 0
|
|
||||||
and 'No such file or directory' not in (_firewall_disable.stderr | default(''))
|
|
||||||
and 'does not exist' not in (_firewall_disable.stderr | default(''))
|
|
||||||
|
|
||||||
# ufw's CLI needs a running kernel and is a no-op in the chroot (leaves ENABLED=no),
|
# ufw's CLI needs a running kernel and is a no-op in the chroot (leaves ENABLED=no),
|
||||||
# so its activation and SSH rule are applied here, after reboot.
|
# so its activation and SSH rule are applied here, after reboot.
|
||||||
- name: Allow SSH through ufw before enabling
|
- name: Allow SSH through ufw before enabling
|
||||||
|
|||||||
@@ -43,14 +43,11 @@
|
|||||||
}}
|
}}
|
||||||
grub_root_flags: >-
|
grub_root_flags: >-
|
||||||
{{ ['rootflags=subvol=@'] if system_cfg.filesystem == 'btrfs' else [] }}
|
{{ ['rootflags=subvol=@'] if system_cfg.filesystem == 'btrfs' else [] }}
|
||||||
grub_selinux_args: >-
|
|
||||||
{{ [] if system_cfg.features.selinux.enabled | bool else ['selinux=0'] }}
|
|
||||||
# String-concat (not list-concat like grub_kernel_cmdline_base below): ansible-lint's
|
# String-concat (not list-concat like grub_kernel_cmdline_base below): ansible-lint's
|
||||||
# jinja render trips on list+list when grub_lvm_args leads the expression here.
|
# jinja render trips on list+list when grub_lvm_args leads the expression here.
|
||||||
grub_cmdline_linux_base: >-
|
grub_cmdline_linux_base: >-
|
||||||
{{
|
{{
|
||||||
((grub_lvm_args | join(' ')) ~ ' ' ~ (grub_selinux_args | join(' ')) ~ ' '
|
((grub_lvm_args | join(' ')) ~ ' ' ~ (_hardware_profile_kernel_params | default([]) | join(' '))) | trim
|
||||||
~ (_hardware_profile_kernel_params | default([]) | join(' '))) | trim
|
|
||||||
}}
|
}}
|
||||||
grub_kernel_cmdline_base: >-
|
grub_kernel_cmdline_base: >-
|
||||||
{{
|
{{
|
||||||
@@ -60,7 +57,6 @@
|
|||||||
+ ['ro']
|
+ ['ro']
|
||||||
+ grub_lvm_args
|
+ grub_lvm_args
|
||||||
+ grub_root_flags
|
+ grub_root_flags
|
||||||
+ grub_selinux_args
|
|
||||||
+ (_hardware_profile_kernel_params | default([]))
|
+ (_hardware_profile_kernel_params | default([]))
|
||||||
)
|
)
|
||||||
| join(' ')
|
| join(' ')
|
||||||
|
|||||||
@@ -22,12 +22,10 @@
|
|||||||
mode: "0644"
|
mode: "0644"
|
||||||
|
|
||||||
# Fedora: setfiles segfaults during bootstrap chroot relabeling, so SELinux
|
# Fedora: setfiles segfaults during bootstrap chroot relabeling, so SELinux
|
||||||
# is left permissive and expected to relabel on first boot. Opting out writes
|
# is left permissive and expected to relabel on first boot.
|
||||||
# disabled here and selinux=0 on the kernel cmdline (grub.yml), the only form
|
- name: Disable SELinux
|
||||||
# EL9 honours.
|
|
||||||
- name: Set the SELinux mode
|
|
||||||
when: os == "fedora" or not system_cfg.features.selinux.enabled | bool
|
when: os == "fedora" or not system_cfg.features.selinux.enabled | bool
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
path: /mnt/etc/selinux/config
|
path: /mnt/etc/selinux/config
|
||||||
regexp: ^SELINUX=
|
regexp: ^SELINUX=
|
||||||
line: "SELINUX={{ 'permissive' if system_cfg.features.selinux.enabled | bool else 'disabled' }}"
|
line: SELINUX=permissive
|
||||||
|
|||||||
@@ -78,8 +78,7 @@ system_defaults:
|
|||||||
timezone: "Europe/Vienna"
|
timezone: "Europe/Vienna"
|
||||||
locale: "en_US.UTF-8"
|
locale: "en_US.UTF-8"
|
||||||
keymap: "us"
|
keymap: "us"
|
||||||
# source: dvd|mirror|satellite|none ('' -> family default: rhel=dvd, else mirror;
|
# source: dvd|mirror|satellite|none ('' -> family default: EL=dvd, else mirror).
|
||||||
# almalinux/rocky/fedora have public mirrors, rhel does not).
|
|
||||||
# satellite values come from inventory/vault only, never committed code.
|
# satellite values come from inventory/vault only, never committed code.
|
||||||
content:
|
content:
|
||||||
source: ""
|
source: ""
|
||||||
|
|||||||
@@ -94,7 +94,6 @@
|
|||||||
|
|
||||||
- name: Set install_drive from primary disk
|
- name: Set install_drive from primary disk
|
||||||
when:
|
when:
|
||||||
- install_drive is not defined
|
|
||||||
- system_disks_cfg | length > 0
|
- system_disks_cfg | length > 0
|
||||||
- system_disks_cfg[0].device | string | length > 0
|
- system_disks_cfg[0].device | string | length > 0
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
|
|||||||
@@ -35,12 +35,10 @@
|
|||||||
}, recursive=True)
|
}, recursive=True)
|
||||||
}}
|
}}
|
||||||
|
|
||||||
# Keyed on os, not hostname: inventories set hostname themselves, and doing so
|
|
||||||
# would otherwise skip enrichment and leave os undefined for validation.
|
|
||||||
- name: Check if pre-computed system_cfg needs enrichment
|
- name: Check if pre-computed system_cfg needs enrichment
|
||||||
when: system_cfg is defined
|
when: system_cfg is defined
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
_bootstrap_needs_enrichment: "{{ os is not defined }}"
|
_bootstrap_needs_enrichment: "{{ hostname is not defined }}"
|
||||||
|
|
||||||
- name: Merge pre-computed system_cfg with bootstrap system_defaults
|
- name: Merge pre-computed system_cfg with bootstrap system_defaults
|
||||||
when:
|
when:
|
||||||
@@ -81,7 +79,9 @@
|
|||||||
os_version: "{{ system_cfg.version | default('') | string }}"
|
os_version: "{{ system_cfg.version | default('') | string }}"
|
||||||
|
|
||||||
- name: Normalize disk configuration (pre-computed system_cfg)
|
- name: Normalize disk configuration (pre-computed system_cfg)
|
||||||
when: system_cfg is defined
|
when:
|
||||||
|
- system_cfg is defined
|
||||||
|
- install_drive is not defined
|
||||||
ansible.builtin.include_tasks: _normalize_disks.yml
|
ansible.builtin.include_tasks: _normalize_disks.yml
|
||||||
|
|
||||||
# Runs on every path before validation, so an empty firewall.backend / content.source
|
# Runs on every path before validation, so an empty firewall.backend / content.source
|
||||||
|
|||||||
@@ -317,7 +317,7 @@
|
|||||||
_autologin: "{{ system_cfg.features.desktop.autologin | default(false) }}"
|
_autologin: "{{ system_cfg.features.desktop.autologin | default(false) }}"
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
- _autologin is boolean and not _autologin or (_autologin is string and _autologin | length > 0 and _autologin in system_cfg.users | map(attribute='name'))
|
- _autologin is boolean and not _autologin or (_autologin is string and _autologin | length > 0 and _autologin in system_cfg.users)
|
||||||
fail_msg: >-
|
fail_msg: >-
|
||||||
desktop.autologin must be false or a username string present in
|
desktop.autologin must be false or a username string present in
|
||||||
system.users; got '{{ _autologin }}'. Bool true is not accepted - the
|
system.users; got '{{ _autologin }}'. Bool true is not accepted - the
|
||||||
@@ -355,12 +355,14 @@
|
|||||||
|
|
||||||
- name: Validate at least one user with a password is defined
|
- name: Validate at least one user with a password is defined
|
||||||
vars:
|
vars:
|
||||||
_pw_users: "{{ system_cfg.users | selectattr('password', 'defined') | map(attribute='password') | map('string') | reject('equalto', '') | list }}"
|
_pw_users: "{{ system_cfg.users | dict2items | selectattr('value.password', 'defined') | list }}"
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
- system_cfg.users | default([]) | length > 0
|
- system_cfg.users | default({}) | length > 0
|
||||||
- _pw_users | length > 0
|
- _pw_users | length > 0
|
||||||
fail_msg: "At least one user with a non-empty password must be defined in system.users."
|
- _pw_users[0].key | string | length > 0
|
||||||
|
- _pw_users[0].value.password | string | length > 0
|
||||||
|
fail_msg: "At least one user with a password must be defined in system.users."
|
||||||
quiet: true
|
quiet: true
|
||||||
no_log: true
|
no_log: true
|
||||||
|
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
---
|
|
||||||
# The virtualization role attaches system.disks to SCSI controller 0 in list order, and
|
|
||||||
# vSphere never gives a disk unit 7 (the controller's own address). The kernel's sdX order
|
|
||||||
# is not that order and differs between the install environment and the installed OS, so
|
|
||||||
# a disk derived as /dev/sd<letter of its index> can be the wrong one. Resolve by target.
|
|
||||||
- name: List disks with their SCSI address
|
|
||||||
ansible.builtin.command: lsblk -dnpo NAME,TYPE,HCTL
|
|
||||||
register: partitioning_vmware_lsblk
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Map SCSI targets to devices
|
|
||||||
vars:
|
|
||||||
_scsi: >-
|
|
||||||
{%- set out = [] -%}
|
|
||||||
{%- for line in partitioning_vmware_lsblk.stdout_lines -%}
|
|
||||||
{%- set p = line.split() -%}
|
|
||||||
{%- if (p | length) == 3 and p[1] == 'disk' and p[2] is match('^\d+:0:\d+:0$') -%}
|
|
||||||
{%- set _ = out.append({'name': p[0], 'host': p[2].split(':')[0], 'target': p[2].split(':')[2]}) -%}
|
|
||||||
{%- endif -%}
|
|
||||||
{%- endfor -%}
|
|
||||||
{{ out }}
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
partitioning_vmware_hosts: "{{ _scsi | map(attribute='host') | unique | list }}"
|
|
||||||
partitioning_vmware_targets: "{{ _scsi | items2dict(key_name='target', value_name='name') }}"
|
|
||||||
partitioning_vmware_target_count: "{{ _scsi | length }}"
|
|
||||||
|
|
||||||
- name: Assert the system disks sit on one SCSI controller with unique targets
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- partitioning_vmware_hosts | length == 1
|
|
||||||
- partitioning_vmware_targets | length == partitioning_vmware_target_count | int
|
|
||||||
fail_msg: >-
|
|
||||||
Expected every disk on one SCSI controller with unique targets, got
|
|
||||||
{{ partitioning_vmware_lsblk.stdout_lines | select('search', ' disk ') | list }}.
|
|
||||||
quiet: true
|
|
||||||
|
|
||||||
- name: Assert each system disk has a device at its SCSI target
|
|
||||||
vars:
|
|
||||||
_target: "{{ (idx if idx < 7 else idx + 1) | string }}"
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- _target in partitioning_vmware_targets
|
|
||||||
fail_msg: "system.disks[{{ idx }}] ({{ item.size }} GB) expects a disk at SCSI target {{ _target }}, none found."
|
|
||||||
quiet: true
|
|
||||||
loop: "{{ system_cfg.disks }}"
|
|
||||||
loop_control:
|
|
||||||
index_var: idx
|
|
||||||
label: "{{ idx }}"
|
|
||||||
|
|
||||||
- name: Point system disks and install_drive at the resolved devices
|
|
||||||
vars:
|
|
||||||
_disks: >-
|
|
||||||
{%- set out = [] -%}
|
|
||||||
{%- for d in system_cfg.disks -%}
|
|
||||||
{%- set dev = partitioning_vmware_targets[(loop.index0 if loop.index0 < 7 else loop.index0 + 1) | string] -%}
|
|
||||||
{%- set _ = out.append(d | combine({'device': dev, 'partition': dev ~ '1'})) -%}
|
|
||||||
{%- endfor -%}
|
|
||||||
{{ out }}
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
system_cfg: "{{ system_cfg | combine({'disks': _disks}) }}"
|
|
||||||
install_drive: "{{ _disks[0].device }}"
|
|
||||||
@@ -1,10 +1,4 @@
|
|||||||
---
|
---
|
||||||
- name: Resolve VMware disks by SCSI target
|
|
||||||
when:
|
|
||||||
- hypervisor_type == "vmware"
|
|
||||||
- system_cfg.type == "virtual"
|
|
||||||
ansible.builtin.include_tasks: _resolve_vmware_disks.yml
|
|
||||||
|
|
||||||
- name: Detect system sizing
|
- name: Detect system sizing
|
||||||
ansible.builtin.include_tasks: _detect_sizing.yml
|
ansible.builtin.include_tasks: _detect_sizing.yml
|
||||||
|
|
||||||
|
|||||||
@@ -50,9 +50,6 @@
|
|||||||
esxi_hostname: "{{ hypervisor_cfg.node }}"
|
esxi_hostname: "{{ hypervisor_cfg.node }}"
|
||||||
register: system_check_esxi
|
register: system_check_esxi
|
||||||
delegate_facts: true
|
delegate_facts: true
|
||||||
until: system_check_esxi.ansible_facts is defined
|
|
||||||
retries: 3
|
|
||||||
delay: 10
|
|
||||||
failed_when: false
|
failed_when: false
|
||||||
changed_when: false
|
changed_when: false
|
||||||
no_log: true
|
no_log: true
|
||||||
@@ -87,9 +84,6 @@
|
|||||||
community.vmware.vmware_datastore_info:
|
community.vmware.vmware_datastore_info:
|
||||||
cluster: "{{ hypervisor_cfg.cluster }}"
|
cluster: "{{ hypervisor_cfg.cluster }}"
|
||||||
register: system_check_cluster
|
register: system_check_cluster
|
||||||
until: system_check_cluster.datastores is defined
|
|
||||||
retries: 3
|
|
||||||
delay: 10
|
|
||||||
failed_when: false
|
failed_when: false
|
||||||
changed_when: false
|
changed_when: false
|
||||||
no_log: true
|
no_log: true
|
||||||
@@ -138,10 +132,6 @@
|
|||||||
path: "{{ item.path }}"
|
path: "{{ item.path }}"
|
||||||
state: file
|
state: file
|
||||||
register: system_check_media_files
|
register: system_check_media_files
|
||||||
# A missing file fails with status 404; a dropped vCenter connection fails with status None.
|
|
||||||
until: system_check_media_files is not failed or system_check_media_files.status is not none
|
|
||||||
retries: 3
|
|
||||||
delay: 10
|
|
||||||
failed_when: false
|
failed_when: false
|
||||||
changed_when: false
|
changed_when: false
|
||||||
loop: "{{ system_check_datastores_needed | rejectattr('source', 'equalto', 'hypervisor.storage') | list }}"
|
loop: "{{ system_check_datastores_needed | rejectattr('source', 'equalto', 'hypervisor.storage') | list }}"
|
||||||
|
|||||||
@@ -82,11 +82,6 @@
|
|||||||
name: "{{ hostname }}"
|
name: "{{ hostname }}"
|
||||||
folder: "{{ system_cfg.path if system_cfg.path | length > 0 else omit }}"
|
folder: "{{ system_cfg.path if system_cfg.path | length > 0 else omit }}"
|
||||||
register: system_check_vmware_check_result
|
register: system_check_vmware_check_result
|
||||||
until: >-
|
|
||||||
not system_check_vmware_check_result.failed
|
|
||||||
or (system_check_vmware_check_result.msg is search('non-existing VM'))
|
|
||||||
retries: 3
|
|
||||||
delay: 10
|
|
||||||
failed_when: false
|
failed_when: false
|
||||||
changed_when: false
|
changed_when: false
|
||||||
no_log: true
|
no_log: true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
# Raw system.content input -> expected normalized system_cfg.content. Covers family
|
# Raw system.content input -> expected normalized system_cfg.content. Covers family
|
||||||
# source defaults (rhel=dvd, else mirror), url pass-through, satellite inputs, and the
|
# source defaults (EL=dvd, else mirror), url pass-through, satellite inputs, and the
|
||||||
# Arch reflector lock-out (dropped only when a custom mirror url is set).
|
# Arch reflector lock-out (dropped only when a custom mirror url is set).
|
||||||
content_fixtures:
|
content_fixtures:
|
||||||
- name: arch-mirror-url-drops-reflector
|
- name: arch-mirror-url-drops-reflector
|
||||||
|
|||||||
Reference in New Issue
Block a user