From 45144f5a5bcbe5314c375a3bb1c2b6ef930119c0 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, 2 Oct 2026 21:44:29 -0300 Subject: [PATCH] test(dhcp): cover an xnba node with the xNBA UEFI file only The renderer gives the node its UEFI first-stage class. kea-dhcp4 then gives xNBA to a UEFI firmware client of the node, and the node script to xNBA. --- xCAT-test/integration/dhcp_ipxe_dispatch.t | 23 ++++++++++++++-------- xCAT-test/unit/dhcp_boot_policy.t | 12 ++++++++++- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/xCAT-test/integration/dhcp_ipxe_dispatch.t b/xCAT-test/integration/dhcp_ipxe_dispatch.t index db73d5f04..07b35de72 100644 --- a/xCAT-test/integration/dhcp_ipxe_dispatch.t +++ b/xCAT-test/integration/dhcp_ipxe_dispatch.t @@ -302,7 +302,7 @@ if ( grep { $_ eq 'kea' } @backends ) { my $network_classes = xCAT::DHCP::BootPolicy->kea_xnba_network_classes( net => '192.0.2.0', prefix => 24, next_server => '192.0.2.1', %upstream ); my $run_kea = sub { - my ( $label, $option_defs, $globals, $xnba_efi, $extra, @rows ) = @_; + my ( $label, $option_defs, $globals, $xnba_files, $extra, @rows ) = @_; my $config = JSON::decode_json( $backend->render_dhcp4_config( { interfaces => ["${interface}s"], @@ -311,9 +311,8 @@ if ( grep { $_ eq 'kea' } @backends ) { 'client-classes' => [ @$extra, @{ xCAT::DHCP::BootPolicy->kea_xnba_node_classes( - xnba_kpxe => 1, - xnba_efi => $xnba_efi, - nodes => [ + %$xnba_files, + nodes => [ map { { node => $_->{name}, mac => $_->{mac}, next_server => '192.0.2.1', netboot => $_->{netboot}, iscsi => $_->{iscsi} } } \%xnba, \%ipxe, \%xnba_san, \%ipxe_san ], @@ -352,7 +351,8 @@ if ( grep { $_ eq 'kea' } @backends ) { my @old_defs = ( { name => 'conf-file', code => 209, type => 'string', space => 'dhcp4' } ); my @defs = ( @old_defs, @{ xCAT::DHCP::BootPolicy->kea_ipxe_option_defs() } ); my $globals = xCAT::DHCP::BootPolicy->kea_client_classes(%upstream); - $run_kea->( 'Kea', \@defs, $globals, 1, [], @node_rows, @network_rows, @san_rows ); + my %xnba_files = ( xnba_kpxe => 1, xnba_efi => 1 ); + $run_kea->( 'Kea', \@defs, $globals, {%xnba_files}, [], @node_rows, @network_rows, @san_rows ); # A SAN node in the boot state gets the loader of its method only on a client without iSCSI. A # client with iSCSI gets no boot file, though the subnet offers its network scripts. @@ -361,15 +361,22 @@ if ( grep { $_ eq 'kea' } @backends ) { @{ xCAT::DHCP::BootPolicy->kea_xnba_node_classes( xnba_kpxe => 1, xnba_efi => 1, nodes => $san_nodes ) }, xCAT::DHCP::BootPolicy->kea_localboot_client_class( macs => [ map { { node => $_->{node}, mac => $_->{mac}, san => 1 } } @$san_nodes ] ), ); - $run_kea->( 'Kea, SAN nodes in the boot state', \@defs, $globals, 1, \@san_boot, @kea_iscsi_rows ); + $run_kea->( 'Kea, SAN nodes in the boot state', \@defs, $globals, {%xnba_files}, \@san_boot, @kea_iscsi_rows ); # Without the local xNBA UEFI file the UEFI clients of an xnba node still get that file, as in ISC, and # not the upstream loader and the discovery script that the global classes give unknown clients. - $run_kea->( 'Kea, no xNBA UEFI file', \@defs, $globals, 0, [], map { [ "xnba node, $_->[0]", { mac => $xnba{mac}, %{ $_->[1] } }, $first{xnba}{uefi} ] } ( + $run_kea->( 'Kea, no xNBA UEFI file', \@defs, $globals, { xnba_kpxe => 1 }, [], map { [ "xnba node, $_->[0]", { mac => $xnba{mac}, %{ $_->[1] } }, $first{xnba}{uefi} ] } ( [ 'firmware PXE, UEFI', { arch => 7 } ], [ 'iPXE with HTTP and EFI, UEFI', { arch => 7, user_class => 'iPXE', ipxe => ipxe(qw(http efi)) } ], ) ); + # With the local xNBA UEFI file only, the UEFI clients of an xnba node still get xNBA and then the + # node script, as the global UEFI class gives only the upstream loader. + $run_kea->( 'Kea, no xNBA BIOS file', \@defs, $globals, { xnba_efi => 1 }, [], map { [ "xnba node, $_->[0]", { mac => $xnba{mac}, %{ $_->[1] } }, $_->[2] ] } ( + [ 'firmware PXE, UEFI', { arch => 7 }, $first{xnba}{uefi} ], + [ 'xNBA, UEFI arch 7', { arch => 7, user_class => 'xNBA', ipxe => ipxe(qw(http efi iscsi)) }, "http://192.0.2.1/tftpboot/xcat/xnba/nodes/$xnba{name}.uefi" ], + ) ); + # makedhcp without -n adds the iPXE feature options to the configuration of an older makedhcp -n, # and keeps the x86 global classes that it wrote, which give xNBA to every client. my $upgraded = { 'option-def' => [@old_defs] }; @@ -383,7 +390,7 @@ if ( grep { $_ eq 'kea' } @backends ) { 'boot-file-name' => 'xcat/xnba.efi', }, ); - $run_kea->( 'Kea, upgraded', $upgraded->{'option-def'}, \@old_globals, 1, [], grep { $_->[0] =~ /^ipxe / } @node_rows, @san_rows ); + $run_kea->( 'Kea, upgraded', $upgraded->{'option-def'}, \@old_globals, {%xnba_files}, [], grep { $_->[0] =~ /^ipxe / } @node_rows, @san_rows ); } done_testing(); diff --git a/xCAT-test/unit/dhcp_boot_policy.t b/xCAT-test/unit/dhcp_boot_policy.t index 513bcf732..fa24b2f3e 100644 --- a/xCAT-test/unit/dhcp_boot_policy.t +++ b/xCAT-test/unit/dhcp_boot_policy.t @@ -532,7 +532,8 @@ is_deeply( xCAT::DHCP::BootPolicy->kea_xnba_network_classes( net => '192.0.2.0', 'the network classes need a next server' ); # The global classes now give the upstream loader, so an xnba node carries the first stage of xNBA -# when this server has the xNBA BIOS file, as it has its ISC host statements. +# when this server has the xNBA BIOS file, as it has its ISC host statements, and the UEFI one when it +# has the xNBA UEFI file. my %xnba_first = ( node => 'cn02', mac => '52:54:00:00:00:02', next_server => '192.0.2.10', netboot => 'xnba' ); my $xnba_first_context = { 'xcat-mac' => '52:54:00:00:00:02', 'xcat-node' => 'cn02', 'xcat-purpose' => 'xnba-first-stage' }; is_deeply( @@ -567,6 +568,15 @@ is_deeply( ['xcat-xnba-cn02-525400000002-bios'], 'without the local xNBA BIOS file, an xnba node has no first-stage classes, as it has no ISC host statements' ); +is_deeply( + [ map { [ $_->{name}, $_->{'boot-file-name'} ] } @{ xCAT::DHCP::BootPolicy->kea_xnba_node_classes( xnba_efi => 1, nodes => [ {%xnba_first} ] ) } ], + [ + [ 'xcat-xnba-cn02-525400000002-bios', 'http://192.0.2.10/tftpboot/xcat/xnba/nodes/cn02' ], + [ 'xcat-xnba-cn02-525400000002-uefi', 'http://192.0.2.10/tftpboot/xcat/xnba/nodes/cn02.uefi' ], + [ 'xcat-xnba-cn02-525400000002-uefi-first-stage', 'xcat/xnba.efi' ], + ], + 'with the local xNBA UEFI file only, an xnba node gets xNBA for UEFI from its own first-stage class' +); is_deeply( [ map { [ $_->{name}, $_->{'boot-file-name'} ] } grep { $_->{name} =~ /-first-stage$/ } @{ xCAT::DHCP::BootPolicy->kea_xnba_node_classes( nodes => [ {%ipxe_node} ] ) } ],