mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-10-22 07:38:08 +00:00
test(blackboxtest): read the boot file from the BOOTP header only
bootfile returned option 67 when the reply carried one and the file header otherwise. xCAT names the loader in the header, and the firmware it serves does not read option 67 (dhcp-wire.md). A backend that moved the loader to option 67 and left the header empty passed every loader assertion. bootfile now reads the header only, and each "no boot file" check also asserts that option 67 is absent. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
@@ -185,16 +185,17 @@ a flag letter (`S` `O` `E` `N`); `E` sends the name in wire format.
|
||||
Reply fields: the BOOTP header (`msgtype` `xid` `yiaddr` `siaddr` `ciaddr`
|
||||
`giaddr` `chaddr` `file` `sname` `secs` `flags` `src_ip` `src_mac`), the
|
||||
aliases `address` `mac` `next_server`, any option as `54`, `option:54`,
|
||||
`opt54` or `server_id`, and three fields a client reads from two places:
|
||||
`opt54` or `server_id`, and three derived fields:
|
||||
|
||||
- `bootfile`: option 67 when sent, else the `file` header. ISC fills the
|
||||
header, dnsmasq answers in option 67, and firmware reads either.
|
||||
- `bootfile`: the loader, from the BOOTP `file` header only. xCAT names the
|
||||
loader there, and the firmware it serves does not read option 67. A "no boot
|
||||
file" check also asserts `67 absent`.
|
||||
- `dns_name`: option 81 when sent, else option 12. Kea answers option 81 in
|
||||
option 81; ISC with `ignore client-updates` sends option 12 only.
|
||||
- `fqdn_flags`: option 81's flags as letters, absent without option 81.
|
||||
|
||||
Assert on those rather than on `file` or one option, unless the one place is
|
||||
the point. `msgtype` is `BOOTREPLY` for a reply with no option 53.
|
||||
Assert on `dns_name` rather than on option 12 or 81, unless one option is the
|
||||
point. `msgtype` is `BOOTREPLY` for a reply with no option 53.
|
||||
|
||||
The client MAC is a random locally administered address, so the host's own
|
||||
network stack never takes a reply as its own. The tool answers ARP only for an
|
||||
@@ -265,8 +266,8 @@ not ok 3 - pxe-bios-x86/bios-discover: bootfile == pxelinux.0
|
||||
---
|
||||
expected: 'pxelinux.0'
|
||||
received: 'xcat/xnba.kpxe'
|
||||
reply: OFFER from 10.99.0.1 (9a:3d:4f:3d:59:1b) xid=0xc45c6376 yiaddr=10.99.0.175 siaddr=10.99.0.1 file=''
|
||||
options: {1 (subnet_mask)=255.255.255.0, 54 (server_id)=10.99.0.1, 67 (bootfile_name)=xcat/xnba.kpxe}
|
||||
reply: OFFER from 10.99.0.1 (9a:3d:4f:3d:59:1b) xid=0xc45c6376 yiaddr=10.99.0.175 siaddr=10.99.0.1 file='xcat/xnba.kpxe'
|
||||
options: {1 (subnet_mask)=255.255.255.0, 54 (server_id)=10.99.0.1}
|
||||
sent: DISCOVER mac=02:da:16:d0:80:dd xid=0xc45c6376 client_arch=0x0000
|
||||
attempt: 1 of 3
|
||||
...
|
||||
|
||||
@@ -32,6 +32,7 @@ assert =
|
||||
msgtype == OFFER
|
||||
yiaddr in %(pool)s
|
||||
bootfile absent
|
||||
67 absent
|
||||
|
||||
[scenario present-loader-is-still-named]
|
||||
description = S-12: An architecture whose loader is still there is unaffected
|
||||
|
||||
@@ -43,6 +43,7 @@ assert =
|
||||
yiaddr == %(booted_ip)s
|
||||
bootfile != %(booted_script)s
|
||||
bootfile absent
|
||||
67 absent
|
||||
|
||||
[scenario booted-pxe-node-is-not-sent-a-loader]
|
||||
description = S-31: An installed node provisioned with netboot=pxe is not handed pxelinux either
|
||||
@@ -59,6 +60,7 @@ assert =
|
||||
msgtype == OFFER
|
||||
yiaddr == %(booted_pxe_ip)s
|
||||
bootfile absent
|
||||
67 absent
|
||||
|
||||
[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
|
||||
@@ -78,3 +80,4 @@ assert =
|
||||
yiaddr == %(booted_ip)s
|
||||
bootfile != %(booted_script)s
|
||||
bootfile absent
|
||||
67 absent
|
||||
|
||||
@@ -190,6 +190,7 @@ assert =
|
||||
msgtype == OFFER
|
||||
option:209 == %(petitboot_conf)s
|
||||
bootfile absent
|
||||
67 absent
|
||||
|
||||
[scenario noip-interface-is-denied]
|
||||
description = S-07: An interface marked *NOIP* is not answered at all
|
||||
|
||||
@@ -174,6 +174,7 @@ assert =
|
||||
msgtype == OFFER
|
||||
option:209 == %(opal_conf)s
|
||||
bootfile absent
|
||||
67 absent
|
||||
|
||||
[scenario s390x-qemu]
|
||||
description = S-16: A QEMU s390x client is given a conf-file and no loader
|
||||
@@ -185,6 +186,7 @@ assert =
|
||||
msgtype == OFFER
|
||||
option:209 == %(s390x_conf)s
|
||||
bootfile absent
|
||||
67 absent
|
||||
|
||||
[scenario vendor-class-etherboot]
|
||||
description = S-18: A client that identifies itself by vendor class alone still boots
|
||||
|
||||
@@ -439,12 +439,12 @@ class DhcpReply(Reply):
|
||||
self.raw_options = raw_options
|
||||
|
||||
def bootfile(self):
|
||||
"""What a client boots: option 67 when sent, else the `file` header.
|
||||
"""The loader a node boots: the BOOTP `file` header.
|
||||
|
||||
ISC fills the header, dnsmasq answers in option 67, and firmware
|
||||
reads whichever arrived.
|
||||
The firmware xCAT serves reads the header. A loader named only in
|
||||
option 67 does not boot it.
|
||||
"""
|
||||
return self.options.get(67) or self.fields.get("file", "")
|
||||
return self.fields.get("file", "")
|
||||
|
||||
def dns_name(self):
|
||||
"""The node's name: option 81 when sent, else option 12.
|
||||
|
||||
@@ -114,11 +114,14 @@ class DhcpFields(unittest.TestCase):
|
||||
for target in ("54", "option:54", "server_id", "opt54"):
|
||||
self.assertTrue(check("%s == 10.0.0.1" % target, reply).ok, target)
|
||||
|
||||
def test_the_boot_file_prefers_option_67(self):
|
||||
def test_the_boot_file_is_the_header_and_never_option_67(self):
|
||||
# xCAT names the loader in the BOOTP header; its firmware does not
|
||||
# read option 67.
|
||||
reply = offer({67: "grub2.aarch64"})
|
||||
self.assertTrue(check("bootfile absent", reply).ok)
|
||||
reply.fields["file"] = "pxelinux.0"
|
||||
self.assertTrue(check("bootfile == grub2.aarch64", reply).ok)
|
||||
self.assertTrue(check("file == pxelinux.0", reply).ok)
|
||||
self.assertTrue(check("bootfile == pxelinux.0", reply).ok)
|
||||
self.assertTrue(check("67 == grub2.aarch64", reply).ok)
|
||||
|
||||
def test_the_dns_name_prefers_option_81_and_falls_back_to_12(self):
|
||||
self.assertTrue(check("dns_name == n1", offer({12: "n1"})).ok)
|
||||
|
||||
Reference in New Issue
Block a user