2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-10-21 15:18:19 +00:00
Files
xcat-core/xCAT-test/bats/check_provisioning_source.bats
Daniel Hilst 1aa05e8304 fix(xcat-core): two branches word the same guard two ways
fix/service-node-el fixed the management-node guard as commit 0f708b96a, with the same
correction this branch made: the log must hold lines, not gain them. The two differ
only in the comment and in the error message, so the file no longer merges as one
change.

The wording here now matches fix/service-node-el. The remaining difference in this file
is the doubled-slash path filter, which that branch does not carry.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-30 13:16:01 -03:00

292 lines
10 KiB
Bash

#!/usr/bin/env bats
#
# Drive check_provisioning_source.sh, which is what tells a hierarchical provision from a flat
# one. The management node, the service node and the compute node share one subnet and both
# dhcpd instances answer for the compute node, so the management node can win the xNBA exchange
# and serve the boot payload itself. The httpd access logs are the only record of that.
#
# The check takes a baseline of both logs before provisioning and reads only what came after, so
# these tests write the old lines, take the baseline, then append the lines of the run.
#
# lsdef, xdsh and hostname are stubbed. XCAT_HTTPD_ACCESS_LOG is the management node's log.
load 'helpers/shell_source'
CN=cn01
SN=sn01
CN_IP=192.0.2.10
setup()
{
SCRIPT="$(require_repo_file 'xCAT-test/autotest/testcase/commoncmd/check_provisioning_source.sh')"
BIN="${BATS_TEST_TMPDIR}/bin"
MN_LOG="${BATS_TEST_TMPDIR}/mn-access_log"
SN_LOG="${BATS_TEST_TMPDIR}/sn-access_log"
STATE="${BATS_TEST_TMPDIR}/baseline"
mkdir -p "$BIN"
: >"$MN_LOG"
: >"$SN_LOG"
printf '#!/bin/sh\nprintf "Object name: %s\\n ip=%s\\n" "$3" "%s"\n' "%s" "%s" "$CN_IP" >"$BIN/lsdef"
printf '#!/bin/sh\necho mn01\n' >"$BIN/hostname"
# A test that reaches the network measures the lab, not this script.
printf '#!/bin/sh\necho "unexpected getent $*" >&2\nexit 1\n' >"$BIN/getent"
# xdsh -e copies the script to the service node and runs it there. Run it here instead, with
# the service node log in place of the management node one, and prefix the node name as xdsh
# does.
printf '#!/bin/sh\nnode=$1\nshift\n[ "$1" = "-e" ] && shift\nscript=$1\nshift\nXCAT_HTTPD_ACCESS_LOG=%s "$script" "$@" | sed "s/^/$node: /"\n' \
"$SN_LOG" >"$BIN/xdsh"
chmod 0755 "$BIN"/*
export PATH="$BIN:$PATH"
}
# One access-log line in the combined format: $1 client, $2 bytes, $3 path.
access_line()
{
printf '%s - - [01/Jan/2026:00:00:00 +0000] "GET %s HTTP/1.1" 200 %s "-" "iPXE"\n' "$1" "$3" "$2"
}
take_baseline()
{
env XCAT_HTTPD_ACCESS_LOG="$MN_LOG" XCAT_PROV_SOURCE_STATE="$STATE" \
"$SCRIPT" --baseline "$CN" "$SN" >/dev/null
}
run_check()
{
run env XCAT_HTTPD_ACCESS_LOG="$MN_LOG" XCAT_PROV_SOURCE_STATE="$STATE" "$SCRIPT" "$CN" "$SN"
}
# A log that has to hold something at baseline time, so the baseline is not trivially zero.
seed_logs()
{
access_line 192.0.2.30 512 /install/rh/x86_64/ >"$SN_LOG"
access_line 192.0.2.31 512 /install/rh/x86_64/ >"$MN_LOG"
}
@test "a service node that served the compute node and a silent management node pass" {
seed_logs
take_baseline
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >>"$SN_LOG"
access_line 192.0.2.21 4096 /install/rh/x86_64/ >>"$MN_LOG"
run_check
[ "$status" -eq 0 ]
[[ "$output" == *"provisioning source ok"* ]]
}
@test "a management node request from BEFORE the baseline does not fail this run" {
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >"$MN_LOG"
access_line 192.0.2.30 512 /install/rh/x86_64/ >"$SN_LOG"
take_baseline
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >>"$SN_LOG"
access_line 192.0.2.21 4096 /install/rh/x86_64/ >>"$MN_LOG"
run_check
[ "$status" -eq 0 ]
[[ "$output" == *"provisioning source ok"* ]]
}
@test "a service node request from BEFORE the baseline does not satisfy the check" {
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >"$SN_LOG"
access_line 192.0.2.31 512 /install/rh/x86_64/ >"$MN_LOG"
take_baseline
access_line 192.0.2.21 4096 /install/rh/x86_64/ >>"$MN_LOG"
run_check
[ "$status" -ne 0 ]
[[ "$output" == *"no boot payload"* ]]
}
@test "a request that carries no boot payload does not satisfy the check" {
seed_logs
take_baseline
printf '%s - - [01/Jan/2026:00:00:00 +0000] "GET /favicon.ico HTTP/1.1" 404 209 "-" "iPXE"\n' \
"$CN_IP" >>"$SN_LOG"
access_line 192.0.2.21 4096 /install/rh/x86_64/ >>"$MN_LOG"
run_check
[ "$status" -ne 0 ]
[[ "$output" == *"no boot payload"* ]]
}
@test "a management node request that carries no boot payload does not read as a flat provision" {
seed_logs
take_baseline
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >>"$SN_LOG"
printf '%s - - [01/Jan/2026:00:00:00 +0000] "GET /favicon.ico HTTP/1.1" 404 209 "-" "iPXE"\n' \
"$CN_IP" >>"$MN_LOG"
run_check
[ "$status" -eq 0 ]
[[ "$output" == *"provisioning source ok"* ]]
}
@test "the check refuses to answer with no baseline" {
seed_logs
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >>"$SN_LOG"
run_check
[ "$status" -ne 0 ]
[[ "$output" == *"no baseline"* ]]
[[ "$output" != *"provisioning source ok"* ]]
}
@test "a log rotated below its baseline is read from its first line" {
for i in 1 2 3 4 5; do access_line 192.0.2.30 512 /install/rh/x86_64/; done >"$SN_LOG"
access_line 192.0.2.31 512 /install/rh/x86_64/ >"$MN_LOG"
take_baseline
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >"$SN_LOG"
access_line 192.0.2.21 4096 /install/rh/x86_64/ >>"$MN_LOG"
run_check
[ "$status" -eq 0 ]
[[ "$output" == *"provisioning source ok"* ]]
}
@test "the management node answering for the compute node fails the check" {
seed_logs
take_baseline
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >>"$SN_LOG"
{
access_line 192.0.2.21 4096 /install/rh/x86_64/
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel
} >>"$MN_LOG"
run_check
[ "$status" -ne 0 ]
[[ "$output" == *"this provision was flat"* ]]
[[ "$output" != *"provisioning source ok"* ]]
}
@test "a management node answering only a bodyless request still fails the check" {
seed_logs
take_baseline
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >>"$SN_LOG"
{
access_line 192.0.2.21 4096 /install/rh/x86_64/
printf '%s - - [01/Jan/2026:00:00:00 +0000] "HEAD %s HTTP/1.1" 304 - "-" "iPXE"\n' \
"$CN_IP" /tftpboot/xcat/genesis.kernel
} >>"$MN_LOG"
run_check
[ "$status" -ne 0 ]
[[ "$output" == *"this provision was flat"* ]]
}
@test "a service node that served the compute node nothing fails the check" {
seed_logs
take_baseline
access_line 192.0.2.22 4096 /install/rh/x86_64/ >>"$SN_LOG"
access_line 192.0.2.21 4096 /install/rh/x86_64/ >>"$MN_LOG"
run_check
[ "$status" -ne 0 ]
[[ "$output" == *"no boot payload"* ]]
}
@test "an unreadable service node log fails the check instead of passing it" {
seed_logs
take_baseline
access_line 192.0.2.21 4096 /install/rh/x86_64/ >>"$MN_LOG"
printf '#!/bin/sh\nexit 1\n' >"$BIN/xdsh"
chmod 0755 "$BIN/xdsh"
run_check
[ "$status" -ne 0 ]
[[ "$output" == *"no httpd access log could be read on $SN"* ]]
}
# The management node provisions the service node BEFORE this baseline, so it can serve nothing
# after it. That is the hierarchical result, and it was read as a broken log.
@test "a management node that serves nothing after the baseline passes" {
seed_logs
take_baseline
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >>"$SN_LOG"
run_check
[ "$status" -eq 0 ]
[[ "$output" == *"provisioning source ok"* ]]
}
@test "a management node log with no entry at all fails the check instead of reading as silence" {
: >"$MN_LOG"
access_line 192.0.2.30 512 /install/rh/x86_64/ >"$SN_LOG"
take_baseline
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >>"$SN_LOG"
run_check
[ "$status" -ne 0 ]
[[ "$output" == *"no httpd access log with entries could be read on mn01"* ]]
}
# The compute node fetches the root image with wget from a URL that carries a double slash, so
# the path in the log reads //install/... and the payload filter did not match it.
@test "a boot payload requested under a doubled slash counts" {
seed_logs
take_baseline
access_line "$CN_IP" 978729607 //install/netboot/ubuntu/x86_64/compute/rootimg.cpio.gz >>"$SN_LOG"
access_line 192.0.2.21 4096 /install/rh/x86_64/ >>"$MN_LOG"
run_check
[ "$status" -eq 0 ]
[[ "$output" == *"provisioning source ok"* ]]
}
@test "a doubled-slash boot payload from the management node reads as a flat provision" {
seed_logs
take_baseline
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >>"$SN_LOG"
{
access_line 192.0.2.21 4096 /install/rh/x86_64/
access_line "$CN_IP" 978729607 //install/netboot/ubuntu/x86_64/compute/rootimg.cpio.gz
} >>"$MN_LOG"
run_check
[ "$status" -ne 0 ]
[[ "$output" == *"this provision was flat"* ]]
}
@test "the Debian per-vhost log format is read as the client address" {
seed_logs
take_baseline
printf 'xcat:80 %s - - [01/Jan/2026:00:00:00 +0000] "GET %s HTTP/1.1" 200 12345678\n' \
"$CN_IP" /tftpboot/xcat/genesis.kernel >>"$SN_LOG"
printf 'xcat:80 %s - - [01/Jan/2026:00:00:00 +0000] "GET %s HTTP/1.1" 200 4096\n' \
192.0.2.21 /install/ubuntu/x86_64/ >>"$MN_LOG"
run_check
[ "$status" -eq 0 ]
[[ "$output" == *"provisioning source ok"* ]]
}
@test "a compute node with no address fails the check" {
seed_logs
take_baseline
printf '#!/bin/sh\nexit 1\n' >"$BIN/lsdef"
printf '#!/bin/sh\nexit 2\n' >"$BIN/getent"
chmod 0755 "$BIN/lsdef" "$BIN/getent"
access_line "$CN_IP" 12345678 /tftpboot/xcat/genesis.kernel >>"$SN_LOG"
access_line 192.0.2.21 4096 /install/rh/x86_64/ >>"$MN_LOG"
run_check
[ "$status" -ne 0 ]
[[ "$output" == *"has no address"* ]]
}
@test "a baseline that cannot reach the service node names the service node" {
seed_logs
printf '#!/bin/sh\nexit 1\n' >"$BIN/xdsh"
chmod 0755 "$BIN/xdsh"
run env XCAT_HTTPD_ACCESS_LOG="$MN_LOG" XCAT_PROV_SOURCE_STATE="$STATE" \
"$SCRIPT" --baseline "$CN" "$SN"
[ "$status" -ne 0 ]
[[ "$output" == *"no access log to baseline on $SN"* ]]
# The message used to append the management node's baseline spec after the node name, so a
# substring match on the name alone passes either way.
[[ "$output" != *"$MN_LOG"* ]]
[ ! -e "$STATE" ]
}