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
|
#!/bin/bash
# SPDX-License-Identifier: GPL-3.0-or-later
# Network diagnostics for VM testing
# Author: Craig Jennings <craigmartinjennings@gmail.com>
# License: GNU GPLv3
# Note: logging.sh and vm-utils.sh should already be sourced by the calling script
# Uses globals: ROOT_PASSWORD, SSH_PORT, SSH_OPTS, VM_IP (from vm-utils.sh or calling script)
# Optional global: TEST_RESULTS_DIR (raw command outputs are saved there when set)
# Gather one read-only fact from the VM, print it, and save the raw output.
# Facts are collected regardless of pass/fail so a failing install still leaves
# the IP/route/resolver evidence in the log and the results dir.
# $1 label human-readable label for the fact
# $2 slug filename slug for the saved raw output
# $3 cmd remote command to run over the shared ssh_base
# Uses the caller's locals ssh_base and results_dir (dynamic scope).
_netdiag_fact() {
local label="$1" slug="$2" cmd="$3" out
out="$($ssh_base "$cmd" 2>&1)"
info "${label}:"
printf '%s\n' "$out" | while IFS= read -r line; do
info " $line"
done
if [ -n "$results_dir" ]; then
printf '%s\n' "$out" > "$results_dir/netdiag-${slug}.txt" 2>/dev/null || true
fi
}
# Run quick network diagnostics.
#
# Evidence first: collect read-only facts (interfaces, route, resolver)
# unconditionally, then run every reachability check and report all failures at
# the end. A DNS failure is named as a DNS failure, not masked as a generic "no
# internet" or misattributed to the Arch mirror. Returns 0 when all checks pass,
# non-zero when any check fails, so callers keep their success/failure contract.
run_network_diagnostics() {
local password="${ROOT_PASSWORD:-archsetup}"
local port="${SSH_PORT:-22}"
local host="${VM_IP:-localhost}"
local ssh_base="sshpass -p $password ssh $SSH_OPTS -p $port root@$host"
local results_dir="${TEST_RESULTS_DIR:-}"
local failures=()
section "Pre-flight Network Diagnostics"
# --- Phase 1: collect read-only facts, unconditionally ---
# These never gate the outcome; they exist so a failed install still has
# the interface/route/resolver evidence to diagnose from.
step "Collecting interface addresses"
_netdiag_fact "Interface addresses (ip -brief addr)" "ip-addr" "ip -brief addr"
step "Collecting default route"
_netdiag_fact "Default route (ip route show default)" "ip-route" "ip route show default"
step "Reading resolver configuration"
_netdiag_fact "Resolver (/etc/resolv.conf)" "resolv-conf" "cat /etc/resolv.conf"
# --- Phase 2: generic connectivity checks (run all, don't short-circuit) ---
# DNS, egress, and TLS are independent failure modes. Keeping them separate
# means a resolver problem reads as DNS, not as a downstream mirror failure.
step "Testing DNS resolution"
if $ssh_base "getent hosts archlinux.org >/dev/null 2>&1" 2>/dev/null; then
success "DNS resolution OK"
else
error "DNS resolution failed"
failures+=("DNS resolution (getent hosts archlinux.org)")
fi
step "Testing HTTP egress"
if $ssh_base "curl -s --connect-timeout 5 -o /dev/null http://archlinux.org" 2>/dev/null; then
success "HTTP egress OK"
else
error "HTTP egress failed"
failures+=("HTTP egress (http://archlinux.org)")
fi
step "Testing TLS/HTTPS egress"
if $ssh_base "curl -s --connect-timeout 5 -o /dev/null https://archlinux.org" 2>/dev/null; then
success "TLS/HTTPS egress OK"
else
error "TLS/HTTPS egress failed"
failures+=("TLS/HTTPS egress (https://archlinux.org)")
fi
# --- Phase 3: Arch-specific checks (run all, don't short-circuit) ---
step "Testing Arch mirror access"
if $ssh_base "curl -s -I https://geo.mirror.pkgbuild.com/ | head -1 | grep -qE '(200|301|302)'" 2>/dev/null; then
success "Arch mirrors accessible"
else
error "Cannot reach Arch mirrors"
failures+=("Arch mirror (https://geo.mirror.pkgbuild.com/)")
fi
step "Testing AUR access"
if $ssh_base "curl -s -I https://aur.archlinux.org/ | head -1 | grep -qE '(200|405)'" 2>/dev/null; then
success "AUR accessible"
else
error "Cannot reach AUR"
failures+=("AUR (https://aur.archlinux.org/)")
fi
# --- Summary: report every failure, not just the first ---
if [ ${#failures[@]} -eq 0 ]; then
success "Network diagnostics complete - all checks passed"
return 0
fi
error "Network diagnostics found ${#failures[@]} failure(s):"
local f
for f in "${failures[@]}"; do
error " - $f"
done
return 1
}
|