feat(hardware): auto-detect audio, bluetooth, camera with declarative override
This commit is contained in:
24
tests/hardware/_assert_fixture.yml
Normal file
24
tests/hardware/_assert_fixture.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
- name: "Seed lscpu/lspci/lsusb registers ({{ fixture.name }})"
|
||||
ansible.builtin.set_fact:
|
||||
_hardware_lscpu: { stdout: "{{ fixture.lscpu }}" }
|
||||
_hardware_lspci: { stdout: "{{ fixture.lspci | join('\n') }}", stdout_lines: "{{ fixture.lspci }}" }
|
||||
_hardware_lsusb: { stdout: "{{ fixture.lsusb }}" }
|
||||
|
||||
- name: "Resolve hardware profile ({{ fixture.name }})"
|
||||
ansible.builtin.include_tasks: ../../roles/environment/tasks/_resolve_hardware_profile.yml
|
||||
|
||||
- name: "Assert resolved profile ({{ fixture.name }})"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- hardware_profile_active.cpu == fixture.expect.cpu
|
||||
- hardware_profile_active.gpus == fixture.expect.gpus
|
||||
- hardware_profile_active.wireless == fixture.expect.wireless
|
||||
- hardware_profile_active.audio == fixture.expect.audio
|
||||
- (hardware_profile_active.fingerprint | bool) == (fixture.expect.fingerprint | bool)
|
||||
- (hardware_profile_active.bluetooth | bool) == (fixture.expect.bluetooth | bool)
|
||||
- (hardware_profile_active.camera.uvc | bool) == (fixture.expect.camera.uvc | bool)
|
||||
- (hardware_profile_active.camera.ipu6 | bool) == (fixture.expect.camera.ipu6 | bool)
|
||||
- (hardware_profile_active.nvidia_supports_open | bool) == (fixture.expect.nvidia_supports_open | bool)
|
||||
fail_msg: "[{{ fixture.name }}] FAIL got {{ hardware_profile_active }}"
|
||||
success_msg: "[{{ fixture.name }}] OK {{ hardware_profile_active }}"
|
||||
44
tests/hardware/_assert_merge.yml
Normal file
44
tests/hardware/_assert_merge.yml
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
- name: "Seed detection + declarative group (merge {{ mf.name }})"
|
||||
ansible.builtin.set_fact:
|
||||
hardware_profile_active: "{{ mf.detected }}"
|
||||
os_family: "{{ mf.os_family }}"
|
||||
_nvidia_driver_resolved: "{{ mf.nvidia_driver_resolved | default('nouveau') }}"
|
||||
system_cfg:
|
||||
features:
|
||||
firmware: { enabled: true, microcode: true }
|
||||
gpu: { enabled: true }
|
||||
peripherals:
|
||||
enabled: true
|
||||
camera: "auto"
|
||||
fingerprint: "auto"
|
||||
audio: "auto"
|
||||
bluetooth: "auto"
|
||||
displaylink: false
|
||||
hardware: "{{ mf.hardware }}"
|
||||
|
||||
- name: "Merge group over detection (merge {{ mf.name }})"
|
||||
ansible.builtin.include_tasks: ../../roles/environment/tasks/_merge_hardware_profile.yml
|
||||
|
||||
- name: "Assert merged profile (merge {{ mf.name }})"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- (hardware_profile_active.fingerprint | bool) == (mf.expect_profile.fingerprint | bool)
|
||||
- (hardware_profile_active.bluetooth | bool) == (mf.expect_profile.bluetooth | bool)
|
||||
- _hardware_profile_kernel_params == (mf.hardware.kernel_params | default([]))
|
||||
fail_msg: "[merge {{ mf.name }}] profile FAIL {{ hardware_profile_active }}"
|
||||
|
||||
- name: "Load package map (merge {{ mf.name }})"
|
||||
ansible.builtin.include_vars:
|
||||
file: ../../roles/bootstrap/vars/hardware.yml
|
||||
|
||||
- name: "Resolve packages (merge {{ mf.name }})"
|
||||
ansible.builtin.include_tasks: ../../roles/bootstrap/tasks/_resolve_hardware_packages.yml
|
||||
|
||||
- name: "Assert resolved package list (merge {{ mf.name }})"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- (mf.expect_contains | default([])) | difference(_hardware_packages) | length == 0
|
||||
- (mf.expect_excludes | default([])) | intersect(_hardware_packages) | length == 0
|
||||
fail_msg: "[merge {{ mf.name }}] FAIL got {{ _hardware_packages }}"
|
||||
success_msg: "[merge {{ mf.name }}] OK {{ _hardware_packages }}"
|
||||
32
tests/hardware/_assert_packages.yml
Normal file
32
tests/hardware/_assert_packages.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
- name: "Seed resolve inputs (pkg {{ pf.name }})"
|
||||
ansible.builtin.set_fact:
|
||||
os_family: "{{ pf.os_family }}"
|
||||
hardware_profile_active: "{{ pf.profile }}"
|
||||
_nvidia_driver_resolved: "{{ pf.nvidia_driver_resolved | default('nouveau') }}"
|
||||
system_cfg:
|
||||
features:
|
||||
firmware: { enabled: true, microcode: true }
|
||||
gpu: { enabled: true }
|
||||
peripherals:
|
||||
enabled: true
|
||||
camera: "auto"
|
||||
fingerprint: "auto"
|
||||
audio: "auto"
|
||||
bluetooth: "auto"
|
||||
displaylink: false
|
||||
|
||||
- name: "Load package map (pkg {{ pf.name }})"
|
||||
ansible.builtin.include_vars:
|
||||
file: ../../roles/bootstrap/vars/hardware.yml
|
||||
|
||||
- name: "Resolve packages (pkg {{ pf.name }})"
|
||||
ansible.builtin.include_tasks: ../../roles/bootstrap/tasks/_resolve_hardware_packages.yml
|
||||
|
||||
- name: "Assert resolved package list (pkg {{ pf.name }})"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- (pf.expect_contains | default([])) | difference(_hardware_packages) | length == 0
|
||||
- (pf.expect_excludes | default([])) | intersect(_hardware_packages) | length == 0
|
||||
fail_msg: "[pkg {{ pf.name }}] FAIL got {{ _hardware_packages }}"
|
||||
success_msg: "[pkg {{ pf.name }}] OK {{ _hardware_packages }}"
|
||||
41
tests/hardware/fixtures.yml
Normal file
41
tests/hardware/fixtures.yml
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
# Canned lscpu/lspci/lsusb -> expected profile. lspci lines are `lspci -nn` shaped,
|
||||
# lsusb is plain `lsusb`.
|
||||
hardware_fixtures:
|
||||
- name: intel-laptop-nvidia-turing
|
||||
lscpu: "Architecture: x86_64\nVendor ID: GenuineIntel\nModel name: 12th Gen Core i7"
|
||||
lspci:
|
||||
- "00:02.0 VGA compatible controller [0300]: Intel Corporation Alder Lake-P GT2 [8086:46a6] (rev 0c)"
|
||||
- "01:00.0 3D controller [0302]: NVIDIA Corporation TU117M [GeForce GTX 1650 Mobile] [10de:1f99] (rev a1)"
|
||||
- "00:14.3 Network controller [0280]: Intel Corporation Wi-Fi 6 AX201 [8086:a0f0] (rev 11)"
|
||||
- "00:1f.3 Audio device [0403]: Intel Corporation Alder Lake PCH-P High Definition Audio [8086:51c8] (rev 01)"
|
||||
lsusb: |-
|
||||
Bus 001 Device 003: ID 06cb:00bd Synaptics, Inc. Prometheus MIS Touch Fingerprint Reader
|
||||
Bus 001 Device 004: ID 8087:0026 Intel Corp. AX201 Bluetooth
|
||||
Bus 001 Device 005: ID 5986:118d Acer, Inc. Integrated Camera
|
||||
expect: { cpu: intel, gpus: [intel, nvidia], nvidia_supports_open: true, wireless: [intel], audio: [intel], fingerprint: true, bluetooth: true, camera: { uvc: true, ipu6: false } }
|
||||
|
||||
- name: amd-desktop-realtek
|
||||
lscpu: "Architecture: x86_64\nVendor ID: AuthenticAMD\nModel name: AMD Ryzen 7 5800X"
|
||||
lspci:
|
||||
- "0a:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Navi 22 [1002:73df] (rev c7)"
|
||||
- "05:00.0 Network controller [0280]: Realtek Semiconductor Co., Ltd. RTL8822CE 802.11ac [10ec:c822]"
|
||||
- "0b:00.4 Audio device [0403]: Advanced Micro Devices, Inc. [AMD] Starship/Matisse HD Audio [1022:1487]"
|
||||
lsusb: "Bus 002 Device 002: ID 046d:c52b Logitech, Inc. Unifying Receiver"
|
||||
expect: { cpu: amd, gpus: [amd], nvidia_supports_open: false, wireless: [realtek], audio: [amd], fingerprint: false, bluetooth: false, camera: { uvc: false, ipu6: false } }
|
||||
|
||||
- name: nvidia-legacy-maxwell
|
||||
lscpu: "Vendor ID: GenuineIntel"
|
||||
lspci:
|
||||
- "01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM107 [GeForce GTX 750 Ti] [10de:1380] (rev a2)"
|
||||
lsusb: ""
|
||||
expect: { cpu: intel, gpus: [nvidia], nvidia_supports_open: false, wireless: [], audio: [], fingerprint: false, bluetooth: false, camera: { uvc: false, ipu6: false } }
|
||||
|
||||
- name: intel-laptop-ipu6-camera
|
||||
lscpu: "Vendor ID: GenuineIntel"
|
||||
lspci:
|
||||
- "00:02.0 VGA compatible controller [0300]: Intel Corporation Raptor Lake-P [8086:a7a0] (rev 04)"
|
||||
- "00:05.0 Multimedia controller [0480]: Intel Corporation Raptor Lake IPU6 [8086:a75d] (rev 04)"
|
||||
- "00:14.3 Network controller [0280]: Intel Corporation Wi-Fi 6E AX211 [8086:51f0]"
|
||||
lsusb: "Bus 003 Device 002: ID 8087:0033 Intel Corp. AX211 Bluetooth"
|
||||
expect: { cpu: intel, gpus: [intel], nvidia_supports_open: false, wireless: [intel], audio: [], fingerprint: false, bluetooth: true, camera: { uvc: false, ipu6: true } }
|
||||
37
tests/hardware/merge_fixtures.yml
Normal file
37
tests/hardware/merge_fixtures.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
# Detected profile + declarative hardware.* -> merged profile + resolved packages.
|
||||
# Exercises union/OR/force-on, disable[] force-off, and packages[os_family] append.
|
||||
merge_fixtures:
|
||||
- name: force-fingerprint-disable-audio-pin-ipu6
|
||||
os_family: Archlinux
|
||||
nvidia_driver_resolved: nouveau
|
||||
detected: { cpu: intel, gpus: [intel], nvidia_supports_open: true, wireless: [intel], audio: [intel], fingerprint: false, bluetooth: false, camera: { uvc: false, ipu6: true } }
|
||||
hardware:
|
||||
fingerprint: true # force-on (detection missed it)
|
||||
packages: { Archlinux: [intel-ipu6-dkms, v4l2-relayd] }
|
||||
disable: [audio] # force-off audio even though detected
|
||||
kernel_params: ["i915.enable_psr=0"]
|
||||
expect_profile: { fingerprint: true, bluetooth: false }
|
||||
expect_contains: [intel-ipu6-dkms, v4l2-relayd, fprintd, libfprint, v4l-utils, intel-ucode]
|
||||
expect_excludes: [sof-firmware, alsa-ucm-conf, bluez]
|
||||
|
||||
- name: union-vendors-force-bluetooth
|
||||
os_family: Debian
|
||||
nvidia_driver_resolved: nouveau
|
||||
detected: { cpu: amd, gpus: [amd], nvidia_supports_open: false, wireless: [], audio: [amd], fingerprint: false, bluetooth: false, camera: { uvc: false, ipu6: false } }
|
||||
hardware:
|
||||
wireless: [realtek] # union: add a wireless vendor detection missed
|
||||
bluetooth: true # force-on bluetooth
|
||||
expect_profile: { fingerprint: false, bluetooth: true }
|
||||
expect_contains: [amd64-microcode, firmware-realtek, firmware-sof-signed, bluez]
|
||||
expect_excludes: [fprintd, v4l-utils]
|
||||
|
||||
- name: disable-vendor-drops-microcode-firmware-gpu
|
||||
os_family: Archlinux
|
||||
nvidia_driver_resolved: open
|
||||
detected: { cpu: intel, gpus: [intel, nvidia], nvidia_supports_open: true, wireless: [intel], audio: [intel], fingerprint: false, bluetooth: false, camera: { uvc: false, ipu6: false } }
|
||||
hardware:
|
||||
disable: [nvidia, intel] # drop the nvidia GPU and every intel-vendor contribution
|
||||
expect_profile: { fingerprint: false, bluetooth: false }
|
||||
expect_contains: [mesa, vulkan-icd-loader]
|
||||
expect_excludes: [nvidia-open-dkms, intel-ucode, vulkan-intel, sof-firmware, linux-firmware-other]
|
||||
22
tests/hardware/pkg_fixtures.yml
Normal file
22
tests/hardware/pkg_fixtures.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
# profile + os_family -> resolved package list. expect_contains: all must be present;
|
||||
# expect_excludes: none may be present. Features default all-on with auto peripherals.
|
||||
package_fixtures:
|
||||
- name: arch-intel-audio-bt-fp
|
||||
os_family: Archlinux
|
||||
profile: { cpu: intel, gpus: [intel], wireless: [intel], audio: [intel], fingerprint: true, bluetooth: true, camera: { uvc: true, ipu6: false } }
|
||||
expect_contains: [intel-ucode, linux-firmware-other, mesa, vulkan-icd-loader, vulkan-intel, sof-firmware, alsa-ucm-conf, bluez, bluez-utils, fprintd, libfprint, v4l-utils]
|
||||
expect_excludes: [nvidia-open-dkms, evdi]
|
||||
|
||||
- name: debian-amd-audio-no-bt-no-fp
|
||||
os_family: Debian
|
||||
profile: { cpu: amd, gpus: [amd], wireless: [realtek], audio: [amd], fingerprint: false, bluetooth: false, camera: { uvc: false, ipu6: false } }
|
||||
expect_contains: [amd64-microcode, firmware-linux-free, firmware-amd-graphics, firmware-realtek, mesa-vulkan-drivers, firmware-sof-signed, alsa-ucm-conf]
|
||||
expect_excludes: [bluez, fprintd, libpam-fprintd, v4l-utils]
|
||||
|
||||
- name: redhat-intel-nvidia-bt
|
||||
os_family: RedHat
|
||||
profile: { cpu: intel, gpus: [intel, nvidia], wireless: [intel], audio: [intel], fingerprint: false, bluetooth: true, camera: { uvc: false, ipu6: true } }
|
||||
nvidia_driver_resolved: open
|
||||
expect_contains: [microcode_ctl, linux-firmware, mesa-dri-drivers, vulkan-loader, akmod-nvidia-open, alsa-sof-firmware, alsa-ucm, bluez, v4l-utils]
|
||||
expect_excludes: [fprintd, evdi]
|
||||
16
tests/hardware/test_detection.yml
Normal file
16
tests/hardware/test_detection.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
# Run: ansible-playbook tests/hardware/test_detection.yml
|
||||
- name: Hardware detection fixture tests
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
connection: local
|
||||
vars_files:
|
||||
- ../../roles/environment/defaults/main.yml
|
||||
- fixtures.yml
|
||||
tasks:
|
||||
- name: Run each detection fixture
|
||||
ansible.builtin.include_tasks: _assert_fixture.yml
|
||||
loop: "{{ hardware_fixtures }}"
|
||||
loop_control:
|
||||
loop_var: fixture
|
||||
label: "{{ fixture.name }}"
|
||||
15
tests/hardware/test_merge.yml
Normal file
15
tests/hardware/test_merge.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
# Run: ansible-playbook tests/hardware/test_merge.yml
|
||||
- name: Hardware merge-layer fixture tests
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
connection: local
|
||||
vars_files:
|
||||
- merge_fixtures.yml
|
||||
tasks:
|
||||
- name: Run each merge fixture
|
||||
ansible.builtin.include_tasks: _assert_merge.yml
|
||||
loop: "{{ merge_fixtures }}"
|
||||
loop_control:
|
||||
loop_var: mf
|
||||
label: "{{ mf.name }}"
|
||||
15
tests/hardware/test_packages.yml
Normal file
15
tests/hardware/test_packages.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
# Run: ansible-playbook tests/hardware/test_packages.yml
|
||||
- name: Hardware package-resolution fixture tests
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
connection: local
|
||||
vars_files:
|
||||
- pkg_fixtures.yml
|
||||
tasks:
|
||||
- name: Run each package fixture
|
||||
ansible.builtin.include_tasks: _assert_packages.yml
|
||||
loop: "{{ package_fixtures }}"
|
||||
loop_control:
|
||||
loop_var: pf
|
||||
label: "{{ pf.name }}"
|
||||
Reference in New Issue
Block a user