mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-10-07 10:06:39 +00:00
test(dhcptest): assert an installed node is sent no script, and cite the spec
Two gaps in what the wire suite proves, both about traceability rather than about a new behaviour. S-31 had no wire case. A node whose chain.currstate is "boot" has an operating system and must be left to start it; a node handed a netboot script every time it powers on reinstalls itself forever, and does so silently, because each individual boot looks like a successful one. The Kea side of this is covered by dhcp_kea_plugin_intent.t, but the ISC side is built inline in addnode against a live database and cannot be reached by a unit test at all. The new case asks twice with the same MAC: once as firmware with no user class, once announcing the xNBA user class the first stage sets. Only the second request can be answered with the node's script, so only the second request can see the bug. What is asserted is S-31's own wording -- not "no boot file", which would forbid the stage-1 binary a server is entitled to send, but "not the node's xNBA script". The node is defined with netboot=xnba because only that method generates a second stage. The remaining ten scenarios already proven on the wire now say which specification scenario they prove, in the same "S-nn:" form the rest of the suite uses. That raises the scenarios cited by a wire case from 36 to 47 of the spec's 73, without running anything new -- the coverage was there and was not traceable.
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
# dhcpfixture.sh run-multimac a node reachable on either of its two ports
|
||||
# dhcpfixture.sh run-iscsi a diskless node is told where its root is
|
||||
# dhcpfixture.sh run-loader-absent a loader that is not on disk is not named
|
||||
# dhcpfixture.sh run-localboot an installed node is sent no xNBA script
|
||||
# dhcpfixture.sh run-httpport URLs carry a non-default web port
|
||||
# dhcpfixture.sh run-rangecidr a dynamic range written as a CIDR block
|
||||
# dhcpfixture.sh run-removal makedhcp -d stops the address being served
|
||||
@@ -112,6 +113,14 @@ RM_NODE=dhcptestrm
|
||||
RM_IP=10.99.0.71
|
||||
RM_MAC=02:00:dc:11:00:71
|
||||
|
||||
# A node that has been installed already: chain.currstate says it has an
|
||||
# operating system and must be left to start it. netboot is xnba rather than
|
||||
# the fixture's usual grub2 because the script that must not be sent is an
|
||||
# xNBA second stage, and only netboot=xnba generates one.
|
||||
LB_NODE=dhcptestboot
|
||||
LB_IP=10.99.0.81
|
||||
LB_MAC=02:00:dc:11:00:61
|
||||
|
||||
# A machine that speaks BOOTP and not DHCP, and the web port a cluster that is
|
||||
# not serving on 80 would use.
|
||||
BOOTP_MAC=02:00:de:ad:b0:07
|
||||
@@ -817,6 +826,29 @@ do_run_iscsi() {
|
||||
return $rc
|
||||
}
|
||||
|
||||
# S-31. A node that has already been installed. chain.currstate is what says
|
||||
# so, and it is set through chtab because it has no node attribute of its own.
|
||||
#
|
||||
# The script that must not be sent is the second stage of an xNBA boot, so the
|
||||
# node is defined with netboot=xnba and the case asks twice: once as firmware,
|
||||
# once announcing the user class the first stage sets. Only the second request
|
||||
# can be answered with the script, so only the second request can catch this.
|
||||
do_run_localboot() {
|
||||
local rc=0
|
||||
extra_define "$LB_NODE" groups=dhcptest ip="$LB_IP" mac="$LB_MAC" \
|
||||
arch=x86_64 netboot=xnba tftpserver="$SRV_IP" xcatmaster="$SRV_IP"
|
||||
chtab node="$LB_NODE" chain.currstate=boot \
|
||||
|| die "cannot set chain.currstate for $LB_NODE"
|
||||
echo done > "$STATE/localboot"
|
||||
makedhcp "$LB_NODE" || die "makedhcp $LB_NODE failed"
|
||||
|
||||
dhcptest_run \
|
||||
--set booted_mac="$LB_MAC" --set booted_ip="$LB_IP" \
|
||||
--set booted_script="http://$SRV_IP/tftpboot/xcat/xnba/nodes/$LB_NODE" \
|
||||
conf/localboot.conf || rc=1
|
||||
return $rc
|
||||
}
|
||||
|
||||
# S-12. One gating loader is taken away and the configuration regenerated --
|
||||
# both backends decide which boot classes to write by looking at what is on
|
||||
# disk, so the file has to be gone before makedhcp runs, not after.
|
||||
@@ -989,6 +1021,7 @@ dispatch() {
|
||||
run-multimac) do_run_multimac ;;
|
||||
run-iscsi) do_run_iscsi ;;
|
||||
run-loader-absent) do_run_loader_absent ;;
|
||||
run-localboot) do_run_localboot ;;
|
||||
run-httpport) do_run_httpport ;;
|
||||
run-rangecidr) do_run_rangecidr ;;
|
||||
run-removal) do_run_removal ;;
|
||||
@@ -997,7 +1030,7 @@ dispatch() {
|
||||
run-hierarchy) do_run_hierarchy ;;
|
||||
run-adoption) do_run_adoption ;;
|
||||
teardown) do_teardown ;;
|
||||
*) die "usage: $0 {check|setup|generate|backends|backend-setup <isc|kea>|backend-teardown <isc|kea>|run|run-arch|run-netboot|run-lease|run-chainload|run-nextserver|run-multimac|run-iscsi|run-loader-absent|run-httpport|run-rangecidr|run-removal|run-bootp|delegate|run-hierarchy|run-adoption|teardown}" ;;
|
||||
*) die "usage: $0 {check|setup|generate|backends|backend-setup <isc|kea>|backend-teardown <isc|kea>|run|run-arch|run-netboot|run-lease|run-chainload|run-nextserver|run-multimac|run-iscsi|run-loader-absent|run-localboot|run-httpport|run-rangecidr|run-removal|run-bootp|delegate|run-hierarchy|run-adoption|teardown}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ timeout = 3
|
||||
retries = 3
|
||||
|
||||
[scenario machine-is-unknown]
|
||||
description = Before it is defined, the machine is served out of the pool
|
||||
description = S-58: Before it is defined, the machine is served out of the pool
|
||||
|
||||
[step before-discover]
|
||||
type = discover
|
||||
@@ -39,7 +39,7 @@ assert =
|
||||
yiaddr != %(adopt_ip)s
|
||||
|
||||
[scenario machine-has-been-adopted]
|
||||
description = Once it is defined, the same MAC is served its own address
|
||||
description = S-58: Once it is defined, the same MAC is served its own address
|
||||
|
||||
[step after-discover]
|
||||
type = discover
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# conf/discovery-bootfile.conf
|
||||
|
||||
[scenario unknown-node-is-told-what-to-boot]
|
||||
description = A machine the server does not know is still handed a loader
|
||||
description = S-55, S-56: A machine the server does not know is still handed a loader
|
||||
|
||||
[step discovery-boot-discover]
|
||||
type = discover
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
# conf/hierarchy-dhcpserver.conf
|
||||
|
||||
[scenario delegated-pool-is-not-served-here]
|
||||
description = An unknown MAC gets nothing: the dynamic pool belongs to another server
|
||||
description = S-40: An unknown MAC gets nothing: the dynamic pool belongs to another server
|
||||
|
||||
[step delegated-discover]
|
||||
type = discover
|
||||
@@ -35,7 +35,7 @@ assert =
|
||||
offers == 0
|
||||
|
||||
[scenario delegated-node-is-pointed-elsewhere]
|
||||
description = A known machine is still answered, but sent to the delegate to boot
|
||||
description = S-41: A known machine is still answered, but sent to the delegate to boot
|
||||
|
||||
[step delegated-node-discover]
|
||||
type = discover
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# A node that already has an operating system.
|
||||
#
|
||||
# Once a node has been installed, chain.currstate is "boot" (or "iscsiboot" for
|
||||
# a node whose disk is an iSCSI target). From that point the server must stop
|
||||
# handing it a netboot script: a node that is given one every time it powers on
|
||||
# reinstalls itself forever, and does so silently, because each individual boot
|
||||
# looks like a successful boot.
|
||||
#
|
||||
# The address is still owned by the node and must still be offered -- this is a
|
||||
# statement about the boot file, not about the reservation.
|
||||
#
|
||||
# The two steps are the two halves of an xNBA boot. Firmware asks first with no
|
||||
# user class and is answered with the loader binary; the loader then asks again
|
||||
# announcing user class xNBA, and *that* is the request that would be answered
|
||||
# with the node's script. A test that only sends the first request cannot see
|
||||
# the difference, because the script never appears in the first reply.
|
||||
#
|
||||
# What is asserted is exactly spec.md S-31: not "no boot file", which would
|
||||
# forbid a server from handing back the stage-1 binary, but "not the node's
|
||||
# xNBA script". The script URL is supplied on the command line so this file
|
||||
# stays a statement about the wire:
|
||||
#
|
||||
# dhcptest run -i eth1 \
|
||||
# --set booted_mac=02:00:dc:11:00:61 \
|
||||
# --set booted_ip=10.0.0.61 \
|
||||
# --set booted_script=http://10.0.0.1/tftpboot/xcat/xnba/nodes/dhcptestboot \
|
||||
# conf/localboot.conf
|
||||
|
||||
[defaults]
|
||||
request_options = 1, 3, 6, 43, 54, 60, 66, 67
|
||||
timeout = 3
|
||||
retries = 3
|
||||
expect = offer
|
||||
|
||||
[scenario booted-node-is-not-sent-a-script]
|
||||
description = S-31: A node that has been installed is offered its address and no xNBA script
|
||||
|
||||
[step firmware-discover]
|
||||
type = discover
|
||||
mac = %(booted_mac)s
|
||||
client_arch = 0x0000
|
||||
vendor_class = PXEClient:Arch:00000:UNDI:002001
|
||||
assert =
|
||||
msgtype == OFFER
|
||||
yiaddr == %(booted_ip)s
|
||||
bootfile != %(booted_script)s
|
||||
|
||||
[scenario booted-node-is-not-sent-a-script-on-the-second-stage]
|
||||
description = S-31: And is not sent one when the loader asks again as xNBA
|
||||
|
||||
# The same node, same MAC, announcing the user class the first stage sets. This
|
||||
# is the request the script is keyed on, so it is the one that decides whether
|
||||
# an installed node reinstalls itself.
|
||||
[step second-stage-discover]
|
||||
type = discover
|
||||
mac = %(booted_mac)s
|
||||
client_arch = 0x0000
|
||||
vendor_class = PXEClient:Arch:00000:UNDI:002001
|
||||
user_class = xNBA
|
||||
user_class_form = raw
|
||||
assert =
|
||||
msgtype == OFFER
|
||||
yiaddr == %(booted_ip)s
|
||||
bootfile != %(booted_script)s
|
||||
@@ -12,7 +12,7 @@
|
||||
# dhcptest run -i eth1 --set foreign_ip=192.0.2.77 conf/nak-foreign-address.conf
|
||||
|
||||
[scenario foreign-address-is-refused]
|
||||
description = A request for an address off this network is refused, not ignored
|
||||
description = S-53: A request for an address off this network is refused, not ignored
|
||||
|
||||
[step reboot-request]
|
||||
type = request
|
||||
|
||||
@@ -38,7 +38,7 @@ timeout = 3
|
||||
retries = 3
|
||||
|
||||
[scenario known-node-is-provisioned]
|
||||
description = A machine the server knows gets its own address and its own boot file
|
||||
description = S-01: A machine the server knows gets its own address and its own boot file
|
||||
|
||||
[step known-discover]
|
||||
type = discover
|
||||
@@ -65,7 +65,7 @@ assert =
|
||||
option:1 present
|
||||
|
||||
[scenario known-node-gets-a-usable-network]
|
||||
description = The node is told how to route, resolve and keep time, not just its address
|
||||
description = S-44, S-49, S-50: The node is told how to route, resolve and keep time, not just its address
|
||||
|
||||
# An address on its own does not install an operating system. The installer has
|
||||
# to route off the provisioning network, resolve the server it fetches from,
|
||||
@@ -151,7 +151,7 @@ assert =
|
||||
yiaddr == %(node_ip)s
|
||||
|
||||
[scenario unknown-node-is-discovered]
|
||||
description = A machine the server does not know gets an address out of the pool
|
||||
description = S-03: A machine the server does not know gets an address out of the pool
|
||||
|
||||
[step unknown-discover]
|
||||
type = discover
|
||||
|
||||
@@ -88,7 +88,7 @@ assert =
|
||||
bootfile == %(uefi_loader)s
|
||||
|
||||
[scenario pxe-aarch64]
|
||||
description = S-11: An aarch64 UEFI client is offered the aarch64 loader
|
||||
description = S-11, S-57: An aarch64 UEFI client is offered the aarch64 loader
|
||||
|
||||
[step aarch64-discover]
|
||||
type = discover
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
# conf/static-vs-dynamic.conf
|
||||
|
||||
[scenario reserved-mac]
|
||||
description = A reserved MAC is offered and acknowledged its reserved address
|
||||
description = S-01: A reserved MAC is offered and acknowledged its reserved address
|
||||
|
||||
[step reserved-discover]
|
||||
type = discover
|
||||
@@ -42,7 +42,7 @@ assert =
|
||||
yiaddr == %(reserved_ip)s
|
||||
|
||||
[scenario unreserved-mac-gets-pool-address]
|
||||
description = An unreserved MAC is offered an address out of the dynamic pool
|
||||
description = S-03: An unreserved MAC is offered an address out of the dynamic pool
|
||||
|
||||
[step pool-discover]
|
||||
type = discover
|
||||
|
||||
Reference in New Issue
Block a user