From f9457753171b0d989ae07d4174f0b17dd7ce4e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Fri, 21 Aug 2026 00:55:26 -0300 Subject: [PATCH] feat(mknb): fetch the Genesis discovery payload over HTTP The grub2 discovery configuration loaded the Genesis kernel and initramfs over TFTP, a lockstep protocol that acknowledges every block and runs one server process per client. Fetching the same 79 MiB Genesis image from a node on the lab network took 61.5 s over TFTP and 1.2 s over HTTP, and a whole cluster discovering at once queues on the TFTP server. Write two entries instead. The default one sets root to the HTTP server of the management node on that network and loads the same files from below the TFTP root, the way nodeset does for netboot=grub2-http; the second keeps the TFTP paths for a management node that does not serve the TFTP root over HTTP, and "set fallback=1" moves to it when GRUB cannot fetch the payload over HTTP. site.httpport is honoured. --- xCAT-server/lib/xcat/plugins/mknb.pm | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/mknb.pm b/xCAT-server/lib/xcat/plugins/mknb.pm index 94702fe66..b9f01b633 100644 --- a/xCAT-server/lib/xcat/plugins/mknb.pm +++ b/xCAT-server/lib/xcat/plugins/mknb.pm @@ -841,11 +841,12 @@ sub process_request { hexnet => $_, xcatd_address => $xcatd_address, xcatdport => $xcatdport, + httpport => $httpport, consolecmdline => $consolecmdline, ); } } - if (exists $GRUB2_DISCOVERY_ARCHES{$arch} and !-e "$tftpdir/boot/grub2/grub2.$arch") { + if (exists $GRUB2_DISCOVERY_ARCHES{$arch} && !-e "$tftpdir/boot/grub2/grub2.$arch") { # The discovery configurations are only reached through this boot loader, which # xCAT does not build: say so instead of letting the nodes time out in firmware. $callback->({ data => ["Note: $tftpdir/boot/grub2/grub2.$arch is missing; $arch nodes need it to reach these configurations (it is installed by grub2-xcat, or copied from the EL $arch installation media)"] }); @@ -879,7 +880,8 @@ sub _grub2_discovery_arches { # then grub.cfg-<8 hex digit ip>, then ever shorter prefixes of that ip, and # finally grub.cfg. nodeset writes the per-node files (full ip and mac), so a # per-network prefix is only reached by clients without a node configuration: -# discovery. The file is rebuilt from the Genesis artifacts present under +# discovery. The payload is fetched over HTTP, with a TFTP entry behind it. +# The file is rebuilt from the Genesis artifacts present under # $tftpdir/xcat and removed when none are left. Returns the path written. sub _write_grub2_discovery_config { my (%args) = @_; @@ -895,14 +897,33 @@ sub _write_grub2_discovery_config { if (defined($args{consolecmdline}) and $args{consolecmdline} ne '') { $cmdline .= " $args{consolecmdline}"; } + # The Genesis initramfs is large and a TFTP server hands it to one client at a + # time, so the default entry fetches it over HTTP, the same way nodeset does for + # netboot=grub2-http. The TFTP entry stays as the second choice for a management + # node that does not serve the TFTP root over HTTP. + my $httpport = $args{httpport} || '80'; + my $httproot = 'http,' . $args{xcatd_address} . ($httpport eq '80' ? '' : ":$httpport"); + my $tftproot = 'tftp,' . $args{xcatd_address}; my $content = "# xCAT Genesis discovery for network $hexnet - generated by mknb, do not edit\n"; $content .= "set default=0\n"; + # Every architecture branch defines the HTTP entry first and the TFTP entry + # second, so a payload GRUB cannot fetch over HTTP is retried over TFTP. + $content .= "set fallback=1\n"; $content .= "set timeout=5\n"; my $keyword = 'if'; foreach my $entry (@arches) { my ($arch, $grub_cpu, $kernel, $initrd) = @{$entry}; $content .= "$keyword [ \"\$grub_cpu\" = \"$grub_cpu\" ]; then\n"; $content .= "menuentry \"xCAT Genesis $arch\" {\n"; + $content .= " insmod http\n"; + $content .= " insmod tftp\n"; + $content .= " set root=$httproot\n"; + $content .= " linux $tftpdir/$kernel $cmdline BOOTIF=\$net_default_mac\n"; + $content .= " initrd $tftpdir/$initrd\n"; + $content .= "}\n"; + $content .= "menuentry \"xCAT Genesis $arch (TFTP)\" {\n"; + $content .= " insmod tftp\n"; + $content .= " set root=$tftproot\n"; $content .= " linux /$kernel $cmdline BOOTIF=\$net_default_mac\n"; $content .= " initrd /$initrd\n"; $content .= "}\n"; @@ -912,8 +933,7 @@ sub _write_grub2_discovery_config { # nodeset hard-links grub.cfg-<8 hex digit ip> to the node file; on a /32 network that is # this file's name, so replace the name instead of truncating a shared inode. unlink($cfgpath); - my $cfg; - open($cfg, ">", $cfgpath) or return; + open(my $cfg, ">", $cfgpath) or return; print $cfg $content; close($cfg); chmod(0644, $cfgpath);