blob: a600870c94d338621293b7da5e5ba3a5ac1983ef (
plain)
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
|
#!/bin/bash
# Run archsetup test in a VM using snapshots
# Author: Craig Jennings <craigmartinjennings@gmail.com>
# License: GNU GPLv3
#
# This script:
# 1. Reverts base VM to clean snapshot
# 2. Boots the VM via QEMU
# 3. Transfers archsetup and dotfiles
# 4. Executes archsetup in the VM
# 5. Captures logs and validates results
# 6. Generates test report
# 7. Reverts to clean snapshot for next run
set -e
# Get script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Source utilities
source "$SCRIPT_DIR/lib/logging.sh"
source "$SCRIPT_DIR/lib/vm-utils.sh"
source "$SCRIPT_DIR/lib/network-diagnostics.sh"
source "$SCRIPT_DIR/lib/validation.sh"
# Parse arguments
KEEP_VM=false
ARCHSETUP_SCRIPT="$PROJECT_ROOT/archsetup"
SNAPSHOT_NAME="clean-install"
while [[ $# -gt 0 ]]; do
case $1 in
--keep)
KEEP_VM=true
shift
;;
--script)
ARCHSETUP_SCRIPT="$2"
shift 2
;;
--snapshot)
SNAPSHOT_NAME="$2"
shift 2
;;
*)
echo "Usage: $0 [--keep] [--script /path/to/archsetup] [--snapshot name]"
echo " --keep Keep VM in post-test state (for debugging)"
echo " --script Specify custom archsetup script to test"
echo " --snapshot Snapshot name to revert to (default: clean-install)"
exit 1
;;
esac
done
# Configuration
TIMESTAMP=$(date +'%Y%m%d-%H%M%S')
VM_IMAGES_DIR="$PROJECT_ROOT/vm-images"
TEST_RESULTS_DIR="$PROJECT_ROOT/test-results/$TIMESTAMP"
ROOT_PASSWORD="archsetup"
ARCHZFS_INBOX="$HOME/code/archzfs/inbox"
ARCHSETUP_VM_CONF="$SCRIPT_DIR/archsetup-vm.conf"
# Set VM_IP for validation.sh backward compatibility
VM_IP="localhost"
# Initialize logging and VM paths
mkdir -p "$TEST_RESULTS_DIR"
LOGFILE="$TEST_RESULTS_DIR/test.log"
init_logging "$LOGFILE"
init_vm_paths "$VM_IMAGES_DIR"
section "ArchSetup Test Run: $TIMESTAMP"
# Verify archsetup script exists
if [ ! -f "$ARCHSETUP_SCRIPT" ]; then
fatal "ArchSetup script not found: $ARCHSETUP_SCRIPT"
fi
# Check disk exists
if [ ! -f "$DISK_PATH" ]; then
fatal "Base disk not found: $DISK_PATH"
info "Create it first: ./scripts/testing/create-base-vm.sh"
fi
# Check if snapshot exists
section "Preparing Test Environment"
step "Checking for snapshot: $SNAPSHOT_NAME"
if ! snapshot_exists "$DISK_PATH" "$SNAPSHOT_NAME"; then
fatal "Snapshot '$SNAPSHOT_NAME' not found on $DISK_PATH"
info "Available snapshots:"
list_snapshots "$DISK_PATH"
info ""
info "Create base VM with: ./scripts/testing/create-base-vm.sh"
fi
success "Snapshot $SNAPSHOT_NAME exists"
# Stop VM if running and restore snapshot
stop_qemu 2>/dev/null || true
step "Reverting to snapshot: $SNAPSHOT_NAME"
if restore_snapshot "$DISK_PATH" "$SNAPSHOT_NAME"; then
success "Reverted to clean state"
else
fatal "Failed to revert snapshot"
fi
# Start VM and wait for SSH
start_timer "boot"
step "Starting VM and waiting for SSH..."
start_qemu "$DISK_PATH" "disk" "" "none" || fatal "Failed to start VM"
wait_for_ssh "$ROOT_PASSWORD" 120 || fatal "VM SSH not available"
stop_timer "boot"
# Run network diagnostics
if ! run_network_diagnostics; then
fatal "Network diagnostics failed - aborting test"
fi
# Capture pre-install state for comparison
capture_pre_install_state "$TEST_RESULTS_DIR"
# Transfer files to VM (simulating git clone)
section "Simulating Git Clone"
step "Creating shallow git clone on VM"
info "This simulates: git clone --depth 1 <repo> /home/cjennings/code/archsetup"
# Create a temporary git bundle from current repo
BUNDLE_FILE=$(mktemp)
git bundle create "$BUNDLE_FILE" HEAD >> "$LOGFILE" 2>&1
# Transfer bundle and extract on VM
vm_exec "$ROOT_PASSWORD" "rm -rf /tmp/archsetup-test && mkdir -p /tmp/archsetup-test" >> "$LOGFILE" 2>&1
copy_to_vm "$BUNDLE_FILE" "/tmp/archsetup.bundle" "$ROOT_PASSWORD"
# Clone from bundle on VM (simulates git clone)
vm_exec "$ROOT_PASSWORD" \
"cd /tmp && git clone --depth 1 /tmp/archsetup.bundle archsetup-test && rm /tmp/archsetup.bundle" \
>> "$LOGFILE" 2>&1
rm -f "$BUNDLE_FILE"
success "Repository cloned to VM (simulating git clone --depth 1)"
# Transfer archsetup VM config file
step "Copying archsetup VM config"
copy_to_vm "$ARCHSETUP_VM_CONF" "/tmp/archsetup-test/archsetup-vm.conf" "$ROOT_PASSWORD"
# Pre-archsetup VM setup
section "Pre-ArchSetup VM Setup"
step "Importing archzfs PGP key"
vm_exec "$ROOT_PASSWORD" \
"curl -sL https://archzfs.com/archzfs.gpg | pacman-key --add - && pacman-key --lsign-key DDF7DB817396A49B2A2723F7403BD972F75D9D76" \
>> "$LOGFILE" 2>&1 && success "archzfs PGP key imported" || warn "Failed to import archzfs key (may already be present)"
step "Syncing package databases"
vm_exec "$ROOT_PASSWORD" "pacman -Sy --noconfirm" >> "$LOGFILE" 2>&1 && \
success "Package databases synced" || warn "Package database sync had issues"
# Execute archsetup
section "Executing ArchSetup"
start_timer "archsetup"
step "Starting archsetup script in detached session on VM..."
info "Log file: $LOGFILE"
# Start archsetup fully detached.
# Use ssh -T -n to prevent PTY allocation and stdin forwarding, which allows
# the SSH session to close immediately after the remote shell exits.
REMOTE_LOG="/tmp/archsetup-test/archsetup-output.log"
sshpass -p "$ROOT_PASSWORD" ssh -T -n $SSH_OPTS \
-p "$SSH_PORT" root@localhost \
"setsid bash -c 'cd /tmp/archsetup-test && bash archsetup --config-file /tmp/archsetup-test/archsetup-vm.conf > $REMOTE_LOG 2>&1' < /dev/null > /dev/null 2>&1 &" \
>> "$LOGFILE" 2>&1
# Verify the process started
sleep 3
if vm_exec "$ROOT_PASSWORD" "pgrep -f 'bash archsetup'" >> "$LOGFILE" 2>/dev/null; then
success "ArchSetup started in background on VM"
else
fatal "ArchSetup process not found after launch"
fi
# Poll for completion
step "Monitoring archsetup progress (polling every 30 seconds)..."
POLL_COUNT=0
MAX_POLLS=180 # 90 minutes max (180 * 30 seconds)
while [ $POLL_COUNT -lt $MAX_POLLS ]; do
# Check if archsetup process is still running
if vm_exec "$ROOT_PASSWORD" "ps aux | grep '[b]ash archsetup' > /dev/null" 2>/dev/null; then
# Still running, wait and continue
sleep 30
POLL_COUNT=$((POLL_COUNT + 1))
# Show progress every 5 minutes
if [ $((POLL_COUNT % 10)) -eq 0 ]; then
ELAPSED_MINS=$((POLL_COUNT / 2))
info "Still running... ($ELAPSED_MINS minutes elapsed)"
fi
else
# Process finished
break
fi
done
if [ $POLL_COUNT -ge $MAX_POLLS ]; then
error "ArchSetup timed out after 90 minutes"
ARCHSETUP_EXIT_CODE=124
else
# Get exit code from the remote log
step "Retrieving archsetup exit status..."
ARCHSETUP_EXIT_CODE=$(vm_exec "$ROOT_PASSWORD" \
"grep -q 'ARCHSETUP_EXECUTION_COMPLETE' /var/log/archsetup-*.log 2>/dev/null && echo 0 || echo 1" \
2>/dev/null)
if [ "$ARCHSETUP_EXIT_CODE" = "0" ]; then
success "ArchSetup completed successfully"
else
error "ArchSetup may have encountered errors (check logs)"
fi
fi
# Copy the remote output log
step "Retrieving archsetup output from VM..."
copy_from_vm "$REMOTE_LOG" "$TEST_RESULTS_DIR/archsetup-output.log" "$ROOT_PASSWORD" || \
warn "Could not copy remote output log"
# Append remote output to main test log
if [ -f "$TEST_RESULTS_DIR/archsetup-output.log" ]; then
cat "$TEST_RESULTS_DIR/archsetup-output.log" >> "$LOGFILE"
fi
stop_timer "archsetup"
# Capture logs and artifacts from VM
section "Capturing Test Artifacts"
step "Copying archsetup log from VM"
copy_from_vm "/var/log/archsetup-*.log" "$TEST_RESULTS_DIR/" "$ROOT_PASSWORD" || \
warn "Could not copy archsetup log"
step "Copying package lists from VM"
copy_from_vm "/var/log/archsetup-*-package-list.txt" "$TEST_RESULTS_DIR/" "$ROOT_PASSWORD" || \
warn "Could not copy package lists"
step "Copying installed packages list"
copy_from_vm "/var/log/archsetup-installed-packages.txt" "$TEST_RESULTS_DIR/" "$ROOT_PASSWORD" || \
warn "Could not copy installed packages list"
# Capture post-install state
capture_post_install_state "$TEST_RESULTS_DIR"
# Run comprehensive validation
# This uses the validation.sh library for all checks
run_all_validations
validate_all_services
# Analyze log differences (pre vs post install)
analyze_log_diff "$TEST_RESULTS_DIR"
# Generate issue attribution report
# If base install issues found and archzfs inbox exists, create issue file
generate_issue_report "$TEST_RESULTS_DIR" "$ARCHZFS_INBOX"
# Set validation result based on failure count
if [ $VALIDATION_FAILED -eq 0 ]; then
TEST_PASSED=true
else
TEST_PASSED=false
fi
# Generate test report
section "Generating Test Report"
REPORT_FILE="$TEST_RESULTS_DIR/test-report.txt"
cat > "$REPORT_FILE" << EOFREPORT
========================================
ArchSetup Test Report
========================================
Test ID: $TIMESTAMP
Date: $(date +'%Y-%m-%d %H:%M:%S')
Test Method: QEMU snapshot-based
VM Configuration:
Disk: $DISK_PATH
Snapshot: $SNAPSHOT_NAME
SSH: localhost:$SSH_PORT
Results:
ArchSetup Exit Code: $ARCHSETUP_EXIT_CODE
Validation: $(if $TEST_PASSED; then echo "PASSED"; else echo "FAILED"; fi)
Validation Summary:
Passed: $VALIDATION_PASSED
Failed: $VALIDATION_FAILED
Warnings: $VALIDATION_WARNINGS
Issue Attribution:
ArchSetup Issues: ${#ARCHSETUP_ISSUES[@]}
Base Install Issues: ${#BASE_INSTALL_ISSUES[@]}
Unknown Issues: ${#UNKNOWN_ISSUES[@]}
Artifacts:
Log file: $LOGFILE
Report: $REPORT_FILE
Results: $TEST_RESULTS_DIR/
Issue Report: $TEST_RESULTS_DIR/issue-report.txt
Pre-install logs: $TEST_RESULTS_DIR/pre-install/
Post-install logs: $TEST_RESULTS_DIR/post-install/
Analysis: $TEST_RESULTS_DIR/analysis/
EOFREPORT
info "Test report saved: $REPORT_FILE"
# Cleanup or keep VM
section "Cleanup"
if $KEEP_VM; then
info "VM is still running in post-test state (--keep flag was used)"
info "Connect with:"
info " SSH: sshpass -p '$ROOT_PASSWORD' ssh -p $SSH_PORT root@localhost"
info ""
info "To stop VM: kill \$(cat $PID_FILE)"
info "To revert: qemu-img snapshot -a $SNAPSHOT_NAME $DISK_PATH"
else
step "Shutting down VM and reverting to clean snapshot"
stop_qemu
if restore_snapshot "$DISK_PATH" "$SNAPSHOT_NAME"; then
success "VM reverted to clean state"
else
warn "Failed to revert snapshot - VM may be in modified state"
fi
fi
# Final summary
section "Test Complete"
if [ "$ARCHSETUP_EXIT_CODE" = "0" ] && $TEST_PASSED; then
success "TEST PASSED"
exit 0
else
error "TEST FAILED"
info "Check logs in: $TEST_RESULTS_DIR"
exit 1
fi
|