From 39f721713ee62de1d95c6ca1cb3bc9d88ecf1742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Sat, 25 Jul 2026 16:53:24 -0300 Subject: [PATCH] fix(netboot): omit the default HTTP port from generated boot URLs Boot URLs handed to nodes always carried an explicit :80 even when the HTTP server listens on the default port. grub2.pm already omits the port when it is 80; make the xNBA, genesis and DHCP boot URLs consistent with it. $portsuffix is empty when site.httpport is unset or 80 and ":" otherwise, so a non-default port is unchanged. Covers the ISC and Kea paths in dhcp.pm, xnba.pm, mknb.pm, and the Kea xNBA client classes in BootPolicy.pm. dhcp_boot_policy.t and mknb_xcatd_address.t follow the new URLs and gain cases for a non-default and an unset port. The floating-address guard in mknb_xcatd_address.t also drops :80 so that it keeps matching. Recovered from the unmerged lenovobuild branch (cd61fd9d, a2f77ea9, 1035841b, b7db0e2, 792fe6d). Co-authored-by: Jarrod Johnson <10814490+jjohnson42@users.noreply.github.com> --- perl-xCAT/xCAT/DHCP/BootPolicy.pm | 4 ++- xCAT-server/lib/xcat/plugins/dhcp.pm | 42 +++++++++++++++++----------- xCAT-server/lib/xcat/plugins/mknb.pm | 21 +++++++------- xCAT-server/lib/xcat/plugins/xnba.pm | 21 +++++++------- xCAT-test/unit/dhcp_boot_policy.t | 25 +++++++++++++++-- xCAT-test/unit/mknb_xcatd_address.t | 30 +++++++++++++++++--- 6 files changed, 99 insertions(+), 44 deletions(-) diff --git a/perl-xCAT/xCAT/DHCP/BootPolicy.pm b/perl-xCAT/xCAT/DHCP/BootPolicy.pm index 3161693ea..4da2c7bf9 100644 --- a/perl-xCAT/xCAT/DHCP/BootPolicy.pm +++ b/perl-xCAT/xCAT/DHCP/BootPolicy.pm @@ -63,7 +63,9 @@ sub kea_xnba_node_classes { next unless $node->{node} && $node->{mac} && $node->{next_server}; my $class_base = _xnba_class_base( $node->{node}, $node->{mac} ); my $mac_test = _mac_test( $node->{mac} ); - my $base_url = 'http://' . $node->{next_server} . ':' . ( $node->{httpport} || '80' ) . '/tftpboot/xcat/xnba/nodes/' . $node->{node}; + my $httpport = $node->{httpport} || '80'; + my $portsuffix = ( $httpport eq '80' ) ? '' : ":$httpport"; + my $base_url = 'http://' . $node->{next_server} . $portsuffix . '/tftpboot/xcat/xnba/nodes/' . $node->{node}; push @classes, { name => "$class_base-bios", diff --git a/xCAT-server/lib/xcat/plugins/dhcp.pm b/xCAT-server/lib/xcat/plugins/dhcp.pm index f9cfcadd4..c121191da 100644 --- a/xCAT-server/lib/xcat/plugins/dhcp.pm +++ b/xCAT-server/lib/xcat/plugins/dhcp.pm @@ -654,6 +654,7 @@ sub addnode if ($hports[0]){ $httpport=$hports[0]; } + my $portsuffix = ( $httpport eq "80" ) ? "" : ":$httpport"; if ($chainents and $chainents->{$node}) { $chainent = $chainents->{$node}->[0]; @@ -857,12 +858,12 @@ sub addnode if (proxydhcp($nrent)) { #proxy dhcp required in uefi invocation $lstatements = 'if option client-architecture = 00:00 or option client-architecture = 00:07 or option client-architecture = 00:09 { filename = \"\"; option vendor-class-identifier \"PXEClient\"; } else { filename = \"\"; }' . $lstatements; #If proxydhcp daemon is enable, use it. } else { - $lstatements = 'if option user-class-identifier = \"xNBA\" and option client-architecture = 00:00 { always-broadcast on; filename = \"http://' . $nxtsrv . ':' . $httpport . '/tftpboot/xcat/xnba/nodes/' . $node . '\"; } else if option client-architecture = 00:07 or option client-architecture = 00:09 { filename = \"\"; option vendor-class-identifier \"PXEClient\"; } else if option client-architecture = 00:00 { filename = \"xcat/xnba.kpxe\"; } else { filename = \"\"; }' . $lstatements; #Only PXE compliant clients should ever receive xNBA + $lstatements = 'if option user-class-identifier = \"xNBA\" and option client-architecture = 00:00 { always-broadcast on; filename = \"http://' . $nxtsrv . $portsuffix . '/tftpboot/xcat/xnba/nodes/' . $node . '\"; } else if option client-architecture = 00:07 or option client-architecture = 00:09 { filename = \"\"; option vendor-class-identifier \"PXEClient\"; } else if option client-architecture = 00:00 { filename = \"xcat/xnba.kpxe\"; } else { filename = \"\"; }' . $lstatements; #Only PXE compliant clients should ever receive xNBA } } elsif ($douefi and $chainent->{currstate} ne "boot" and $chainent->{currstate} ne "iscsiboot") { - $lstatements = 'if option user-class-identifier = \"xNBA\" and option client-architecture = 00:00 { always-broadcast on; filename = \"http://' . $nxtsrv . ':' . $httpport . '/tftpboot/xcat/xnba/nodes/' . $node . '\"; } else if option user-class-identifier = \"xNBA\" and (option client-architecture = 00:09 or option client-architecture = 00:07) { filename = \"http://' . $nxtsrv .':' . $httpport . '/tftpboot/xcat/xnba/nodes/' . $node . '.uefi\"; } else if option client-architecture = 00:07 { filename = \"xcat/xnba.efi\"; } else if option client-architecture = 00:00 { filename = \"xcat/xnba.kpxe\"; } else { filename = \"\"; }' . $lstatements; #Only PXE compliant clients should ever receive xNBA + $lstatements = 'if option user-class-identifier = \"xNBA\" and option client-architecture = 00:00 { always-broadcast on; filename = \"http://' . $nxtsrv . $portsuffix . '/tftpboot/xcat/xnba/nodes/' . $node . '\"; } else if option user-class-identifier = \"xNBA\" and (option client-architecture = 00:09 or option client-architecture = 00:07) { filename = \"http://' . $nxtsrv . $portsuffix . '/tftpboot/xcat/xnba/nodes/' . $node . '.uefi\"; } else if option client-architecture = 00:07 { filename = \"xcat/xnba.efi\"; } else if option client-architecture = 00:00 { filename = \"xcat/xnba.kpxe\"; } else { filename = \"\"; }' . $lstatements; #Only PXE compliant clients should ever receive xNBA } else { - $lstatements = 'if option user-class-identifier = \"xNBA\" and option client-architecture = 00:00 { filename = \"http://' . $nxtsrv .':' . $httpport . '/tftpboot/xcat/xnba/nodes/' . $node . '\"; } else if option client-architecture = 00:00 { filename = \"xcat/xnba.kpxe\"; } else { filename = \"\"; }' . $lstatements; #Only PXE compliant clients should ever receive xNBA + $lstatements = 'if option user-class-identifier = \"xNBA\" and option client-architecture = 00:00 { filename = \"http://' . $nxtsrv . $portsuffix . '/tftpboot/xcat/xnba/nodes/' . $node . '\"; } else if option client-architecture = 00:00 { filename = \"xcat/xnba.kpxe\"; } else { filename = \"\"; }' . $lstatements; #Only PXE compliant clients should ever receive xNBA } } } #TODO: warn when windows @@ -879,7 +880,7 @@ sub addnode } elsif ($nrent and $nrent->{netboot} and $nrent->{netboot} =~ /^grub2[-]?.*$/) { $lstatements = 'filename = \"/boot/grub2/grub2-' . $node . '\";' . $lstatements; } elsif ($nrent and $nrent->{netboot} and $nrent->{netboot} eq 'petitboot') { - $lstatements = 'option conf-file \"http://' . $nxtsrv .':' . $httpport . '/tftpboot/petitboot/' . $node . '\";' . $lstatements; + $lstatements = 'option conf-file \"http://' . $nxtsrv . $portsuffix . '/tftpboot/petitboot/' . $node . '\";' . $lstatements; } elsif ($nrent and $nrent->{netboot} and $nrent->{netboot} eq 'onie') { my $provmethod = $ntent->{provmethod}; if ($provmethod) { @@ -891,7 +892,7 @@ sub addnode my $validpkgdir; foreach my $mypkgdir (@pkgdirs){ if (-f $mypkgdir) { - $lstatements = 'if substring (option vendor-class-identifier,0,11) = \"onie_vendor\" { option www-server = \"http://' . $nxtsrv .':' . $httpport . $mypkgdir . '\";}' . $lstatements; + $lstatements = 'if substring (option vendor-class-identifier,0,11) = \"onie_vendor\" { option www-server = \"http://' . $nxtsrv . $portsuffix . $mypkgdir . '\";}' . $lstatements; $validpkgdir = 1; last; } @@ -2540,6 +2541,7 @@ sub kea_build_dhcp4_intent if ($hports[0]) { $httpport = $hports[0]; } + my $portsuffix = ( $httpport eq "80" ) ? "" : ":$httpport"; my $nettab = xCAT::Table->new("networks"); return { error => "Unable to open networks table, please run makenetworks" } unless $nettab; @@ -2926,6 +2928,7 @@ sub kea_command_path sub kea_subnet4_intent { my ( $nettab, $net, $mask, $interface, $remote, $id, $httpport ) = @_; + my $portsuffix = ( $httpport eq "80" ) ? "" : ":$httpport"; my @myipd = xCAT::NetworkUtils->my_ip_facing($net); my $myip; @@ -2984,7 +2987,7 @@ sub kea_subnet4_intent push @option_data, { name => 'domain-name-servers', data => $nameservers }; } push @option_data, { name => 'interface-mtu', data => $ent->{mtu} } if $ent && $ent->{mtu}; - push @option_data, { name => 'cumulus-provision-url', data => "http://$tftp:$httpport/install/postscripts/cumulusztp" } if $tftp; + push @option_data, { name => 'cumulus-provision-url', data => "http://$tftp$portsuffix/install/postscripts/cumulusztp" } if $tftp; my $domainstring = join(', ', map { $_ eq $domain ? $_ : $_ } grep { $_ } @alldomains); push @option_data, { name => 'domain-search', data => $domainstring } if $domainstring; @@ -3015,6 +3018,7 @@ sub kea_subnet4_intent sub kea_opal_client_class { my ( $net, $prefix, $tftp, $httpport ) = @_; + my $portsuffix = ( $httpport eq "80" ) ? "" : ":$httpport"; return unless $net && defined($prefix) && $tftp; @@ -3028,7 +3032,7 @@ sub kea_opal_client_class 'option-data' => [ { name => 'conf-file', - data => "http://$tftp:$httpport/tftpboot/pxelinux.cfg/p/" . $net . "_" . $prefix, + data => "http://$tftp$portsuffix/tftpboot/pxelinux.cfg/p/" . $net . "_" . $prefix, }, ], }; @@ -3232,6 +3236,7 @@ sub kea_xnba_client_classes_for_nodes if ($hports[0]) { $httpport = $hports[0]; } + my $portsuffix = ( $httpport eq "80" ) ? "" : ":$httpport"; my @records; foreach my $node (@$nodes) { @@ -3442,6 +3447,7 @@ sub kea_boot_for_node if ($hports[0]) { $httpport = $hports[0]; } + my $portsuffix = ( $httpport eq "80" ) ? "" : ":$httpport"; my %boot = ( 'option-data' => [] ); my $netboot = $nrent ? $nrent->{netboot} : undef; @@ -3461,7 +3467,7 @@ sub kea_boot_for_node $boot{'boot-file-name'} = "/boot/grub2/grub2-$node"; } elsif ($netboot and $netboot eq 'petitboot') { if ($nxtsrv) { - my $petitboot_conf = "http://$nxtsrv:$httpport/tftpboot/petitboot/$node"; + my $petitboot_conf = "http://$nxtsrv$portsuffix/tftpboot/petitboot/$node"; $boot{'boot-file-name'} = $petitboot_conf; push @{ $boot{'option-data'} }, { name => 'conf-file', data => $petitboot_conf }; } @@ -3477,17 +3483,18 @@ sub kea_boot_for_node sub kea_onie_url_for_node { my ( $node, $ntent, $nxtsrv, $httpport ) = @_; + my $portsuffix = ( $httpport eq "80" ) ? "" : ":$httpport"; return unless $nxtsrv; my $provmethod = $ntent ? $ntent->{provmethod} : undef; - return "http://$nxtsrv:$httpport/install/onie/onie-installer" unless $provmethod; + return "http://$nxtsrv$portsuffix/install/onie/onie-installer" unless $provmethod; my $linuximagetab = xCAT::Table->new('linuximage'); my $imagetab = $linuximagetab ? $linuximagetab->getAttribs({ imagename => $provmethod }, 'pkgdir') : undef; - return "http://$nxtsrv:$httpport/install/onie/onie-installer" unless $imagetab; + return "http://$nxtsrv$portsuffix/install/onie/onie-installer" unless $imagetab; foreach my $pkgdir (split(/,/, $imagetab->{pkgdir} || '')) { - return "http://$nxtsrv:$httpport$pkgdir" if -f $pkgdir; + return "http://$nxtsrv$portsuffix$pkgdir" if -f $pkgdir; } $callback->({ warning => ["osimage $provmethod pkgdir doesn't exists"]}); @@ -3836,6 +3843,7 @@ sub addnet if ($hports[0]){ $httpport=$hports[0]; } + my $portsuffix = ( $httpport eq "80" ) ? "" : ":$httpport"; my $firstoctet = $net; $firstoctet =~ s/^(\d+)\..*/$1/; if ($net eq "169.254.0.0" or ($firstoctet >= 224 and $firstoctet <= 239)) { @@ -4118,7 +4126,7 @@ sub addnet } } #for cumulus ZTP process - push @netent, " option cumulus-provision-url \"http://$tftp:$httpport/install/postscripts/cumulusztp\";\n"; + push @netent, " option cumulus-provision-url \"http://$tftp$portsuffix/install/postscripts/cumulusztp\";\n"; my $ddnserver = $nameservers; $ddnserver =~ s/,.*//; @@ -4161,11 +4169,11 @@ sub addnet # $lstatements = 'if exists gpxe.bus-id { filename = \"\"; } else if exists client-architecture { filename = \"xcat/xnba.kpxe\"; } '.$lstatements; push @netent, " if option user-class-identifier = \"xNBA\" and option client-architecture = 00:00 { #x86, xCAT Network Boot Agent\n"; push @netent, " always-broadcast on;\n"; - push @netent, " filename = \"http://$tftp:$httpport/tftpboot/xcat/xnba/nets/" . $net . "_" . $maskbits . "\";\n"; + push @netent, " filename = \"http://$tftp$portsuffix/tftpboot/xcat/xnba/nets/" . $net . "_" . $maskbits . "\";\n"; push @netent, " } else if option user-class-identifier = \"xNBA\" and option client-architecture = 00:09 { #x86, xCAT Network Boot Agent\n"; - push @netent, " filename = \"http://$tftp:$httpport/tftpboot/xcat/xnba/nets/" . $net . "_" . $maskbits . ".uefi\";\n"; + push @netent, " filename = \"http://$tftp$portsuffix/tftpboot/xcat/xnba/nets/" . $net . "_" . $maskbits . ".uefi\";\n"; push @netent, " } else if option user-class-identifier = \"xNBA\" and option client-architecture = 00:07 { #x86-64 UEFI, xCAT Network Boot Agent\n"; - push @netent, " filename = \"http://$tftp:$httpport/tftpboot/xcat/xnba/nets/" . $net . "_" . $maskbits . ".uefi\";\n"; + push @netent, " filename = \"http://$tftp$portsuffix/tftpboot/xcat/xnba/nets/" . $net . "_" . $maskbits . ".uefi\";\n"; push @netent, " } else if option client-architecture = 00:00 { #x86\n"; push @netent, " filename \"xcat/xnba.kpxe\";\n"; push @netent, " } else if option vendor-class-identifier = \"Etherboot-5.4\" { #x86\n"; @@ -4184,10 +4192,10 @@ sub addnet push @netent, " filename \"boot/grub2/grub2.aarch64\";\n"; push @netent, " } else if option client-architecture = 00:0e { #OPAL-v3\n "; - push @netent, " option conf-file = \"http://$tftp:$httpport/tftpboot/pxelinux.cfg/p/" . $net . "_" . $maskbits . "\";\n"; + push @netent, " option conf-file = \"http://$tftp$portsuffix/tftpboot/pxelinux.cfg/p/" . $net . "_" . $maskbits . "\";\n"; push @netent, " } else if substring (option vendor-class-identifier,0,11) = \"onie_vendor\" { #for onie on cumulus switch\n"; - push @netent, " option www-server = \"http://$tftp:$httpport/install/onie/onie-installer\";\n"; + push @netent, " option www-server = \"http://$tftp$portsuffix/install/onie/onie-installer\";\n"; push @netent, " } else if substring(filename,0,1) = null { #otherwise, provide yaboot if the client isn't specific\n "; push @netent, " filename \"/yaboot\";\n"; diff --git a/xCAT-server/lib/xcat/plugins/mknb.pm b/xCAT-server/lib/xcat/plugins/mknb.pm index 54c613574..fd44dbb57 100644 --- a/xCAT-server/lib/xcat/plugins/mknb.pm +++ b/xCAT-server/lib/xcat/plugins/mknb.pm @@ -73,6 +73,7 @@ sub process_request { if ($hports[0]){ $httpport=$hports[0]; } + my $portsuffix = ( $httpport eq "80" ) ? "" : ":$httpport"; @entries = xCAT::TableUtils->get_site_attribute("dhcpinterfaces"); $t_entry = $entries[0]; @@ -384,11 +385,11 @@ sub process_request { open($cfg, ">", "$tftpdir/xcat/xnba/nets/$net"); print $cfg "#!gpxe\n"; if ($invisibletouch) { - print $cfg 'imgfetch -n kernel http://${next-server}:'.$httpport.'/tftpboot/xcat/genesis.kernel.' . "$arch xcatd=" . $xcatd_address . ":$xcatdport $consolecmdline BOOTIF=01-" . '${netX/machyp}' . "\n"; - print $cfg 'imgfetch -n nbfs http://${next-server}:'.$httpport . "$initrd_file\n"; + print $cfg 'imgfetch -n kernel http://${next-server}'.$portsuffix.'/tftpboot/xcat/genesis.kernel.' . "$arch xcatd=" . $xcatd_address . ":$xcatdport $consolecmdline BOOTIF=01-" . '${netX/machyp}' . "\n"; + print $cfg 'imgfetch -n nbfs http://${next-server}'.$portsuffix . "$initrd_file\n"; } else { - print $cfg 'imgfetch -n kernel http://${next-server}:'.$httpport.'/tftpboot/xcat/nbk.' . "$arch xcatd=" . $xcatd_address . ":$xcatdport $consolecmdline\n"; - print $cfg 'imgfetch -n nbfs http://${next-server}:'.$httpport . "$initrd_file\n"; + print $cfg 'imgfetch -n kernel http://${next-server}'.$portsuffix.'/tftpboot/xcat/nbk.' . "$arch xcatd=" . $xcatd_address . ":$xcatdport $consolecmdline\n"; + print $cfg 'imgfetch -n nbfs http://${next-server}'.$portsuffix . "$initrd_file\n"; } print $cfg "imgload kernel\n"; print $cfg "imgexec kernel\n"; @@ -404,9 +405,9 @@ sub process_request { close($cfg); open($cfg, ">", "$tftpdir/xcat/xnba/nets/$net.uefi"); print $cfg "#!gpxe\n"; - print $cfg 'imgfetch -n kernel http://${next-server}:'.$httpport.'/tftpboot/xcat/genesis.kernel.' . "$arch\nimgload kernel\n"; + print $cfg 'imgfetch -n kernel http://${next-server}'.$portsuffix.'/tftpboot/xcat/genesis.kernel.' . "$arch\nimgload kernel\n"; print $cfg "imgargs kernel xcatd=" . $xcatd_address . ":$xcatdport $consolecmdline BOOTIF=01-" . '${netX/mac:hexhyp}' . " destiny=discover initrd=initrd\n"; - print $cfg 'imgfetch -n initrd http://${next-server}:'.$httpport . "$initrd_file\nimgexec kernel\n"; + print $cfg 'imgfetch -n initrd http://${next-server}'.$portsuffix . "$initrd_file\nimgexec kernel\n"; close($cfg); } } elsif ($arch =~ /ppc/) { @@ -414,8 +415,8 @@ sub process_request { print $cfgfile "default \"xCAT Genesis (" . $normnets->{$_} . ")\"\n"; print $cfgfile " delay=10\n"; print $cfgfile " label \"xCAT Genesis (" . $normnets->{$_} . ")\"\n"; - print $cfgfile " kernel http://" . $xcatd_address . ":$httpport/$tftpdir/xcat/genesis.kernel.$arch\n"; - print $cfgfile " initrd http://" . $xcatd_address . ":$httpport/$initrd_file\n"; + print $cfgfile " kernel http://" . $xcatd_address . "$portsuffix/$tftpdir/xcat/genesis.kernel.$arch\n"; + print $cfgfile " initrd http://" . $xcatd_address . "$portsuffix/$initrd_file\n"; print $cfgfile ' append "xcatd=' . $xcatd_address . ":$xcatdport $consolecmdline\"\n"; close($cfgfile); } @@ -454,8 +455,8 @@ sub process_request { print $cfgfile "default \"xCAT Genesis (" . $normnets->{$_} . ")\"\n"; print $cfgfile " delay=10\n"; print $cfgfile " label \"xCAT Genesis (" . $normnets->{$_} . ")\"\n"; - print $cfgfile " kernel http://" . $xcatd_address . ":$httpport/$tftpdir/xcat/genesis.kernel.$arch\n"; - print $cfgfile " initrd http://" . $xcatd_address . ":$httpport/$initrd_file\n"; + print $cfgfile " kernel http://" . $xcatd_address . "$portsuffix/$tftpdir/xcat/genesis.kernel.$arch\n"; + print $cfgfile " initrd http://" . $xcatd_address . "$portsuffix/$initrd_file\n"; print $cfgfile ' append "xcatd=' . $xcatd_address . ":$xcatdport $consolecmdline\"\n"; close($cfgfile); } diff --git a/xCAT-server/lib/xcat/plugins/xnba.pm b/xCAT-server/lib/xcat/plugins/xnba.pm index 88c09c5e6..e0a7c3026 100644 --- a/xCAT-server/lib/xcat/plugins/xnba.pm +++ b/xCAT-server/lib/xcat/plugins/xnba.pm @@ -152,6 +152,7 @@ sub setstate { if ($hports[0]){ $httpport=$hports[0]; } + my $portsuffix = ( $httpport eq "80" ) ? "" : ":$httpport"; # get kernel and initrd from boottarget table my $bttab; @@ -290,8 +291,8 @@ sub setstate { my $kernel; ($kernel, $hypervisor) = split /!/, $kern->{kernel}; print $pcfg " set 209:string xcat/xnba/nodes/$node.pxelinux\n"; - print $pcfg " set 210:string http://" . '${next-server}'. ':' . $httpport . "/tftpboot/\n"; - print $pcfg " imgfetch -n pxelinux.0 http://" . '${next-server}' . ':' . $httpport . "/tftpboot/xcat/pxelinux.0\n"; + print $pcfg " set 210:string http://" . '${next-server}' . $portsuffix . "/tftpboot/\n"; + print $pcfg " imgfetch -n pxelinux.0 http://" . '${next-server}' . $portsuffix . "/tftpboot/xcat/pxelinux.0\n"; print $pcfg " imgload pxelinux.0\n"; print $pcfg " imgexec pxelinux.0\n"; close($pcfg); @@ -301,8 +302,8 @@ sub setstate { } else { if ($kern->{kernel} =~ /\.c32\z/ or $kern->{kernel} =~ /memdisk\z/) { #gPXE comboot support seems insufficient, chain pxelinux instead print $pcfg " set 209:string xcat/xnba/nodes/$node.pxelinux\n"; - print $pcfg " set 210:string http://" . '${next-server}' . ':' . $httpport . "/tftpboot/\n"; - print $pcfg " imgfetch -n pxelinux.0 http://" . '${next-server}' . ':' . $httpport . "/tftpboot/xcat/pxelinux.0\n"; + print $pcfg " set 210:string http://" . '${next-server}' . $portsuffix . "/tftpboot/\n"; + print $pcfg " imgfetch -n pxelinux.0 http://" . '${next-server}' . $portsuffix . "/tftpboot/xcat/pxelinux.0\n"; print $pcfg " imgload pxelinux.0\n"; print $pcfg " imgexec pxelinux.0\n"; close($pcfg); @@ -330,11 +331,11 @@ sub setstate { $kern->{kcmdline} =~ s/xcat\/netboot/\/tftpboot\/xcat\/netboot/; } print $ucfg "#!gpxe\n"; - print $ucfg 'chain http://${next-server}:'.$httpport.'/tftpboot/xcat/esxboot-x64.efi ' . $kern->{kcmdline} . "\n"; + print $ucfg 'chain http://${next-server}'.$portsuffix.'/tftpboot/xcat/esxboot-x64.efi ' . $kern->{kcmdline} . "\n"; close($ucfg); } } else { #other than comboot/multiboot, we won't have need of pxelinux - print $pcfg "imgfetch -n kernel http://" . '${next-server}:' . $httpport.'/tftpboot/' . $kern->{kernel} . "\n"; + print $pcfg "imgfetch -n kernel http://" . '${next-server}' . $portsuffix.'/tftpboot/' . $kern->{kernel} . "\n"; print $pcfg "imgload kernel\n"; if ($kern->{kcmdline}) { print $pcfg "imgargs kernel " . $kern->{kcmdline} . ' BOOTIF=01-${netX/machyp}' . "\n"; @@ -342,7 +343,7 @@ sub setstate { print $pcfg "imgargs kernel BOOTIF=" . '${netX/mac}' . "\n"; } if ($kern->{initrd}) { - print $pcfg "imgfetch -n initrd http://" . '${next-server}:' . "$httpport/tftpboot/" . $kern->{initrd} . "\n"; + print $pcfg "imgfetch -n initrd http://" . '${next-server}' . "$portsuffix/tftpboot/" . $kern->{initrd} . "\n"; } print $pcfg "imgexec kernel\n"; if ($kern->{kcmdline} and $kern->{initrd}) { #only a linux kernel/initrd pair should land here, write elilo config and uefi variant of xnba config file @@ -350,19 +351,19 @@ sub setstate { open($ucfg, '>', $tftpdir . "/xcat/xnba/nodes/" . $node . ".uefi"); if (_use_efistub_for_uefi($kern)) { print $ucfg "#!gpxe\n"; - print $ucfg "imgfetch -n kernel http://" . '${next-server}:' . $httpport.'/tftpboot/' . $kern->{kernel} . "\n"; + print $ucfg "imgfetch -n kernel http://" . '${next-server}' . $portsuffix.'/tftpboot/' . $kern->{kernel} . "\n"; print $ucfg "imgload kernel\n"; if ($kern->{kcmdline}) { print $ucfg "imgargs kernel " . $kern->{kcmdline} . ' BOOTIF=01-${netX/mac:hexhyp} initrd=initrd' . "\n"; } else { print $ucfg "imgargs kernel BOOTIF=" . '${netX/mac} initrd=initrd' . "\n"; } - print $ucfg "imgfetch -n initrd http://" . '${next-server}:' . "$httpport/tftpboot/" . $kern->{initrd} . "\n"; + print $ucfg "imgfetch -n initrd http://" . '${next-server}' . "$portsuffix/tftpboot/" . $kern->{initrd} . "\n"; print $ucfg "imgexec kernel\n"; close($ucfg); } else { print $ucfg "#!gpxe\n"; - print $ucfg 'chain http://${next-server}:'.$httpport.'/tftpboot/xcat/elilo-x64.efi -C /tftpboot/xcat/xnba/nodes/' . $node . ".elilo\n"; + print $ucfg 'chain http://${next-server}'.$portsuffix.'/tftpboot/xcat/elilo-x64.efi -C /tftpboot/xcat/xnba/nodes/' . $node . ".elilo\n"; close($ucfg); open($ucfg, '>', $tftpdir . "/xcat/xnba/nodes/" . $node . ".elilo"); print $ucfg 'default="xCAT"' . "\n"; diff --git a/xCAT-test/unit/dhcp_boot_policy.t b/xCAT-test/unit/dhcp_boot_policy.t index fab0c2afd..8b0f823ae 100644 --- a/xCAT-test/unit/dhcp_boot_policy.t +++ b/xCAT-test/unit/dhcp_boot_policy.t @@ -46,13 +46,34 @@ ok( $xnba_bios, 'xNBA BIOS second-stage class is named by node and MAC' ); like( $xnba_bios->{test}, qr/option\[77\]\.text == 'xNBA'/, 'xNBA second-stage class matches text user-class' ); like( $xnba_bios->{test}, qr/substring\(option\[77\]\.hex,1,4\) == 'xNBA'/, 'xNBA second-stage class matches tuple-encoded user-class' ); like( $xnba_bios->{test}, qr/pkt4\.mac == 0x52544b100011/, 'xNBA second-stage class matches the node MAC' ); -is( $xnba_bios->{'boot-file-name'}, 'http://10.241.10.1:80/tftpboot/xcat/xnba/nodes/cn01', 'xNBA BIOS class returns the node script URL' ); +is( $xnba_bios->{'boot-file-name'}, 'http://10.241.10.1/tftpboot/xcat/xnba/nodes/cn01', 'xNBA BIOS class returns the node script URL without the default HTTP port' ); is( $xnba_bios->{'user-context'}{'xcat-purpose'}, 'xnba-second-stage', 'xNBA class carries removable user-context' ); -is( $xnba_by_name{'xcat-xnba-cn01-52544b100011-uefi'}{'boot-file-name'}, 'http://10.241.10.1:80/tftpboot/xcat/xnba/nodes/cn01.uefi', 'xNBA UEFI class returns the UEFI node script URL' ); +is( $xnba_by_name{'xcat-xnba-cn01-52544b100011-uefi'}{'boot-file-name'}, 'http://10.241.10.1/tftpboot/xcat/xnba/nodes/cn01.uefi', 'xNBA UEFI class returns the UEFI node script URL without the default HTTP port' ); like( $xnba_by_name{'xcat-xnba-cn01-52544b100011-uefi'}{test}, qr/0x0007/, 'xNBA UEFI class matches standard UEFI PXE architecture 7' ); like( $xnba_by_name{'xcat-xnba-cn01-52544b100011-uefi'}{test}, qr/0x0009/, 'xNBA UEFI class matches alternate UEFI PXE architecture 9' ); like( $xnba_by_name{'xcat-xnba-cn01-52544b100011-uefi'}{test}, qr/0x0010/, 'xNBA UEFI class matches UEFI HTTP boot architecture 16' ); +my $altport_classes = xCAT::DHCP::BootPolicy->kea_xnba_node_classes( + xnba_efi => 1, + nodes => [ + { + node => 'cn02', + mac => '52:54:4b:10:00:12', + next_server => '10.241.10.1', + httpport => '8080', + }, + { + node => 'cn03', + mac => '52:54:4b:10:00:13', + next_server => '10.241.10.1', + }, + ], +); +my %altport_by_name = map { $_->{name} => $_ } @$altport_classes; +is( $altport_by_name{'xcat-xnba-cn02-52544b100012-bios'}{'boot-file-name'}, 'http://10.241.10.1:8080/tftpboot/xcat/xnba/nodes/cn02', 'a non-default HTTP port is kept in the node script URL' ); +is( $altport_by_name{'xcat-xnba-cn02-52544b100012-uefi'}{'boot-file-name'}, 'http://10.241.10.1:8080/tftpboot/xcat/xnba/nodes/cn02.uefi', 'a non-default HTTP port is kept in the UEFI node script URL' ); +is( $altport_by_name{'xcat-xnba-cn03-52544b100013-bios'}{'boot-file-name'}, 'http://10.241.10.1/tftpboot/xcat/xnba/nodes/cn03', 'an unset HTTP port falls back to the default and is omitted' ); + my $combined_classes = xCAT::DHCP::BootPolicy->kea_client_classes( xnba_kpxe => 1, xnba_efi => 1, diff --git a/xCAT-test/unit/mknb_xcatd_address.t b/xCAT-test/unit/mknb_xcatd_address.t index f68c4362c..9af5e1b18 100644 --- a/xCAT-test/unit/mknb_xcatd_address.t +++ b/xCAT-test/unit/mknb_xcatd_address.t @@ -13,11 +13,12 @@ BEGIN { $INC{'xCAT/Utils.pm'} = __FILE__; package xCAT::TableUtils; - our ($tftpdir, $site_master); + our ($tftpdir, $site_master, $site_httpport); sub getTftpDir { return $tftpdir; } sub get_site_attribute { my $attribute = $_[-1]; return ($site_master) if $attribute eq 'master'; + return ($site_httpport) if $attribute eq 'httpport' and defined $site_httpport; return; } $INC{'xCAT/TableUtils.pm'} = __FILE__; @@ -214,12 +215,12 @@ foreach my $relative_path ( my $content = read_config("$xCAT::TableUtils::tftpdir/$relative_path"); like( $content, - qr/kernel http:\/\/192\.168\.148\.10:80\//, + qr/kernel http:\/\/192\.168\.148\.10\//, "$relative_path uses the first address for the kernel URL", ); like( $content, - qr/initrd http:\/\/192\.168\.148\.10:80\//, + qr/initrd http:\/\/192\.168\.148\.10\//, "$relative_path uses the first address for the initrd URL", ); like( @@ -229,11 +230,32 @@ foreach my $relative_path ( ); unlike( $content, - qr/(?:kernel|initrd) http:\/\/192\.168\.149\.100:80\/|xcatd=192\.168\.149\.100:3001/, + qr/(?:kernel|initrd) http:\/\/192\.168\.149\.100\/|xcatd=192\.168\.149\.100:3001/, "$relative_path has no functional endpoint using the later floating address", ); } +# the default HTTP port is left out of the generated URLs, but a port that is +# not the default still has to be carried through +$xCAT::TableUtils::site_httpport = '8080'; +use_reporter_address_maps(); +prepare_tftpdir($tmpdir, 'tftpboot-power-altport', 'ppc64'); +$responses = run_mknb('ppc64'); +generation_succeeded($responses, 'POWER configuration generation succeeds with a non-default HTTP port'); + +my $altport_content = read_config("$xCAT::TableUtils::tftpdir/pxelinux.cfg/p/192.168.144.0_20"); +like( + $altport_content, + qr/kernel http:\/\/192\.168\.148\.10:8080\//, + 'a non-default HTTP port is kept in the kernel URL', +); +like( + $altport_content, + qr/initrd http:\/\/192\.168\.148\.10:8080\//, + 'a non-default HTTP port is kept in the initrd URL', +); +$xCAT::TableUtils::site_httpport = undef; + $xCAT::NetworkUtils::normnet_addresses = { '192.168.144.0/20' => ['192.168.148.10'], };