mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-09 05:00:44 +00:00
test(genesis): cover s390x network boot
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../../perl-xCAT";
|
||||
|
||||
use File::Spec;
|
||||
use File::Temp qw(tempdir);
|
||||
use Test::More;
|
||||
use xCAT::DHCP::BootPolicy;
|
||||
|
||||
my ($dhcpd) = grep { -x $_ } qw(/usr/sbin/dhcpd /usr/local/sbin/dhcpd);
|
||||
plan skip_all => 'dhcpd is required for ISC configuration validation' unless $dhcpd;
|
||||
plan skip_all => 'root is required to validate from the ISC configuration directory'
|
||||
unless $> == 0;
|
||||
|
||||
my @config = (
|
||||
"#xCAT generated dhcp configuration\n",
|
||||
"\n",
|
||||
"option conf-file code 209 = text;\n",
|
||||
"option user-class-identifier code 77 = string;\n",
|
||||
"option client-architecture code 93 = unsigned integer 16;\n",
|
||||
"option www-server code 114 = string;\n",
|
||||
"default-lease-time 600;\n",
|
||||
"max-lease-time 600;\n",
|
||||
"subnet 192.0.2.0 netmask 255.255.255.0 {\n",
|
||||
" range 192.0.2.100 192.0.2.110;\n",
|
||||
);
|
||||
|
||||
ok(
|
||||
xCAT::DHCP::BootPolicy->ensure_isc_path_prefix_definition(\@config),
|
||||
'the upgrade path adds option 210 to an existing configuration',
|
||||
);
|
||||
push @config, @{ xCAT::DHCP::BootPolicy->isc_client_architecture_lines(
|
||||
next_server => '192.0.2.1',
|
||||
portsuffix => '',
|
||||
net => '192.0.2.0',
|
||||
prefix => 24,
|
||||
) }, "}\n";
|
||||
|
||||
my $configuration_root = -d '/etc/dhcp' ? '/etc/dhcp' : '/etc';
|
||||
my $directory = tempdir(DIR => $configuration_root, CLEANUP => 1);
|
||||
my $path = File::Spec->catfile($directory, 'dhcpd.conf');
|
||||
open(my $config_file, '>', $path) or die "Cannot create $path: $!";
|
||||
print {$config_file} @config;
|
||||
close($config_file) or die "Cannot close $path: $!";
|
||||
|
||||
my $status = system($dhcpd, '-t', '-cf', $path);
|
||||
is($status, 0, 'ISC accepts the upgraded s390x boot policy');
|
||||
|
||||
done_testing();
|
||||
@@ -24,6 +24,7 @@ my $json = $backend->render_dhcp4_config(
|
||||
interfaces => ['*'],
|
||||
'option-def' => [
|
||||
{ name => 'conf-file', code => 209, type => 'string', space => 'dhcp4' },
|
||||
{ name => 'path-prefix', code => 210, type => 'string', space => 'dhcp4' },
|
||||
{ name => 'iscsi-initiator-iqn', code => 203, type => 'string', space => 'dhcp4' },
|
||||
{ name => 'cumulus-provision-url', code => 239, type => 'string', space => 'dhcp4' },
|
||||
],
|
||||
@@ -41,6 +42,15 @@ my $json = $backend->render_dhcp4_config(
|
||||
{ name => 'conf-file', data => 'http://192.168.122.1:80/tftpboot/pxelinux.cfg/p/192.168.122.0_24' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name => 'xcat-s390x-qemu-192.168.122.0_24',
|
||||
test => 'option[93].hex == 0x001f',
|
||||
additional_only => JSON::true,
|
||||
'option-data' => [
|
||||
{ name => 'conf-file', data => '192.168.122.0_24' },
|
||||
{ name => 'path-prefix', data => 'pxelinux.cfg/s390x/' },
|
||||
],
|
||||
},
|
||||
{
|
||||
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')))",
|
||||
@@ -65,7 +75,10 @@ my $json = $backend->render_dhcp4_config(
|
||||
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'],
|
||||
additional_client_classes => [
|
||||
'xcat-opal-v3-192.168.122.0-24',
|
||||
'xcat-s390x-qemu-192.168.122.0_24',
|
||||
],
|
||||
option_data => [
|
||||
{ name => 'routers', data => '192.168.122.1' },
|
||||
{ name => 'domain-name', data => 'cluster.test' },
|
||||
|
||||
@@ -217,4 +217,63 @@ unlike(
|
||||
'the global class list keeps HTTP boot out: it needs the address of the management node',
|
||||
);
|
||||
|
||||
my $s390x = xCAT::DHCP::BootPolicy->kea_s390x_network_classes(
|
||||
net => '10.0.0.0',
|
||||
prefix => 24,
|
||||
);
|
||||
is_deeply(
|
||||
$s390x,
|
||||
[
|
||||
{
|
||||
name => 'xcat-s390x-qemu-10.0.0.0_24',
|
||||
test => 'option[93].hex == 0x001f',
|
||||
additional_only => 1,
|
||||
'option-data' => [
|
||||
{
|
||||
name => 'conf-file',
|
||||
data => '10.0.0.0_24',
|
||||
'always-send' => 1,
|
||||
},
|
||||
{
|
||||
name => 'path-prefix',
|
||||
data => 'pxelinux.cfg/s390x/',
|
||||
'always-send' => 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
'QEMU s390x stays within its architecture-specific configuration path',
|
||||
);
|
||||
is_deeply(
|
||||
xCAT::DHCP::BootPolicy->kea_s390x_network_classes(prefix => 24),
|
||||
[],
|
||||
's390x classes require a network',
|
||||
);
|
||||
|
||||
my @legacy_isc_config = (
|
||||
"#xCAT generated dhcp configuration\n",
|
||||
"\n",
|
||||
"option conf-file code 209 = text;\n",
|
||||
);
|
||||
ok(
|
||||
xCAT::DHCP::BootPolicy->ensure_isc_path_prefix_definition(
|
||||
\@legacy_isc_config
|
||||
),
|
||||
'an older ISC configuration receives the path-prefix definition',
|
||||
);
|
||||
is(
|
||||
$legacy_isc_config[1],
|
||||
"option path-prefix code 210 = text;\n",
|
||||
'the definition is inserted in the global configuration header',
|
||||
);
|
||||
ok(
|
||||
!xCAT::DHCP::BootPolicy->ensure_isc_path_prefix_definition(
|
||||
\@legacy_isc_config
|
||||
),
|
||||
'an existing path-prefix definition is preserved',
|
||||
);
|
||||
my $definition_count =
|
||||
grep { /^\s*option\s+path-prefix\s+code\s+210\b/ } @legacy_isc_config;
|
||||
is($definition_count, 1, 'repeated updates do not duplicate the definition');
|
||||
|
||||
done_testing();
|
||||
|
||||
@@ -36,6 +36,11 @@ like(
|
||||
qr/option conf-file = "http:\/\/192\.0\.2\.10:8080\/tftpboot\/pxelinux\.cfg\/p\/192\.0\.2\.0_24";/,
|
||||
'the existing OPAL branch keeps its subnet URL',
|
||||
);
|
||||
like(
|
||||
$rendered,
|
||||
qr/client-architecture = 00:1f \{ #QEMU s390x\n\s+option path-prefix = "pxelinux\.cfg\/s390x\/";\n\s+option conf-file = "192\.0\.2\.0_24";/,
|
||||
'QEMU s390x receives its subnet configuration and fallback path',
|
||||
);
|
||||
|
||||
my @riscv_ids = $rendered =~ /client-architecture = (00:1[9a-e])/g;
|
||||
is_deeply(
|
||||
@@ -47,12 +52,14 @@ is_deeply(
|
||||
my $aarch64_pos = index($rendered, 'client-architecture = 00:0b');
|
||||
my $tftp_pos = index($rendered, 'client-architecture = 00:1b');
|
||||
my $http_pos = index($rendered, 'client-architecture = 00:1c');
|
||||
my $s390_qemu_pos = index($rendered, 'client-architecture = 00:1f');
|
||||
my $opal_pos = index($rendered, 'client-architecture = 00:0e');
|
||||
my $fallback_pos = index($rendered, 'substring(filename,0,1) = null');
|
||||
|
||||
cmp_ok($aarch64_pos, '<', $tftp_pos, 'riscv64 follows the aarch64 branch');
|
||||
cmp_ok($tftp_pos, '<', $http_pos, 'the TFTP branch precedes the HTTP branch');
|
||||
cmp_ok($http_pos, '<', $opal_pos, 'the HTTP branch precedes the OPAL branch');
|
||||
cmp_ok($http_pos, '<', $s390_qemu_pos, 's390x follows the RISC-V HTTP branch');
|
||||
cmp_ok($s390_qemu_pos, '<', $opal_pos, 's390x precedes the OPAL branch');
|
||||
cmp_ok($http_pos, '<', $fallback_pos, 'the HTTP branch is reachable before the fallback');
|
||||
like($rendered, qr/filename "\/yaboot";\n\s*\}\n\z/, 'the policy ends with the existing yaboot fallback');
|
||||
|
||||
|
||||
@@ -120,6 +120,38 @@ my %network_entry = (
|
||||
tftpserver => '<xcatmaster>',
|
||||
);
|
||||
|
||||
{
|
||||
no warnings 'redefine';
|
||||
local *xCAT::NetworkUtils::thishostisnot = sub { return 0; };
|
||||
my $nettab = DHCPKeaIntentNetTable->new(\%network_entry);
|
||||
my $subnet = xCAT_plugin::dhcp::kea_subnet4_intent(
|
||||
$nettab, '10.0.0.0', '255.255.255.0', 'eth0', 0, 1, 80
|
||||
);
|
||||
my %classes = map { $_->{name} => $_ } @{ $subnet->{client_classes} };
|
||||
ok($classes{'xcat-s390x-qemu-10.0.0.0_24'}, 'the Kea subnet includes QEMU s390x boot policy');
|
||||
is_deeply(
|
||||
[ grep { /^xcat-s390x-/ } @{ $subnet->{additional_client_classes} } ],
|
||||
['xcat-s390x-qemu-10.0.0.0_24'],
|
||||
'the s390x policy is evaluated only for its subnet',
|
||||
);
|
||||
is_deeply(
|
||||
$classes{'xcat-s390x-qemu-10.0.0.0_24'}{'option-data'},
|
||||
[
|
||||
{
|
||||
name => 'conf-file',
|
||||
data => '10.0.0.0_24',
|
||||
'always-send' => 1,
|
||||
},
|
||||
{
|
||||
name => 'path-prefix',
|
||||
data => 'pxelinux.cfg/s390x/',
|
||||
'always-send' => 1,
|
||||
},
|
||||
],
|
||||
'the rendered subnet keeps s390x fallback lookups in their own path',
|
||||
);
|
||||
}
|
||||
|
||||
my @sysconfig_policy_cases = (
|
||||
[ 'sles10', 0, 'SLES 10' ],
|
||||
[ 'sles11', 1, 'SLES 11' ],
|
||||
|
||||
@@ -14,6 +14,7 @@ my $rpm_weak_dependencies = join(
|
||||
'Recommends: xCAT-genesis-openembedded-x86_64',
|
||||
'Recommends: xCAT-genesis-openembedded-ppc64le',
|
||||
'Recommends: xCAT-genesis-openembedded-riscv64',
|
||||
'Recommends: xCAT-genesis-openembedded-s390x',
|
||||
'%endif',
|
||||
);
|
||||
|
||||
@@ -45,6 +46,11 @@ like(
|
||||
qr/^Recommends:.*\bxcat-genesis-openembedded-riscv64\b/m,
|
||||
'DEB installations recommend the first-class riscv64 image',
|
||||
);
|
||||
like(
|
||||
$deb_control,
|
||||
qr/^Recommends:.*\bxcat-genesis-openembedded-s390x\b/m,
|
||||
'DEB installations recommend the s390x image',
|
||||
);
|
||||
unlike(
|
||||
$deb_control,
|
||||
qr/^Depends:.*\bxcat-genesis-openembedded-/m,
|
||||
@@ -74,6 +80,11 @@ like(
|
||||
qr/^Recommends:.*\bxcat-genesis-openembedded-riscv64\b/m,
|
||||
'DEB service nodes recommend the first-class riscv64 image',
|
||||
);
|
||||
like(
|
||||
$sn_deb_control,
|
||||
qr/^Recommends:.*\bxcat-genesis-openembedded-s390x\b/m,
|
||||
'DEB service nodes recommend the s390x image',
|
||||
);
|
||||
|
||||
my $go_xcat = slurp_repo_file('xCAT-server/share/xcat/tools/go-xcat');
|
||||
unlike(
|
||||
@@ -81,7 +92,7 @@ unlike(
|
||||
qr/GO_XCAT_LIBRARY_ONLY/,
|
||||
'go-xcat cannot be disabled by an inherited test environment variable',
|
||||
);
|
||||
for my $architecture (qw(x86 x86_64 ppc64 ppc64le armv7hf aarch64 riscv64)) {
|
||||
for my $architecture (qw(x86 x86_64 ppc64 ppc64le armv7hf aarch64 riscv64 s390x)) {
|
||||
like(
|
||||
$go_xcat,
|
||||
qr/\bxCAT-genesis-openembedded-\Q$architecture\E\b/,
|
||||
|
||||
@@ -156,6 +156,29 @@ ok(!-e "$tftpdir/xcat/genesis.exact-arch.ppc64le",
|
||||
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 configuration 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 $failed_kernel = "$tftpdir/xcat/genesis.kernel.aarch64";
|
||||
make_path($failed_kernel);
|
||||
for my $artifact (qw(
|
||||
|
||||
@@ -508,4 +508,83 @@ ok(
|
||||
%xCAT::TableUtils::site_extra = ();
|
||||
$xCAT::NetworkUtils::nic_ips = undef;
|
||||
|
||||
make_path("$::XCATROOT/share/xcat/netboot/genesis-openembedded/s390x");
|
||||
use_reporter_address_maps();
|
||||
prepare_tftpdir($tmpdir, 'tftpboot-s390x', 's390x');
|
||||
$responses = run_mknb('s390x');
|
||||
generation_succeeded($responses, 's390x configuration generation succeeds');
|
||||
|
||||
my $s390x_qemu_path =
|
||||
"$xCAT::TableUtils::tftpdir/pxelinux.cfg/s390x/192.168.144.0_20";
|
||||
ok(-f $s390x_qemu_path, 's390x writes a QEMU network IPL configuration');
|
||||
is(
|
||||
read_config($s390x_qemu_path),
|
||||
"# pxelinux.cfg xCAT Genesis s390x\n"
|
||||
. "DEFAULT xCAT\n"
|
||||
. "LABEL xCAT\n"
|
||||
. " KERNEL xcat/genesis.kernel.s390x\n"
|
||||
. " INITRD xcat/genesis.fs.s390x.gz\n"
|
||||
. " APPEND xcatd=192.168.148.10:3001 xcat.bootloader=s390-ccw console=ttysclp0\n",
|
||||
'the QEMU configuration selects Genesis and the SCLP console',
|
||||
);
|
||||
unlike(
|
||||
read_config($s390x_qemu_path),
|
||||
qr/192\.168\.149\.100/,
|
||||
's390x configurations do not use the later floating address',
|
||||
);
|
||||
|
||||
write_text($s390x_qemu_path, "admin network configuration\n");
|
||||
%xCAT::TableUtils::site_extra = ( dhcpinterfaces => 'eth0,eth1:noboot' );
|
||||
$xCAT::NetworkUtils::nic_ips = { eth0 => '10.0.0.1', eth1 => '192.168.148.10' };
|
||||
$responses = run_mknb('s390x');
|
||||
generation_succeeded($responses, 's390x configuration generation accepts a :noboot interface');
|
||||
is(
|
||||
read_config($s390x_qemu_path),
|
||||
"admin network configuration\n",
|
||||
'a :noboot interface preserves an administrator-owned s390x configuration',
|
||||
);
|
||||
%xCAT::TableUtils::site_extra = ();
|
||||
$xCAT::NetworkUtils::nic_ips = undef;
|
||||
$responses = run_mknb('s390x');
|
||||
generation_succeeded($responses, 's390x configuration is restored after removing :noboot');
|
||||
|
||||
my $s390x_failure_root = "$tmpdir/tftpboot-s390x-failure";
|
||||
make_path("$s390x_failure_root/pxelinux.cfg/s390x/192.168.144.0_20");
|
||||
my (undef, $s390x_write_error) =
|
||||
xCAT_plugin::mknb::_write_s390x_discovery_config(
|
||||
tftpdir => $s390x_failure_root,
|
||||
network => '192.168.144.0_20',
|
||||
xcatd_address => '192.168.148.10',
|
||||
xcatdport => 3001,
|
||||
consolecmdline => 'console=ttysclp0',
|
||||
initrd => "$s390x_failure_root/xcat/genesis.fs.s390x.gz",
|
||||
);
|
||||
like(
|
||||
$s390x_write_error,
|
||||
qr/^Unable to write s390x Genesis configuration:/,
|
||||
's390x configuration write failures are reported',
|
||||
);
|
||||
|
||||
%xCAT::TableUtils::site_extra = (
|
||||
defserialport => '2',
|
||||
defserialspeed => '9600',
|
||||
defserialflow => 'hard',
|
||||
xcatdport => '3002',
|
||||
);
|
||||
$responses = run_mknb('s390x');
|
||||
generation_succeeded($responses, 's390x ignores PC serial settings');
|
||||
like(
|
||||
read_config($s390x_qemu_path),
|
||||
qr/^ APPEND xcatd=192\.168\.148\.10:3002 xcat\.bootloader=s390-ccw console=ttysclp0$/m,
|
||||
's390x keeps its SCLP console and the configured xcatd port',
|
||||
);
|
||||
|
||||
%xCAT::TableUtils::site_extra = ( dhcpinterfaces => 'eth0,eth1:noboot' );
|
||||
$xCAT::NetworkUtils::nic_ips = { eth0 => '10.0.0.1', eth1 => '192.168.148.10' };
|
||||
$responses = run_mknb('s390x');
|
||||
generation_succeeded($responses, 's390x configuration generation honors :noboot');
|
||||
ok(!-e $s390x_qemu_path, 'a :noboot network gets no QEMU s390x configuration');
|
||||
%xCAT::TableUtils::site_extra = ();
|
||||
$xCAT::NetworkUtils::nic_ips = undef;
|
||||
|
||||
done_testing();
|
||||
|
||||
@@ -27,6 +27,7 @@ make_path(
|
||||
"$tmpdir/share/xcat/netboot/genesis/x86_64/fs",
|
||||
"$tmpdir/share/xcat/netboot/genesis-openembedded/aarch64",
|
||||
"$tmpdir/share/xcat/netboot/genesis-openembedded/ppc64le",
|
||||
"$tmpdir/share/xcat/netboot/genesis-openembedded/s390x",
|
||||
"$tmpdir/share/xcat/netboot/genesis-openembedded/x86_64",
|
||||
);
|
||||
my $symlink_target = "$tmpdir/openembedded-riscv64";
|
||||
@@ -38,25 +39,25 @@ symlink(
|
||||
|
||||
is_deeply(
|
||||
[ _installed_genesis_architectures($tmpdir) ],
|
||||
[ qw(aarch64 ppc64 ppc64le x86_64) ],
|
||||
[ qw(aarch64 ppc64 ppc64le s390x x86_64) ],
|
||||
'xcatconfig ignores linked OpenEmbedded images and finds legacy images',
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
[ _genesis_architectures_to_build($tmpdir, 0) ],
|
||||
[ qw(aarch64 ppc64le x86_64) ],
|
||||
[ qw(aarch64 ppc64le s390x x86_64) ],
|
||||
'an ordinary xCAT update rebuilds only installed OpenEmbedded images',
|
||||
);
|
||||
is_deeply(
|
||||
[ _genesis_architectures_to_build($tmpdir, 1) ],
|
||||
[ qw(aarch64 ppc64 ppc64le x86_64) ],
|
||||
[ qw(aarch64 ppc64 ppc64le s390x x86_64) ],
|
||||
'a legacy package trigger rebuilds every installed Genesis image',
|
||||
);
|
||||
|
||||
make_path("$tmpdir/share/xcat/netboot/genesis-openembedded/unsupported");
|
||||
is_deeply(
|
||||
[ _installed_genesis_architectures($tmpdir) ],
|
||||
[ qw(aarch64 ppc64 ppc64le x86_64) ],
|
||||
[ qw(aarch64 ppc64 ppc64le s390x x86_64) ],
|
||||
'unknown directories are not passed to mknb',
|
||||
);
|
||||
|
||||
@@ -67,7 +68,7 @@ symlink($legacy_target, "$tmpdir/share/xcat/netboot/genesis/ppc64")
|
||||
or die "create legacy directory symlink: $!";
|
||||
is_deeply(
|
||||
[ _installed_genesis_architectures($tmpdir) ],
|
||||
[ qw(aarch64 ppc64 ppc64le x86_64) ],
|
||||
[ qw(aarch64 ppc64 ppc64le s390x x86_64) ],
|
||||
'legacy Genesis directory symlinks remain supported',
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user