2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-08-28 17:46:40 +00:00

test(mknb): cover exported Genesis images

This commit is contained in:
Vinícius Ferrão
2026-08-10 20:37:53 -03:00
parent 26b4aec340
commit 57360b89ff
+221
View File
@@ -0,0 +1,221 @@
#!/usr/bin/env perl
use strict;
use warnings;
## no critic (Modules::RequireFilenameMatchesPackage, TestingAndDebugging::ProhibitNoStrict, TestingAndDebugging::ProhibitNoWarnings)
use Digest::SHA qw(sha256_hex);
use File::Path qw(make_path);
use File::Temp qw(tempdir);
use FindBin;
use Test::More;
BEGIN {
package xCAT::Utils;
sub genpassword { return 'test-token'; }
$INC{'xCAT/Utils.pm'} = __FILE__;
package xCAT::TableUtils;
our ($tftpdir, $site_master);
sub getTftpDir { return $tftpdir; }
sub get_site_attribute {
my $attribute = $_[-1];
return ($site_master) if $attribute eq 'master' && defined($site_master);
return;
}
$INC{'xCAT/TableUtils.pm'} = __FILE__;
package xCAT::NetworkUtils;
our ($normnet_addresses, $hexnet_addresses, @master_addresses);
sub my_nets { return $normnet_addresses; }
sub my_hexnets { return $hexnet_addresses; }
sub getipaddr { return @master_addresses; }
$INC{'xCAT/NetworkUtils.pm'} = __FILE__;
package xCAT::NodeRange;
sub import {
my $caller = caller;
no strict 'refs';
*{"${caller}::noderange"} = sub { return; };
}
$INC{'xCAT/NodeRange.pm'} = __FILE__;
}
my $source_mknb_plugin =
"$FindBin::Bin/../../xCAT-server/lib/xcat/plugins/mknb.pm";
if (-f $source_mknb_plugin) {
require $source_mknb_plugin;
} else {
require xCAT_plugin::mknb;
}
sub write_file {
my ($filename, $content) = @_;
open(my $fh, '>:raw', $filename) or die "Unable to write $filename: $!";
print {$fh} $content;
close($fh) or die "Unable to close $filename: $!";
}
sub read_file {
my ($filename) = @_;
open(my $fh, '<:raw', $filename) or die "Unable to read $filename: $!";
my $content = do { local $/; <$fh> };
close($fh);
return $content;
}
sub prepare_export {
my ($directory, $kernel, $initramfs) = @_;
make_path($directory);
write_file("$directory/kernel", $kernel);
write_file("$directory/initramfs.cpio.gz", $initramfs);
write_file(
"$directory/SHA256SUMS",
sha256_hex($initramfs) . " initramfs.cpio.gz\n"
. sha256_hex($kernel) . " kernel\n",
);
}
sub published_files {
my ($tftpdir, $arch) = @_;
return (
"$tftpdir/xcat/genesis.kernel.$arch",
"$tftpdir/xcat/genesis.fs.$arch.gz",
);
}
sub temporary_files {
my ($directory) = @_;
opendir(my $dir_fh, $directory) or return;
my @files = grep { /\.test-token\.(?:new|old)$/ } readdir($dir_fh);
closedir($dir_fh);
return @files;
}
my $tmpdir = tempdir(CLEANUP => 1);
my $export = "$tmpdir/export";
my $tftpdir = "$tmpdir/tftpboot";
prepare_export($export, 'new kernel', 'new initramfs');
ok(
xCAT_plugin::mknb::_prebuilt_genesis_requested($export),
'an exported initramfs selects the prebuilt path',
);
my ($installed_initrd, $install_error) =
xCAT_plugin::mknb::_install_prebuilt_genesis($export, $tftpdir, 'x86_64');
is($install_error, undef, 'a valid export installs without an error');
is(
$installed_initrd,
"$tftpdir/xcat/genesis.fs.x86_64.gz",
'the installer returns the published initramfs path',
);
my ($published_kernel, $published_initramfs) =
published_files($tftpdir, 'x86_64');
is(read_file($published_kernel), 'new kernel', 'the kernel is published');
is(read_file($published_initramfs), 'new initramfs', 'the initramfs is published');
is(sprintf('%04o', (stat($published_kernel))[2] & oct('7777')), '0644', 'the kernel is readable by TFTP');
is(sprintf('%04o', (stat($published_initramfs))[2] & oct('7777')), '0644', 'the initramfs is readable by TFTP');
is_deeply([temporary_files("$tftpdir/xcat")], [], 'staging files are removed');
write_file($published_kernel, 'current kernel');
write_file($published_initramfs, 'current initramfs');
write_file("$export/kernel", 'corrupt kernel');
($installed_initrd, $install_error) =
xCAT_plugin::mknb::_install_prebuilt_genesis($export, $tftpdir, 'x86_64');
like($install_error, qr/Genesis checksum mismatch/, 'a checksum mismatch is rejected');
is(read_file($published_kernel), 'current kernel', 'a bad export keeps the current kernel');
is(read_file($published_initramfs), 'current initramfs', 'a bad export keeps the current initramfs');
is_deeply([temporary_files("$tftpdir/xcat")], [], 'a failed install removes staging files');
my $partial_export = "$tmpdir/partial";
make_path($partial_export);
write_file("$partial_export/initramfs.cpio.gz", 'partial initramfs');
ok(
xCAT_plugin::mknb::_prebuilt_genesis_requested($partial_export),
'a partial export still selects the prebuilt path',
);
(undef, $install_error) = xCAT_plugin::mknb::_install_prebuilt_genesis(
$partial_export, $tftpdir, 'x86_64'
);
like($install_error, qr/Missing Genesis checksum file/, 'a partial export fails closed');
my $missing_entry = "$tmpdir/missing-entry";
prepare_export($missing_entry, 'kernel', 'initramfs');
write_file(
"$missing_entry/SHA256SUMS",
sha256_hex('kernel') . " kernel\n",
);
(undef, $install_error) = xCAT_plugin::mknb::_install_prebuilt_genesis(
$missing_entry, $tftpdir, 'x86_64'
);
like($install_error, qr/Missing Genesis checksum entry: initramfs\.cpio\.gz/, 'each published file needs a checksum');
my $duplicate_entry = "$tmpdir/duplicate-entry";
prepare_export($duplicate_entry, 'kernel', 'initramfs');
write_file(
"$duplicate_entry/SHA256SUMS",
sha256_hex('kernel') . " kernel\n"
. sha256_hex('kernel') . " kernel\n",
);
(undef, $install_error) = xCAT_plugin::mknb::_install_prebuilt_genesis(
$duplicate_entry, $tftpdir, 'x86_64'
);
like($install_error, qr/Duplicate Genesis checksum entry: kernel/, 'duplicate checksum entries are rejected');
my $malformed_entry = "$tmpdir/malformed-entry";
prepare_export($malformed_entry, 'kernel', 'initramfs');
write_file("$malformed_entry/SHA256SUMS", "not a checksum\n");
(undef, $install_error) = xCAT_plugin::mknb::_install_prebuilt_genesis(
$malformed_entry, $tftpdir, 'x86_64'
);
like($install_error, qr/Invalid Genesis checksum entry/, 'malformed checksum entries are rejected');
my $symlink_export = "$tmpdir/symlink-export";
prepare_export($symlink_export, 'kernel', 'initramfs');
unlink("$symlink_export/kernel");
symlink("$symlink_export/initramfs.cpio.gz", "$symlink_export/kernel")
or die "Unable to create test symlink: $!";
(undef, $install_error) = xCAT_plugin::mknb::_install_prebuilt_genesis(
$symlink_export, $tftpdir, 'x86_64'
);
like($install_error, qr/Missing Genesis artifact: .*\/kernel/, 'artifact symlinks are rejected');
my $legacy_directory = "$tmpdir/legacy";
make_path("$legacy_directory/fs");
write_file("$legacy_directory/kernel", 'legacy kernel');
ok(
!xCAT_plugin::mknb::_prebuilt_genesis_requested($legacy_directory),
'the legacy fs layout does not select the prebuilt path',
);
$::XCATROOT = "$tmpdir/xcatroot";
my $process_export =
"$::XCATROOT/share/xcat/netboot/genesis/ppc64";
prepare_export($process_export, 'process kernel', 'process initramfs');
$xCAT::TableUtils::tftpdir = "$tmpdir/custom-tftpboot";
$xCAT::NetworkUtils::normnet_addresses = {
'192.0.2.0/24' => ['192.0.2.1'],
};
$xCAT::NetworkUtils::hexnet_addresses = {};
$xCAT::TableUtils::site_master = undef;
@xCAT::NetworkUtils::master_addresses = ();
my @responses;
xCAT_plugin::mknb::process_request(
{ arg => ['ppc64'] },
sub { push(@responses, @_); },
);
ok(
!grep({ ref($_) eq 'HASH' && $_->{error} } @responses),
'mknb accepts the exported layout',
);
my ($process_kernel, $process_initramfs) =
published_files($xCAT::TableUtils::tftpdir, 'ppc64');
is(read_file($process_kernel), 'process kernel', 'mknb publishes the exported kernel');
is(read_file($process_initramfs), 'process initramfs', 'mknb publishes the exported initramfs');
ok(
-f "$xCAT::TableUtils::tftpdir/pxelinux.cfg/p/192.0.2.0_24",
'mknb writes boot configuration after publishing the export',
);
done_testing();