2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-05 20:47:55 +00:00
Files
xcat-core/xCAT-test/integration/dhcp_kea_config_validation.t
T
Daniel Hilst 6ab9aca0b7 fix(xcat-core): split the source-only unit tests from the MN integration tests
Three of the files under xCAT-test/unit are not unit tests. They need an
installed management node rather than a checkout: copycds_packages_integrity.t
wants an /install populated by a real copycds, dhcp_kea_config_validation.t
wants a kea-dhcp4 binary that can read the config it generates, and
dhcp_kea_control_agent_smoke.t wants live kea-dhcp4 and kea-ctrl-agent
daemons running as root.

On a GitHub runner none of that exists, so all three plan skip_all. They were
the only three files skipping in the pull request run, which is not a
coincidence -- the skip is the symptom of them being filed in the wrong place.
A skipped test reports neither pass nor fail, so leaving them mixed in with
the unit tests trains the reader to scroll past skips in a directory where a
skip should mean something is wrong.

Move them to xCAT-test/integration, ship that directory alongside unit in
both the rpm and the deb, and drive it from a new xcattest testcase that
proves the installed copy on an MN. The case is deliberately not labelled
ci_test: the pull request workflow has no management node and must not pick
it up. check:rc==0 is the right gate for it -- prove exits non-zero on a real
failure, exits 0 when a test legitimately skips on a node without Kea, and
exits 2 if the directory is missing entirely, so a packaging regression still
fails the case.

Add a README.md to each directory recording which side of the line a new test
belongs on and how each suite is run.

xCAT-test/unit is now 44 files and 802 assertions with no skips at all; the
assertion count is unchanged, confirming the three moved files were
contributing nothing but skips.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-07-23 11:06:10 -03:00

253 lines
9.3 KiB
Perl

use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/../../perl-xCAT";
use File::Temp qw/tempfile/;
use JSON ();
use Test::More;
use xCAT::DHCP::Backend::Kea;
my $kea_dhcp4 = command_path('kea-dhcp4');
plan skip_all => 'kea-dhcp4 is not installed' unless $kea_dhcp4;
my $validation_dir = validation_temp_dir($kea_dhcp4);
plan skip_all => 'kea-dhcp4 cannot read temporary config files; run as root to validate from /etc/kea'
unless defined $validation_dir;
my $backend = xCAT::DHCP::Backend::Kea->new();
my $json = $backend->render_dhcp4_config(
{
interfaces => ['*'],
'option-def' => [
{ name => 'conf-file', code => 209, type => 'string', space => 'dhcp4' },
{ name => 'iscsi-initiator-iqn', code => 203, type => 'string', space => 'dhcp4' },
{ name => 'cumulus-provision-url', code => 239, type => 'string', space => 'dhcp4' },
],
'client-classes' => [
{
name => 'xcat-xnba-node01-525400123456-bios',
test => "(option[77].exists and (option[77].text == 'xNBA' or option[77].hex == 0x784e4241 or substring(option[77].hex,1,4) == 'xNBA')) and option[93].hex == 0x0000 and pkt4.mac == 0x525400123456",
'boot-file-name' => 'http://192.168.122.1:80/tftpboot/xcat/xnba/nodes/node01',
},
{
name => 'xcat-opal-v3-192.168.122.0-24',
test => 'option[93].hex == 0x000e',
additional_only => JSON::true,
'option-data' => [
{ name => 'conf-file', data => 'http://192.168.122.1:80/tftpboot/pxelinux.cfg/p/192.168.122.0_24' },
],
},
{
name => 'xcat-uefi-x64',
test => "(option[93].hex == 0x0007 or option[93].hex == 0x0009 or option[93].hex == 0x0010) and not ((option[77].exists and (option[77].text == 'xNBA' or option[77].hex == 0x784e4241 or substring(option[77].hex,1,4) == 'xNBA')))",
'boot-file-name' => 'xcat/xnba.efi',
},
],
'dhcp-ddns' => {
'enable-updates' => JSON::true,
'server-ip' => '127.0.0.1',
'server-port' => 53001,
'ncr-protocol' => 'UDP',
'ncr-format' => 'JSON',
},
'ddns-send-updates' => JSON::true,
'ddns-override-no-update' => JSON::true,
'ddns-override-client-update' => JSON::true,
'ddns-qualifying-suffix' => 'cluster.test.',
'ddns-update-on-renew' => JSON::true,
subnets => [
{
id => 1,
subnet => '192.168.122.0/24',
dynamicrange => '192.168.122.100-192.168.122.120',
next_server => '192.168.122.1',
additional_client_classes => ['xcat-opal-v3-192.168.122.0-24'],
option_data => [
{ name => 'routers', data => '192.168.122.1' },
{ name => 'domain-name', data => 'cluster.test' },
{ name => 'domain-name-servers', data => '192.168.122.1' },
{ name => 'cumulus-provision-url', data => 'http://192.168.122.1:80/install/postscripts/cumulusztp' },
],
reservations => [
{
'hw-address' => '52:54:00:12:34:56',
'ip-address' => '192.168.122.50',
hostname => 'node01',
'next-server' => '192.168.122.1',
'boot-file-name' => 'pxelinux.0',
'option-data' => [ { name => 'host-name', data => 'node01' } ],
},
],
},
{
id => 2,
subnet => '192.168.123.0/24',
pools => [],
reservations => [
{
'hw-address' => '52:54:00:65:43:21',
'ip-address' => '192.168.123.50',
hostname => 'node02',
},
],
},
],
}
);
my $path = write_validation_file( $json, 'xcat-test-kea-dhcp4' );
my $result = $backend->validate_dhcp4_config($path);
ok( !$result->{error}, 'generated Kea DHCPv4 config validates with kea-dhcp4 -t' )
or diag $result->{error};
unlink $path;
SKIP: {
skip 'kea-dhcp6 is not installed', 1 unless command_path('kea-dhcp6');
my $dhcp6_json = $backend->render_dhcp6_config(
{
interfaces => ['*'],
'dhcp-ddns' => {
'enable-updates' => JSON::true,
'server-ip' => '127.0.0.1',
'server-port' => 53001,
'ncr-protocol' => 'UDP',
'ncr-format' => 'JSON',
},
'ddns-send-updates' => JSON::true,
'ddns-override-no-update' => JSON::true,
'ddns-override-client-update' => JSON::true,
'ddns-qualifying-suffix' => 'cluster.test.',
'ddns-update-on-renew' => JSON::true,
subnets => [
{
id => 6,
subnet => '2001:db8:1::/64',
dynamicrange => '2001:db8:1::100/120',
option_data => [
{ name => 'dns-servers', data => '2001:db8:1::1' },
{ name => 'domain-search', data => 'cluster.test' },
],
reservations => [
{
duid => '00:04:52:54:00:12:34:56',
'ip-addresses' => ['2001:db8:1::50'],
hostname => 'nodev6',
},
],
},
],
}
);
my $dhcp6_path = write_validation_file( $dhcp6_json, 'xcat-test-kea-dhcp6' );
my $dhcp6_result = $backend->validate_dhcp6_config($dhcp6_path);
ok( !$dhcp6_result->{error}, 'generated Kea DHCPv6 config validates with kea-dhcp6 -t' )
or diag $dhcp6_result->{error};
unlink $dhcp6_path;
}
SKIP: {
skip 'kea-dhcp-ddns is not installed', 1 unless command_path('kea-dhcp-ddns');
my $ddns_json = $backend->render_ddns_config(
{
'tsig-keys' => [
{ name => 'xcat_key', algorithm => 'HMAC-SHA256', secret => 'YWJjMTIz' },
],
forward_domains => [
{
name => 'cluster.test.',
'key-name' => 'xcat_key',
'dns-servers' => [ { 'ip-address' => '127.0.0.1', port => 53 } ],
},
],
reverse_domains => [
{
name => '122.168.192.in-addr.arpa.',
'key-name' => 'xcat_key',
'dns-servers' => [ { 'ip-address' => '127.0.0.1', port => 53 } ],
},
],
}
);
my $ddns_path = write_validation_file( $ddns_json, 'xcat-test-kea-ddns' );
my $ddns_result = $backend->validate_ddns_config($ddns_path);
ok( !$ddns_result->{error}, 'generated Kea DHCP-DDNS config validates with kea-dhcp-ddns -t' )
or diag $ddns_result->{error};
unlink $ddns_path;
}
SKIP: {
skip 'kea-ctrl-agent is not installed', 1 unless command_path('kea-ctrl-agent');
my $ctrl_agent_json = $backend->render_ctrl_agent_config(
{
dhcp6 => 1,
ddns => 1,
}
);
my $ctrl_path = write_validation_file( $ctrl_agent_json, 'xcat-test-kea-ctrl-agent' );
my $ctrl_result = $backend->validate_ctrl_agent_config($ctrl_path);
ok( !$ctrl_result->{error}, 'generated Kea Control Agent config validates with kea-ctrl-agent -t' )
or diag $ctrl_result->{error};
unlink $ctrl_path;
}
done_testing();
sub command_path {
my ($command) = @_;
foreach my $dir ( split /:/, $ENV{PATH} || '' ) {
next unless $dir;
return "$dir/$command" if -x "$dir/$command";
}
foreach my $path ( "/usr/sbin/$command", "/usr/bin/$command", "/sbin/$command", "/bin/$command" ) {
return $path if -x $path;
}
return;
}
sub validation_temp_dir {
my ($kea_dhcp4) = @_;
return '/etc/kea' if -d '/etc/kea' && -w '/etc/kea';
my ( $fh, $path ) = tempfile();
print $fh '{"Dhcp4":{"interfaces-config":{"interfaces":[]},"lease-database":{"type":"memfile","name":"/tmp/xcat-test-kea-leases4.csv"},"valid-lifetime":600,"subnet4":[]}}';
close($fh);
chmod 0644, $path or die "Unable to set $path permissions: $!";
my $command = shell_quote($kea_dhcp4) . ' -t ' . shell_quote($path) . ' 2>&1';
my $output = `$command`;
unlink $path;
if ( $output =~ /Unable to open file/ ) {
return;
}
return '';
}
sub write_validation_file {
my ( $content, $template ) = @_;
my %opts = ( TEMPLATE => "$template-XXXXXX", UNLINK => 0 );
$opts{DIR} = $validation_dir if defined $validation_dir;
my ( $fh, $path ) = tempfile(%opts);
print $fh $content;
close($fh);
chmod 0644, $path or die "Unable to set $path permissions: $!";
return $path;
}
sub shell_quote {
my ($value) = @_;
$value =~ s/'/'\\''/g;
return "'$value'";
}