1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
|
#+TITLE: ArchSetup Testing Infrastructure
#+AUTHOR: Craig Jennings
#+DATE: 2025-11-08
* Overview
This directory contains the complete testing infrastructure for archsetup, built on QEMU/KVM virtualization. It provides automated, reproducible testing of the archsetup installation script in isolated virtual machines.
** Philosophy
*Realism over speed.* We use full VMs (not containers) to test everything archsetup does: user creation, systemd services, X11/DWM, hardware drivers, and boot process.
* Quick Start
** One-Time Setup
#+begin_src bash
# Install required packages and configure environment
./scripts/testing/setup-testing-env.sh
# Log out and back in (for libvirt group membership)
# Create the base VM (minimal Arch installation)
./scripts/testing/create-base-vm.sh
# Follow on-screen instructions to complete installation
# Run finalize-base-vm.sh when done
#+end_src
** Run a Test
#+begin_src bash
# Test the current archsetup script
./scripts/testing/run-test.sh
# Test a specific version
./scripts/testing/run-test.sh --script /path/to/archsetup
# Keep VM running for debugging
./scripts/testing/run-test.sh --keep
#+end_src
** Debug Interactively
#+begin_src bash
# Clone base VM for debugging
./scripts/testing/debug-vm.sh
# Use existing test disk
./scripts/testing/debug-vm.sh test-results/20251108-143000/test.qcow2
# Use base VM (read-only)
./scripts/testing/debug-vm.sh --base
#+end_src
** Clean Up
#+begin_src bash
# Interactive cleanup (prompts for confirmation)
./scripts/testing/cleanup-tests.sh
# Keep last 10 test results
./scripts/testing/cleanup-tests.sh --keep 10
# Force cleanup without prompts
./scripts/testing/cleanup-tests.sh --force
#+end_src
* Scripts
** setup-testing-env.sh
*Purpose:* One-time setup of testing infrastructure
*What it does:*
- Installs QEMU/KVM, libvirt, and related tools
- Configures libvirt networking
- Adds user to libvirt group
- Verifies KVM support
- Creates directories for artifacts
*When to run:* Once per development machine
*Usage:*
#+begin_src bash
./scripts/testing/setup-testing-env.sh
#+end_src
** create-base-vm.sh
*Purpose:* Create the "golden image" minimal Arch VM
*What it does:*
- Downloads latest Arch ISO
- Creates VM and boots from ISO
- Opens virt-viewer for you to complete installation manually
*When to run:* Once (or when you want to refresh base image)
*Usage:*
#+begin_src bash
./scripts/testing/create-base-vm.sh
#+end_src
*Process:*
1. Script creates VM and boots from Arch ISO
2. virt-viewer opens automatically showing VM display
3. You complete installation manually using archinstall:
- Login as root (no password)
- Run =archinstall=
- Configure: hostname=archsetup-test, root password=archsetup
- Install packages: openssh git vim sudo
- Enable services: sshd, dhcpcd
- Configure SSH to allow root login
- Poweroff when done
4. Run =./scripts/testing/finalize-base-vm.sh= to complete
*See also:* [[file:../../docs/base-vm-installation-checklist.org][Base VM Installation Checklist]]
*Result:* Base VM image at =vm-images/archsetup-base.qcow2=
** run-test.sh
*Purpose:* Execute a full test run of archsetup
*What it does:*
- Clones base VM (copy-on-write, fast)
- Starts test VM
- Transfers archsetup script and dotfiles
- Executes archsetup inside VM
- Captures logs and results
- Runs validation checks
- Generates test report
- Cleans up (unless =--keep=)
*When to run:* Every time you want to test archsetup
*Usage:*
#+begin_src bash
# Test current archsetup
./scripts/testing/run-test.sh
# Test specific version
./scripts/testing/run-test.sh --script /path/to/archsetup
# Keep VM for debugging
./scripts/testing/run-test.sh --keep
#+end_src
*Time:* 30-60 minutes (mostly downloading packages)
*Results:* Saved to =test-results/TIMESTAMP/=
- =test.log= - Complete log output
- =test-report.txt= - Summary of results
- =archsetup-*.log= - Log from archsetup script
- =*.txt= - Package lists from VM
** debug-vm.sh
*Purpose:* Launch VM for interactive debugging
*What it does:*
- Creates VM from base image or existing test disk
- Configures console and SSH access
- Provides connection instructions
*When to run:* When you need to manually test or debug
*Usage:*
#+begin_src bash
# Clone base VM for debugging
./scripts/testing/debug-vm.sh
# Use existing test disk
./scripts/testing/debug-vm.sh vm-images/archsetup-test-20251108-143000.qcow2
# Use base VM (read-only)
./scripts/testing/debug-vm.sh --base
#+end_src
*Connect via:*
- Console: =virsh console archsetup-debug-TIMESTAMP=
- SSH: =ssh root@IP_ADDRESS= (password: archsetup)
- VNC: =virt-viewer archsetup-debug-TIMESTAMP=
** cleanup-tests.sh
*Purpose:* Clean up old test VMs and artifacts
*What it does:*
- Lists all test VMs and destroys them
- Removes test disk images
- Keeps last N test results, deletes rest
*When to run:* Periodically to free disk space
*Usage:*
#+begin_src bash
# Interactive cleanup
./scripts/testing/cleanup-tests.sh
# Keep last 3 test results
./scripts/testing/cleanup-tests.sh --keep 3
# Force without prompts
./scripts/testing/cleanup-tests.sh --force
#+end_src
* Directory Structure
#+begin_example
archsetup/
├── scripts/
│ └── testing/
│ ├── README.org # This file
│ ├── setup-testing-env.sh # Setup infrastructure
│ ├── create-base-vm.sh # Create base VM
│ ├── run-test.sh # Run tests
│ ├── debug-vm.sh # Interactive debugging
│ ├── cleanup-tests.sh # Clean up
│ ├── finalize-base-vm.sh # Finalize base (generated)
│ ├── archinstall-config.json # Archinstall config
│ └── lib/
│ ├── logging.sh # Logging utilities
│ └── vm-utils.sh # VM management
├── vm-images/ # VM disk images (gitignored)
│ ├── archsetup-base.qcow2 # Golden image
│ ├── arch-latest.iso # Arch ISO
│ └── archsetup-test-*.qcow2 # Test VMs
├── test-results/ # Test results (gitignored)
│ ├── TIMESTAMP/
│ │ ├── test.log
│ │ ├── test-report.txt
│ │ └── archsetup-*.log
│ └── latest -> TIMESTAMP/ # Symlink to latest
└── docs/
└── testing-strategy.org # Complete strategy doc
#+end_example
* Configuration
** VM Specifications
All test VMs use:
- *CPUs:* 2 vCPUs
- *RAM:* 4GB (matches archsetup tmpfs build directory)
- *Disk:* 50GB (thin provisioned qcow2)
- *Network:* NAT via libvirt default network
- *Boot:* UEFI (systemd-boot bootloader)
- *Display:* Serial console + VNC
Set environment variables to customize:
#+begin_src bash
VM_CPUS=4 VM_RAM=8192 ./scripts/testing/run-test.sh
#+end_src
** Base VM Specifications
The base VM contains a minimal Arch installation:
- Base system packages
- Linux kernel and firmware
- OpenSSH server (for automation)
- dhcpcd (for networking)
- git, vim, sudo (essentials)
- Root password: "archsetup"
This matches the documented prerequisites for archsetup.
* Validation Checks
Each test run performs these validation checks:
** Critical (Must Pass)
1. archsetup exits with code 0
2. User 'cjennings' was created
3. Dotfiles are stowed (symlinks exist)
4. yay (AUR helper) is installed
5. DWM is built and installed
** Additional (Future)
- All expected packages installed
- X11 can start
- systemd services enabled
- Firewall configured
* Troubleshooting
** VM fails to start
Check if libvirtd is running:
#+begin_src bash
sudo systemctl status libvirtd
sudo systemctl start libvirtd
#+end_src
** Cannot get VM IP address
The VM may not have booted completely or networking failed:
#+begin_src bash
# Check VM status
virsh domstate VM_NAME
# Connect to console to debug
virsh console VM_NAME
# Check if dhcpcd is running in VM
systemctl status dhcpcd
#+end_src
** SSH connection refused
Wait longer for VM to boot, or check if sshd is enabled:
#+begin_src bash
virsh console VM_NAME
# Inside VM:
systemctl status sshd
systemctl start sshd
#+end_src
** KVM not available
Check if virtualization is enabled in BIOS and KVM modules loaded:
#+begin_src bash
# Check for /dev/kvm
ls -l /dev/kvm
# Load KVM module (Intel)
sudo modprobe kvm-intel
# Or for AMD
sudo modprobe kvm-amd
# Verify
lsmod | grep kvm
#+end_src
** Disk space issues
Clean up old tests:
#+begin_src bash
./scripts/testing/cleanup-tests.sh --force
#+end_src
Check disk usage:
#+begin_src bash
du -sh vm-images/ test-results/
#+end_src
** Base VM Installation Issues
*** Firewall blocking VM network
If the VM cannot reach the internet (100% packet loss when pinging), check the host firewall:
#+begin_src bash
# Check UFW status on host
sudo ufw status
# Check libvirt NAT rules on host
sudo iptables -t nat -L -n -v | grep -i libvirt
#+end_src
*Solution:* Temporarily disable UFW during base VM creation:
#+begin_src bash
sudo ufw disable
# Create base VM
sudo ufw enable
#+end_src
Or add libvirt rules to UFW:
#+begin_src bash
sudo ufw allow in on virbr0
sudo ufw allow out on virbr0
#+end_src
*** VM network not working after boot
If =dhcpcd= isn't running or network isn't configured:
#+begin_src bash
# In the VM - restart network from scratch
killall dhcpcd
# Bring interface down and up (replace enp1s0 with your interface)
ip link set enp1s0 down
ip link set enp1s0 up
# Start dhcpcd
dhcpcd enp1s0
# Wait and verify
sleep 3
ip addr show enp1s0
ip route
# Test connectivity
ping -c 3 192.168.122.1 # Gateway
ping -c 3 8.8.8.8 # Google DNS
#+end_src
*** DNS not working (127.0.0.53 in resolv.conf)
The Live ISO uses systemd-resolved stub resolver which may not work:
#+begin_src bash
# In the VM - set real DNS servers
echo "nameserver 8.8.8.8" > /etc/resolv.conf
echo "nameserver 1.1.1.1" >> /etc/resolv.conf
# Test
ping -c 3 archlinux.org
#+end_src
*** Cannot paste into virt-viewer terminal
Clipboard integration doesn't work well with virt-viewer. Use HTTP server instead:
#+begin_src bash
# On host - serve the installation script
cd vm-images
python -m http.server 8000
# In VM - download and run
curl http://192.168.122.1:8000/auto-install.sh | bash
# Or download first to review
curl http://192.168.122.1:8000/auto-install.sh -o install.sh
cat install.sh
bash install.sh
#+end_src
*** Partitions "in use" error
If re-running installation after a failed attempt:
#+begin_src bash
# In the VM - unmount and wipe partitions
mount | grep vda
umount /mnt/boot 2>/dev/null
umount /mnt 2>/dev/null
umount -l /mnt # Lazy unmount if still busy
# Wipe partition table completely
wipefs -a /dev/vda
# Run install script again
bash install.sh
#+end_src
*** Alternative: Use archinstall
Instead of the auto-install.sh script, you can use Arch's built-in installer:
#+begin_src bash
# In the VM
archinstall
#+end_src
*Recommended settings:*
- Disk: =/dev/vda=
- Filesystem: =ext4=
- Bootloader: =systemd-boot=
- Hostname: =archsetup-test=
- Root password: =archsetup=
- Profile: =minimal=
- Additional packages: =openssh dhcpcd git vim sudo=
- Network: =NetworkManager= or =systemd-networkd=
*After installation, before rebooting:*
#+begin_src bash
# Chroot into new system
arch-chroot /mnt
# Enable services
systemctl enable sshd
systemctl enable dhcpcd # or NetworkManager
# Allow root SSH login
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
# Exit and poweroff
exit
poweroff
#+end_src
* Future Enhancements
** Planned Improvements
- [ ] Fully automated base VM creation (expect-based console automation)
- [ ] Parallel test execution (multiple VMs)
- [ ] Screenshot capture of X11 desktop
- [ ] CI/CD integration (GitHub Actions / GitLab CI)
- [ ] Performance benchmarking over time
- [ ] Cloud-init based base image (faster provisioning)
** Test Scenarios
- [ ] Idempotency test (run archsetup twice)
- [ ] Network failure recovery
- [ ] Offline installation (local package cache)
- [ ] Different hardware profiles (CPU/RAM variations)
* References
- [[file:../../docs/testing-strategy.org][Testing Strategy Document]]
- [[https://wiki.archlinux.org/title/Libvirt][Arch Wiki: libvirt]]
- [[https://wiki.archlinux.org/title/QEMU][Arch Wiki: QEMU]]
- [[file:../../archsetup][Main archsetup script]]
- [[file:../../TODO.org][Project TODO]]
|