diff --git a/perl-xCAT/xCAT/DHCP/BootPolicy.pm b/perl-xCAT/xCAT/DHCP/BootPolicy.pm index c722608ae..13290c979 100644 --- a/perl-xCAT/xCAT/DHCP/BootPolicy.pm +++ b/perl-xCAT/xCAT/DHCP/BootPolicy.pm @@ -254,16 +254,30 @@ sub kea_onie_network_classes { test => onie_vendor_class_test(), additional_only => 1, 'option-data' => [ - { - name => 'www-server', - data => "http://$opts{next_server}$portsuffix/install/onie/onie-installer", - 'always-send' => 1, - }, + kea_onie_url_option( undef, "http://$opts{next_server}$portsuffix/install/onie/onie-installer" ), ], }, ]; } +# The installer URL goes in option 114, which is where ONIE looks for it. +# +# xCAT's dhcpd.conf says so by declaring "option www-server code 114 = string" +# -- a local redefinition, because ISC's own www-server is the standard option +# 72. Kea has no such redefinition: to it, www-server means option 72, a list +# of IPv4 addresses, and a URL in one is a configuration error that stops the +# server from starting at all. Naming the code says the same thing to both, +# and puts the same bytes on the wire. +sub kea_onie_url_option { + my ( $class, $url ) = @_; + + return { + code => 114, + data => $url, + 'always-send' => 1, + }; +} + # The user class a chainloaded second stage announces itself with, as an ISC # dhcpd condition. # diff --git a/xCAT-server/lib/xcat/plugins/dhcp.pm b/xCAT-server/lib/xcat/plugins/dhcp.pm index bafa6cd0e..b2201129d 100644 --- a/xCAT-server/lib/xcat/plugins/dhcp.pm +++ b/xCAT-server/lib/xcat/plugins/dhcp.pm @@ -4155,7 +4155,7 @@ sub kea_boot_for_node } } elsif ($netboot and $netboot eq 'onie') { my $onie_url = kea_onie_url_for_node($node, $ntent, $nxtsrv, $httpport); - push @{ $boot{'option-data'} }, { name => 'www-server', data => $onie_url } if $onie_url; + push @{ $boot{'option-data'} }, xCAT::DHCP::BootPolicy->kea_onie_url_option($onie_url) if $onie_url; } push @{ $boot{'option-data'} }, { name => 'host-name', data => $node }; @@ -5117,6 +5117,17 @@ sub newconfig push @dhcpconf, "option iscsi-initiator-iqn code 203 = string;\n"; #Only via gPXE, not a standard push @dhcpconf, "ddns-update-style interim;\n"; + + # A node that was moved to another rack comes up asking for the address it + # held there. Answering nothing leaves it retrying an address it can never + # have until its own timers give up; a DHCPNAK tells it to start over now. + # + # Each subnet declaration says "authoritative" as well, but that flag is + # read from the subnet the requested address belongs to -- and the whole + # point of this case is that it belongs to none of them. Only the global + # statement covers an address this server has never heard of, which is + # what Kea's global authoritative:true covers. + push @dhcpconf, "authoritative;\n"; push @dhcpconf, "ignore client-updates;\n"; #Windows clients like to do all caps, very un xCAT-like # push @dhcpconf, "update-static-leases on;\n"; #makedns rendered optional diff --git a/xCAT-test/dhcptest/conf/provision-vs-discovery.conf b/xCAT-test/dhcptest/conf/provision-vs-discovery.conf index daa2a3490..5aa33ed90 100644 --- a/xCAT-test/dhcptest/conf/provision-vs-discovery.conf +++ b/xCAT-test/dhcptest/conf/provision-vs-discovery.conf @@ -83,9 +83,17 @@ description = The node is told how to route, resolve and keep time, not just its # # Asked for as an INIT-REBOOT request -- option 50, no option 54 -- which is # what a node that already holds this lease sends when it comes back up. +# +# And asked without the PXEClient vendor class this file otherwise sends, +# because this is the reply an installed system gets: the options here are the +# ones an operating system needs, and a client that announces itself as PXE +# firmware is deliberately given a ten-minute lease instead of the cluster's +# (S-51), which is a different question asked in loader-absent.conf. [step known-network-settings] type = request mac = %(node_mac)s +vendor_class = +client_arch = requested_address = %(node_ip)s expect = ack assert = diff --git a/xCAT-test/dhcptest/conf/pxe-arch-matrix.conf b/xCAT-test/dhcptest/conf/pxe-arch-matrix.conf index a2048ac9e..58b52f0bd 100644 --- a/xCAT-test/dhcptest/conf/pxe-arch-matrix.conf +++ b/xCAT-test/dhcptest/conf/pxe-arch-matrix.conf @@ -208,9 +208,16 @@ description = S-19: An ONIE switch is offered an installer URL before it is a no # A switch announces onie_vendor on its very first boot, which is necessarily # before anyone has defined it as a node. If only a node definition can produce # the installer URL, the switch can never reach the state where it gets one. +# +# Option 114 is asked for, because a server sends an option when the client +# asks for it: ISC dhcpd puts nothing in the reply for an option missing from +# the parameter request list, however carefully the class set it. A real ONIE +# switch asks for 114, which is the whole reason xCAT's dhcpd.conf redefines +# www-server to that code. [step onie-discover] -type = discover -vendor_class = onie_vendor:x86_64 +type = discover +vendor_class = onie_vendor:x86_64 +request_options = 1, 3, 6, 54, 114 assert = msgtype == OFFER option:114 == %(onie_url)s diff --git a/xCAT-test/dhcptest/spec.md b/xCAT-test/dhcptest/spec.md index 337ed1414..d7fa7a672 100644 --- a/xCAT-test/dhcptest/spec.md +++ b/xCAT-test/dhcptest/spec.md @@ -515,10 +515,12 @@ Scenario: The reply carries an MTU where the network defines one @S-50 Scenario: The lease is as long as site.dhcplease says Given site.dhcplease is set - When a client is acknowledged + When a client that is not PXE firmware is acknowledged Then option 51 (lease-time) is that value And 43200 seconds when site.dhcplease is unset - # dhcp.pm:4524 + # dhcp.pm:4524. "Not PXE firmware" because a client announcing a PXEClient + # vendor class is answered by S-51 instead, and the two are the same reply + # field. @S-51 Scenario: A PXE client gets a short lease diff --git a/xCAT-test/unit/dhcp_boot_policy.t b/xCAT-test/unit/dhcp_boot_policy.t index 872368e72..1f5ef0cc3 100644 --- a/xCAT-test/unit/dhcp_boot_policy.t +++ b/xCAT-test/unit/dhcp_boot_policy.t @@ -290,7 +290,7 @@ is_deeply( additional_only => 1, 'option-data' => [ { - name => 'www-server', + code => 114, data => 'http://10.0.0.1/install/onie/onie-installer', 'always-send' => 1, }, @@ -299,6 +299,15 @@ is_deeply( ], 'an ONIE switch is pointed at the installer over HTTP, as the ISC path does', ); + +# The option is named by code and not by name on purpose. "www-server" means +# option 114 in xCAT's dhcpd.conf, which declares it that way, and option 72 to +# Kea, which does not -- and option 72 holds IPv4 addresses, so a URL in it +# stops kea-dhcp4 from starting. +is( $onie->[0]{'option-data'}[0]{code}, 114, + 'the installer URL is option 114, the one ONIE reads' ); +ok( !exists $onie->[0]{'option-data'}[0]{name}, + 'and it is not named www-server, which is a different option to Kea' ); is( xCAT::DHCP::BootPolicy->kea_onie_network_classes( net => '10.0.0.0', prefix => 24, next_server => '10.0.0.1', httpport => 8080,