diff --git a/xCAT-test/blackboxtest/README.md b/xCAT-test/blackboxtest/README.md index 09da69ece..2756a2c8d 100644 --- a/xCAT-test/blackboxtest/README.md +++ b/xCAT-test/blackboxtest/README.md @@ -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 ... diff --git a/xCAT-test/blackboxtest/conf/dhcp/loader-absent.conf b/xCAT-test/blackboxtest/conf/dhcp/loader-absent.conf index 030535cd2..d364c11db 100644 --- a/xCAT-test/blackboxtest/conf/dhcp/loader-absent.conf +++ b/xCAT-test/blackboxtest/conf/dhcp/loader-absent.conf @@ -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 diff --git a/xCAT-test/blackboxtest/conf/dhcp/localboot.conf b/xCAT-test/blackboxtest/conf/dhcp/localboot.conf index fadf55403..33565b7ee 100644 --- a/xCAT-test/blackboxtest/conf/dhcp/localboot.conf +++ b/xCAT-test/blackboxtest/conf/dhcp/localboot.conf @@ -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 diff --git a/xCAT-test/blackboxtest/conf/dhcp/netboot-methods.conf b/xCAT-test/blackboxtest/conf/dhcp/netboot-methods.conf index c889b0534..150f8e99c 100644 --- a/xCAT-test/blackboxtest/conf/dhcp/netboot-methods.conf +++ b/xCAT-test/blackboxtest/conf/dhcp/netboot-methods.conf @@ -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 diff --git a/xCAT-test/blackboxtest/conf/dhcp/pxe-arch-matrix.conf b/xCAT-test/blackboxtest/conf/dhcp/pxe-arch-matrix.conf index f4a9fdd95..107f2306e 100644 --- a/xCAT-test/blackboxtest/conf/dhcp/pxe-arch-matrix.conf +++ b/xCAT-test/blackboxtest/conf/dhcp/pxe-arch-matrix.conf @@ -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 diff --git a/xCAT-test/blackboxtest/src/blackboxtest_lib/dhcpopts.py b/xCAT-test/blackboxtest/src/blackboxtest_lib/dhcpopts.py index 9dfde3ed9..0875bfc80 100644 --- a/xCAT-test/blackboxtest/src/blackboxtest_lib/dhcpopts.py +++ b/xCAT-test/blackboxtest/src/blackboxtest_lib/dhcpopts.py @@ -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. diff --git a/xCAT-test/blackboxtest/tests/test_assertions.py b/xCAT-test/blackboxtest/tests/test_assertions.py index 9f0fbb726..246b5af6e 100644 --- a/xCAT-test/blackboxtest/tests/test_assertions.py +++ b/xCAT-test/blackboxtest/tests/test_assertions.py @@ -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)