mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-09 14:36:43 +00:00
557 lines
22 KiB
Perl
557 lines
22 KiB
Perl
#!/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 remove_tree);
|
|
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 export_manifest {
|
|
my ($architecture) = @_;
|
|
return "format=xcat-genesis\n"
|
|
. "version=1\n"
|
|
. "architecture=$architecture\n";
|
|
}
|
|
|
|
sub prepare_export {
|
|
my ($directory, $kernel, $initramfs, $architecture) = @_;
|
|
$architecture //= 'x86_64';
|
|
make_path($directory);
|
|
write_file("$directory/kernel", $kernel);
|
|
write_file("$directory/initramfs.cpio.gz", $initramfs);
|
|
my $manifest = export_manifest($architecture);
|
|
write_file("$directory/xcat-genesis.manifest", $manifest);
|
|
write_file(
|
|
"$directory/SHA256SUMS",
|
|
sha256_hex($initramfs) . " initramfs.cpio.gz\n"
|
|
. sha256_hex($kernel) . " kernel\n"
|
|
. sha256_hex($manifest) . " xcat-genesis.manifest\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');
|
|
make_path("$tftpdir/xcat");
|
|
write_file("$tftpdir/xcat/genesis.fs.x86_64.lzma", 'old initramfs');
|
|
|
|
ok(
|
|
xCAT_plugin::mknb::_prebuilt_genesis_requested($export),
|
|
'an export manifest 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');
|
|
ok(!-e "$tftpdir/xcat/genesis.fs.x86_64.lzma",
|
|
'installing an export removes the obsolete legacy initramfs');
|
|
is(
|
|
read_file("$tftpdir/xcat/genesis.exact-arch.x86_64"),
|
|
export_manifest('x86_64'),
|
|
'the canonical architecture marker is published with the image',
|
|
);
|
|
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("$tftpdir/xcat/genesis.kernel.ppc64le", 'stale kernel');
|
|
write_file("$tftpdir/xcat/genesis.fs.ppc64le.gz", 'stale initramfs');
|
|
write_file("$tftpdir/xcat/genesis.fs.ppc64le.lzma", 'stale legacy initramfs');
|
|
write_file("$tftpdir/xcat/genesis.exact-arch.ppc64le", export_manifest('ppc64le'));
|
|
write_file("$tftpdir/xcat/genesis.kernel.ppc64", 'legacy kernel');
|
|
my ($removed, $remove_error) =
|
|
xCAT_plugin::mknb::_remove_openembedded_genesis($tftpdir, 'ppc64le');
|
|
is($remove_error, undef, 'OpenEmbedded boot artifacts can be retired cleanly');
|
|
is($removed, 4, 'all exact-architecture boot artifacts are retired');
|
|
ok(!-e "$tftpdir/xcat/genesis.kernel.ppc64le",
|
|
'the exact OpenEmbedded kernel is removed');
|
|
ok(!-e "$tftpdir/xcat/genesis.fs.ppc64le.gz"
|
|
&& !-e "$tftpdir/xcat/genesis.fs.ppc64le.lzma",
|
|
'the exact OpenEmbedded initramfs files are removed');
|
|
ok(!-e "$tftpdir/xcat/genesis.exact-arch.ppc64le",
|
|
'the canonical architecture marker is removed');
|
|
ok(-f "$tftpdir/xcat/genesis.kernel.ppc64",
|
|
'retiring ppc64le does not remove the legacy ppc64 fallback');
|
|
|
|
for my $artifact (qw(
|
|
genesis.kernel.s390x
|
|
genesis.fs.s390x.gz
|
|
genesis.fs.s390x.lzma
|
|
genesis.exact-arch.s390x
|
|
)) {
|
|
write_file("$tftpdir/xcat/$artifact", 'stale artifact');
|
|
}
|
|
make_path("$tftpdir/pxelinux.cfg/s390x");
|
|
write_file(
|
|
"$tftpdir/pxelinux.cfg/s390x/192.0.2.0_24",
|
|
"# pxelinux.cfg xCAT Genesis s390x\nstale config\n",
|
|
);
|
|
write_file("$tftpdir/pxelinux.cfg/s390x/default", "admin fallback\n");
|
|
($removed, $remove_error) =
|
|
xCAT_plugin::mknb::_remove_openembedded_genesis($tftpdir, 's390x');
|
|
is($remove_error, undef, 's390x boot artifacts can be retired cleanly');
|
|
is($removed, 5, 's390x image and generated discovery configurations are retired');
|
|
ok(!-e "$tftpdir/pxelinux.cfg/s390x/192.0.2.0_24",
|
|
'retiring s390x removes the generated discovery configuration');
|
|
is(read_file("$tftpdir/pxelinux.cfg/s390x/default"), "admin fallback\n",
|
|
'retiring s390x preserves administrator-owned configurations');
|
|
|
|
my $special_tftpdir = "$tmpdir/tftp root {s390x}";
|
|
make_path("$special_tftpdir/xcat", "$special_tftpdir/pxelinux.cfg/s390x");
|
|
for my $artifact (qw(genesis.kernel.s390x genesis.fs.s390x.gz genesis.exact-arch.s390x)) {
|
|
write_file("$special_tftpdir/xcat/$artifact", "artifact\n");
|
|
}
|
|
write_file(
|
|
"$special_tftpdir/pxelinux.cfg/s390x/192.0.2.0_24",
|
|
"# pxelinux.cfg xCAT Genesis s390x\nconfiguration\n",
|
|
);
|
|
($removed, $remove_error) =
|
|
xCAT_plugin::mknb::_remove_openembedded_genesis($special_tftpdir, 's390x');
|
|
is($remove_error, undef, 's390x cleanup accepts a TFTP path with shell metacharacters');
|
|
is($removed, 4, 's390x cleanup removes every generated artifact from that path');
|
|
ok(!-e "$special_tftpdir/pxelinux.cfg/s390x/192.0.2.0_24",
|
|
's390x cleanup does not expand the TFTP path as a glob');
|
|
|
|
my $failed_kernel = "$tftpdir/xcat/genesis.kernel.aarch64";
|
|
make_path($failed_kernel);
|
|
for my $artifact (qw(
|
|
genesis.fs.aarch64.gz
|
|
genesis.fs.aarch64.lzma
|
|
genesis.exact-arch.aarch64
|
|
)) {
|
|
write_file("$tftpdir/xcat/$artifact", 'stale artifact');
|
|
}
|
|
($removed, $remove_error) =
|
|
xCAT_plugin::mknb::_remove_openembedded_genesis($tftpdir, 'aarch64');
|
|
is($removed, 3, 'artifact cleanup continues after an unlink failure');
|
|
like(
|
|
$remove_error,
|
|
qr/Unable to remove Genesis artifact: \Q$failed_kernel\E/,
|
|
'artifact cleanup reports the failed path',
|
|
);
|
|
ok(-d $failed_kernel, 'the failed artifact remains in place');
|
|
ok(
|
|
!-e "$tftpdir/xcat/genesis.fs.aarch64.gz"
|
|
&& !-e "$tftpdir/xcat/genesis.fs.aarch64.lzma"
|
|
&& !-e "$tftpdir/xcat/genesis.exact-arch.aarch64",
|
|
'artifact cleanup removes every remaining path',
|
|
);
|
|
|
|
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 $unmarked_export = "$tmpdir/unmarked";
|
|
prepare_export($unmarked_export, 'kernel', 'initramfs');
|
|
unlink("$unmarked_export/xcat-genesis.manifest");
|
|
ok(
|
|
!xCAT_plugin::mknb::_prebuilt_genesis_requested($unmarked_export),
|
|
'boot artifacts without an export manifest do not select the prebuilt path',
|
|
);
|
|
(undef, $install_error) = xCAT_plugin::mknb::_install_prebuilt_genesis(
|
|
$unmarked_export, $tftpdir, 'x86_64'
|
|
);
|
|
like($install_error, qr/Missing Genesis export manifest/, 'the installer requires the export manifest');
|
|
|
|
my $partial_export = "$tmpdir/partial";
|
|
make_path($partial_export);
|
|
write_file("$partial_export/initramfs.cpio.gz", 'partial initramfs');
|
|
write_file(
|
|
"$partial_export/xcat-genesis.manifest",
|
|
export_manifest('x86_64'),
|
|
);
|
|
ok(
|
|
!xCAT_plugin::mknb::_prebuilt_genesis_requested($partial_export),
|
|
'a partial export does not satisfy the prebuilt layout',
|
|
);
|
|
ok(
|
|
xCAT_plugin::mknb::_genesis_export_manifest_present($partial_export),
|
|
'a partial export still declares the new format',
|
|
);
|
|
(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_manifest_checksum = "$tmpdir/missing-manifest-checksum";
|
|
prepare_export($missing_manifest_checksum, 'kernel', 'initramfs');
|
|
write_file(
|
|
"$missing_manifest_checksum/SHA256SUMS",
|
|
sha256_hex('kernel') . " kernel\n"
|
|
. sha256_hex('initramfs') . " initramfs.cpio.gz\n",
|
|
);
|
|
(undef, $install_error) = xCAT_plugin::mknb::_install_prebuilt_genesis(
|
|
$missing_manifest_checksum, $tftpdir, 'x86_64'
|
|
);
|
|
like($install_error, qr/Missing Genesis checksum entry: xcat-genesis\.manifest/, 'the export manifest needs a checksum');
|
|
|
|
my $bad_manifest_checksum = "$tmpdir/bad-manifest-checksum";
|
|
prepare_export($bad_manifest_checksum, 'kernel', 'initramfs');
|
|
write_file(
|
|
"$bad_manifest_checksum/xcat-genesis.manifest",
|
|
"architecture=x86_64\nversion=1\nformat=xcat-genesis\n",
|
|
);
|
|
(undef, $install_error) = xCAT_plugin::mknb::_install_prebuilt_genesis(
|
|
$bad_manifest_checksum, $tftpdir, 'x86_64'
|
|
);
|
|
like($install_error, qr/Genesis checksum mismatch: .*xcat-genesis\.manifest/, 'the export manifest checksum is verified');
|
|
|
|
my @invalid_manifests = (
|
|
[ malformed => "not a manifest\n", qr/Invalid Genesis export manifest entry/ ],
|
|
[ unknown => export_manifest('x86_64') . "label=test\n", qr/Unknown Genesis export manifest entry: label/ ],
|
|
[ duplicate => export_manifest('x86_64') . "version=1\n", qr/Duplicate Genesis export manifest entry: version/ ],
|
|
[ missing => "format=xcat-genesis\nversion=1\n", qr/Missing Genesis export manifest entry: architecture/ ],
|
|
[ version => "format=xcat-genesis\nversion=2\narchitecture=x86_64\n", qr/Unsupported Genesis export version: 2/ ],
|
|
[ architecture => export_manifest('ppc64le'), qr/Unsupported Genesis export architecture: ppc64le/ ],
|
|
);
|
|
foreach my $case (@invalid_manifests) {
|
|
my ($name, $content, $error_pattern) = @{$case};
|
|
my $invalid_export = "$tmpdir/manifest-$name";
|
|
prepare_export($invalid_export, 'kernel', 'initramfs');
|
|
write_file("$invalid_export/xcat-genesis.manifest", $content);
|
|
(undef, $install_error) = xCAT_plugin::mknb::_install_prebuilt_genesis(
|
|
$invalid_export, $tftpdir, 'x86_64'
|
|
);
|
|
like($install_error, $error_pattern, "$name export manifests are rejected");
|
|
}
|
|
|
|
my $symlink_manifest = "$tmpdir/symlink-manifest";
|
|
prepare_export($symlink_manifest, 'kernel', 'initramfs');
|
|
unlink("$symlink_manifest/xcat-genesis.manifest");
|
|
symlink("$symlink_manifest/kernel", "$symlink_manifest/xcat-genesis.manifest")
|
|
or die "Unable to create manifest symlink: $!";
|
|
ok(
|
|
xCAT_plugin::mknb::_prebuilt_genesis_requested($symlink_manifest),
|
|
'a manifest symlink still selects the prebuilt path',
|
|
);
|
|
(undef, $install_error) = xCAT_plugin::mknb::_install_prebuilt_genesis(
|
|
$symlink_manifest, $tftpdir, 'x86_64'
|
|
);
|
|
like($install_error, qr/Missing Genesis export manifest/, 'export manifest symlinks fail closed');
|
|
|
|
my $missing_entry = "$tmpdir/missing-entry";
|
|
prepare_export($missing_entry, 'kernel', 'initramfs');
|
|
write_file(
|
|
"$missing_entry/SHA256SUMS",
|
|
sha256_hex('kernel') . " kernel\n"
|
|
. sha256_hex(export_manifest('x86_64'))
|
|
. " xcat-genesis.manifest\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', 'ppc64');
|
|
$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',
|
|
);
|
|
|
|
unlink("$process_export/SHA256SUMS");
|
|
@responses = ();
|
|
xCAT_plugin::mknb::process_request(
|
|
{ arg => ['ppc64'] },
|
|
sub { push(@responses, @_); },
|
|
);
|
|
ok(
|
|
grep(
|
|
{ ref($_) eq 'HASH' && $_->{error}
|
|
&& $_->{error}->[0] =~ /Incomplete Genesis export/ }
|
|
@responses
|
|
),
|
|
'mknb rejects an incomplete marked export',
|
|
);
|
|
is(
|
|
read_file($process_kernel),
|
|
'process kernel',
|
|
'an incomplete marked export keeps the published kernel',
|
|
);
|
|
is(
|
|
read_file($process_initramfs),
|
|
'process initramfs',
|
|
'an incomplete marked export keeps the published initramfs',
|
|
);
|
|
|
|
$::XCATROOT = "$tmpdir/openembedded-xcatroot";
|
|
my $openembedded_process_export =
|
|
"$::XCATROOT/share/xcat/netboot/genesis-openembedded/ppc64le";
|
|
my $legacy_process_export =
|
|
"$::XCATROOT/share/xcat/netboot/genesis/ppc64";
|
|
prepare_export(
|
|
$openembedded_process_export,
|
|
'openembedded ppc64le kernel',
|
|
'openembedded ppc64le initramfs',
|
|
'ppc64le',
|
|
);
|
|
prepare_export(
|
|
$legacy_process_export,
|
|
'legacy ppc64 kernel',
|
|
'legacy ppc64 initramfs',
|
|
'ppc64',
|
|
);
|
|
$xCAT::TableUtils::tftpdir = "$tmpdir/openembedded-tftpboot";
|
|
@responses = ();
|
|
xCAT_plugin::mknb::process_request(
|
|
{ arg => ['ppc64le'] },
|
|
sub { push(@responses, @_); },
|
|
);
|
|
ok(
|
|
!grep({ ref($_) eq 'HASH' && $_->{error} } @responses),
|
|
'mknb installs an exact ppc64le OpenEmbedded export',
|
|
);
|
|
my ($openembedded_kernel, $openembedded_initramfs) =
|
|
published_files($xCAT::TableUtils::tftpdir, 'ppc64le');
|
|
is(read_file($openembedded_kernel), 'openembedded ppc64le kernel',
|
|
'mknb prefers the OpenEmbedded kernel when legacy Genesis is also installed');
|
|
is(read_file($openembedded_initramfs), 'openembedded ppc64le initramfs',
|
|
'mknb prefers the OpenEmbedded initramfs when legacy Genesis is also installed');
|
|
my $ppc64le_config = read_file(
|
|
"$xCAT::TableUtils::tftpdir/pxelinux.cfg/p/192.0.2.0_24"
|
|
);
|
|
like($ppc64le_config, qr/genesis\.kernel\.ppc64le/,
|
|
'POWER boot configuration keeps the exact ppc64le artifact name');
|
|
like($ppc64le_config, qr/genesis\.fs\.ppc64le\.gz/,
|
|
'POWER boot configuration uses the exact ppc64le initramfs name');
|
|
|
|
remove_tree($openembedded_process_export);
|
|
write_file(
|
|
"$xCAT::TableUtils::tftpdir/xcat/genesis.kernel.ppc64",
|
|
'canonical big-endian ppc64 kernel',
|
|
);
|
|
write_file(
|
|
"$xCAT::TableUtils::tftpdir/xcat/genesis.exact-arch.ppc64",
|
|
export_manifest('ppc64'),
|
|
);
|
|
@responses = ();
|
|
xCAT_plugin::mknb::process_request(
|
|
{ arg => ['ppc64le'] },
|
|
sub { push(@responses, @_); },
|
|
);
|
|
ok(
|
|
grep(
|
|
{ ref($_) eq 'HASH' && $_->{error}
|
|
&& $_->{error} =~ /canonical ppc64 image/ }
|
|
@responses
|
|
),
|
|
'the legacy ppc64le fallback cannot replace a canonical ppc64 image',
|
|
);
|
|
is(
|
|
read_file("$xCAT::TableUtils::tftpdir/xcat/genesis.kernel.ppc64"),
|
|
'canonical big-endian ppc64 kernel',
|
|
'a refused ppc64le fallback leaves the canonical ppc64 kernel intact',
|
|
);
|
|
|
|
my $selection_root = "$tmpdir/selection-root";
|
|
my $legacy_x86 = "$selection_root/share/xcat/netboot/genesis/x86_64";
|
|
my $openembedded_x86 =
|
|
"$selection_root/share/xcat/netboot/genesis-openembedded/x86_64";
|
|
make_path("$legacy_x86/fs", $openembedded_x86);
|
|
|
|
my ($selected_dir, $selected_arch, $selected_type) =
|
|
xCAT_plugin::mknb::_select_genesis_source($selection_root, 'x86_64');
|
|
is($selected_dir, $openembedded_x86,
|
|
'an installed OpenEmbedded export takes precedence over legacy Genesis');
|
|
is($selected_arch, 'x86_64', 'the OpenEmbedded x86_64 name is unchanged');
|
|
is($selected_type, 'openembedded', 'the selected source is identified');
|
|
|
|
remove_tree($openembedded_x86);
|
|
($selected_dir, $selected_arch, $selected_type) =
|
|
xCAT_plugin::mknb::_select_genesis_source($selection_root, 'x86_64');
|
|
is($selected_dir, $legacy_x86, 'legacy Genesis remains the fallback');
|
|
is($selected_arch, 'x86_64', 'the legacy x86_64 name is unchanged');
|
|
is($selected_type, 'legacy', 'the fallback source is identified');
|
|
|
|
my $linked_legacy = "$tmpdir/linked-legacy-x86_64";
|
|
make_path("$linked_legacy/fs");
|
|
remove_tree($legacy_x86);
|
|
symlink($linked_legacy, $legacy_x86)
|
|
or die "Unable to create legacy Genesis directory symlink: $!";
|
|
($selected_dir, $selected_arch, $selected_type) =
|
|
xCAT_plugin::mknb::_select_genesis_source($selection_root, 'x86_64');
|
|
is($selected_dir, $legacy_x86, 'legacy Genesis directory symlinks remain usable');
|
|
is($selected_type, 'legacy', 'a linked legacy source keeps its source type');
|
|
|
|
my $openembedded_ppc64le =
|
|
"$selection_root/share/xcat/netboot/genesis-openembedded/ppc64le";
|
|
my $legacy_ppc64 = "$selection_root/share/xcat/netboot/genesis/ppc64";
|
|
make_path($openembedded_ppc64le, "$legacy_ppc64/fs");
|
|
($selected_dir, $selected_arch, $selected_type) =
|
|
xCAT_plugin::mknb::_select_genesis_source($selection_root, 'ppc64le');
|
|
is($selected_dir, $openembedded_ppc64le,
|
|
'ppc64le selects its exact OpenEmbedded export');
|
|
is($selected_arch, 'ppc64le', 'ppc64le is not rewritten to ppc64');
|
|
is($selected_type, 'openembedded', 'ppc64le uses the OpenEmbedded source');
|
|
|
|
($selected_dir, $selected_arch, $selected_type) =
|
|
xCAT_plugin::mknb::_select_genesis_source($selection_root, 'ppc64el');
|
|
is($selected_dir, $openembedded_ppc64le,
|
|
'the Debian spelling resolves to the canonical ppc64le export');
|
|
is($selected_arch, 'ppc64le', 'the canonical architecture name is returned');
|
|
|
|
remove_tree($openembedded_ppc64le);
|
|
($selected_dir, $selected_arch, $selected_type) =
|
|
xCAT_plugin::mknb::_select_genesis_source($selection_root, 'ppc64le');
|
|
is($selected_dir, $legacy_ppc64,
|
|
'ppc64le falls back to the old combined POWER image when needed');
|
|
is($selected_arch, 'ppc64', 'only the legacy fallback uses the old ppc64 name');
|
|
is($selected_type, 'legacy', 'the POWER fallback is identified as legacy');
|
|
|
|
my $unsafe = xCAT_plugin::mknb::_select_genesis_source(
|
|
$selection_root, '../../outside'
|
|
);
|
|
is($unsafe, undef, 'unsupported architecture names cannot escape the image root');
|
|
|
|
done_testing();
|