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);