2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-10-21 15:18:19 +00:00

test(ubuntu): exercise live-media imports and warnings

Replace source-text assertions with real media imports in an isolated filesystem and database. Run the native fixture before the package build in CI.
This commit is contained in:
Vinícius Ferrão
2026-10-07 21:51:58 -03:00
parent 495bb36db9
commit 114efc35e1
5 changed files with 150 additions and 35 deletions
+4 -1
View File
@@ -9,7 +9,7 @@ jobs:
- name: Refresh package indexes
run: sudo apt-get update
- name: Install dependencies
run: sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests bats bubblewrap gawk mawk rpm rsyslog build-essential fakeroot reprepro devscripts debhelper libcapture-tiny-perl libfile-slurper-perl libjson-perl libyaml-pp-perl libparallel-forkmanager-perl libsoap-lite-perl libdbi-perl libcgi-pm-perl quilt openssh-server dpkg looptools genometools software-properties-common grub-common grub-efi-amd64-bin squashfs-tools pigz
run: sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests bats bubblewrap cpio gawk mawk rpm rsyslog build-essential fakeroot reprepro devscripts debhelper libcapture-tiny-perl libfile-slurper-perl libjson-perl libyaml-pp-perl libparallel-forkmanager-perl libsoap-lite-perl libdbi-perl libdbd-sqlite3-perl libcgi-pm-perl quilt openssh-server dpkg looptools genometools software-properties-common grub-common grub-efi-amd64-bin squashfs-tools pigz
- name: Enable postscript test namespaces
run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
- name: Install lifecycle test dependencies
@@ -19,6 +19,9 @@ jobs:
- name: Prepare xCAT syslog directory
if: ${{ !cancelled() }}
run: sudo install -d -o syslog -g adm -m 0750 /var/log/xcat
- name: Run Ubuntu image fixture tests
if: ${{ !cancelled() }}
run: prove xCAT-test/native/ubuntu_live_media_guardrails.t
- name: Run tests
if: ${{ !cancelled() }}
run: perl github_action_xcat_test.pl
+64
View File
@@ -0,0 +1,64 @@
package XCAT::Test::UbuntuImage;
use strict;
use warnings;
use Capture::Tiny qw(capture_merged);
use File::Basename qw(dirname);
use File::Path qw(make_path);
use File::Slurper qw(read_binary write_binary);
use File::Temp qw(tempdir);
use XCAT::Test::File qw(repo_path);
sub new {
my ($class) = @_;
for my $tool (qw(bwrap timeout cpio gzip perl)) {
die "Ubuntu image tests require $tool\n"
unless grep { -x "$_/$tool" } qw(/usr/bin /bin /usr/sbin /sbin);
}
my $self = bless { root => tempdir(CLEANUP => 1) }, $class;
make_path(map { "$self->{root}/$_" } qw(etc install tmp work/bin work/db));
return $self;
}
sub write {
my ($self, $file, $content) = @_;
my $path = "$self->{root}/$file";
make_path(dirname($path));
write_binary($path, $content);
return $path;
}
sub read {
my ($self, $file) = @_;
return read_binary("$self->{root}/$file");
}
sub run {
my ($self, @command) = @_;
my $root = $self->{root};
my @sandbox = (
'bwrap', '--unshare-all', '--die-with-parent', '--new-session',
'--tmpfs', '/',
(map { ('--ro-bind', $_, $_) } grep { -d $_ } qw(/usr /bin /sbin /lib /lib64)),
'--dev', '/dev', '--proc', '/proc', '--dir', '/run', '--dir', '/sys',
'--dir', '/opt',
'--bind', "$root/etc", '/etc', '--bind', "$root/install", '/install',
'--bind', "$root/tmp", '/tmp', '--bind', "$root/work", '/work',
'--ro-bind', repo_path('.'), '/repo', '--chdir', '/work',
'--setenv', 'PATH', '/work/bin:/usr/bin:/bin:/usr/sbin:/sbin',
'--setenv', 'LC_ALL', 'C', '--setenv', 'XCATROOT', '/repo',
'--setenv', 'XCATCFG', 'SQLite:/work/db',
'--setenv', 'PERL5LIB', '/repo/perl-xCAT:/repo/xCAT-server/lib/perl',
);
push @sandbox, '--ro-bind', '/etc/alternatives', '/etc/alternatives'
if -d '/etc/alternatives';
my ($output, $status) = capture_merged {
local %ENV = (PATH => '/usr/bin:/bin:/usr/sbin:/sbin');
system(@sandbox, 'timeout', '45', @command);
$?;
};
return ($status, $output);
}
1;
@@ -0,0 +1,26 @@
use strict;
use warnings;
use File::Slurper qw(write_binary);
use JSON::PP qw(encode_json);
use xCAT::Table;
my $plugin = '/repo/xCAT-server/lib/xcat/plugins/debian.pm';
require $plugin;
my $site = xCAT::Table->new('site', -create => 1);
$site->setAttribs({ key => 'installdir' }, { value => '/install' });
$site->close();
my @responses;
my $detected = xCAT_plugin::debian::is_ubuntu_live_media('/work/media');
xCAT_plugin::debian::process_request(
{ command => ['copycd'], arg => ['-m', '/work/media', '-o'] },
sub { push @responses, @_ },
);
my $osdistro = xCAT::Table->new('osdistro');
my $row = $osdistro->getAttribs({ osdistroname => 'ubuntu24.04-x86_64' },
qw(arch dirpaths type));
$osdistro->close();
write_binary('/work/result.json', encode_json({ detected => $detected,
responses => \@responses, osdistro => $row }));
@@ -0,0 +1,56 @@
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/../lib";
use JSON::PP qw(decode_json);
use Test::More;
use XCAT::Test::UbuntuImage;
plan skip_all => 'Linux filesystem namespaces are required' unless $^O eq 'linux';
for my $case (
['install-source metadata', ['casper/install-sources.yaml'], 1],
['squashfs payload', ['casper/ubuntu-server.squashfs'], 1],
['both live markers', ['casper/install-sources.yaml', 'casper/root.squashfs'], 1],
['ordinary installer', ['install/vmlinuz'], 0],
['casper without a live marker', ['casper/vmlinuz'], 0],
['similarly named files', ['casper/root.squashfs.bak', 'casper/install-sources.yml'], 0],
['marker outside casper', ['casper/vmlinuz', 'install-sources.yaml', 'root.squashfs'], 0],
) {
my ($name, $files, $live) = @$case;
subtest $name => sub {
my $image = XCAT::Test::UbuntuImage->new();
$image->write('work/media/.disk/info', "Ubuntu-Server 24.04 LTS \"Noble Numbat\" - Release amd64 (20240423)\n");
$image->write('work/media/README.diskdefines', "#define DISKNUM 1\n");
$image->write('work/media/dists/noble/Release', "Suite: noble\n");
$image->write("work/media/$_", "fixture $_\n") for @$files;
my ($status, $output) = $image->run('perl',
'/repo/xCAT-test/native/fixtures/ubuntu_image/media.pl');
is($status, 0, 'copycd request completes') or diag($output);
return unless $status == 0;
my $result = decode_json($image->read('work/result.json'));
is_deeply([grep { $_->{error} || ($_->{data} || '') =~ /^Error/ }
@{ $result->{responses} }], [], 'import reports no errors');
is_deeply($result->{osdistro}, { arch => 'x86_64', type => 'Linux',
dirpaths => '/install/ubuntu24.04/x86_64' }, 'import records the copied distribution');
is($result->{detected}, $live, 'media classification matches its contents');
my @warnings = map { @{ $_->{warning} || [] } } @{ $result->{responses} };
is(scalar @warnings, $live, 'only live media produces a package-source warning');
if ($live) {
like($warnings[0], qr/not a complete Ubuntu apt package mirror/,
'warning explains the live media limitation');
like($warnings[0], qr/linuximage\.pkgdir.*linuximage\.otherpkgdir.*HTTP\/HTTPS/,
'warning identifies configurable package sources');
}
ok(grep({ ($_->{data} || '') eq 'Media copy operation successful' }
@{ $result->{responses} }), 'request reports a successful import');
for my $file (@$files) {
is($image->read("install/ubuntu24.04/x86_64/$file"), "fixture $file\n",
"$file reaches the copied media");
}
};
}
done_testing();
@@ -1,34 +0,0 @@
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/../lib";
use Test::More;
use XCAT::Test::File qw(slurp_repo_file);
my $debian_pm = slurp_repo_file('xCAT-server/lib/xcat/plugins/debian.pm');
like( $debian_pm, qr/sub is_ubuntu_live_media/, 'copycds can detect Ubuntu live media' );
like( $debian_pm, qr/casper\/install-sources\.yaml/, 'copycds recognizes Subiquity install source metadata' );
like( $debian_pm, qr/casper\/\*\.squashfs/, 'copycds recognizes live squashfs media' );
like( $debian_pm, qr/not a complete Ubuntu apt package mirror/, 'copycds warns that Ubuntu live media is not a complete apt mirror' );
like( $debian_pm, qr/linuximage\.pkgdir.*linuximage\.otherpkgdir.*HTTP\/HTTPS Ubuntu apt repository/s, 'copycds warning points to explicit package source attributes' );
my $genimage = slurp_repo_file('xCAT-server/share/xcat/netboot/ubuntu/genimage');
unlike( $genimage, qr{http://archive\.ubuntu\.com/ubuntu/}, 'Ubuntu genimage does not implicitly use the public amd64 archive' );
unlike( $genimage, qr{http://ports\.ubuntu\.com/ubuntu-ports/}, 'Ubuntu genimage does not implicitly use the public ports archive' );
like( $genimage, qr{\$aptcmd2 = "--verbose --arch \$uarch \$dist \$rootimg_dir file://\$srcdir"}, 'Ubuntu genimage uses copied local media when no explicit mirror is configured' );
like( $genimage, qr/copied Ubuntu media.*complete local Ubuntu apt mirror.*HTTP\/HTTPS Ubuntu apt repository/s, 'Ubuntu genimage gives an actionable package source error' );
like( $genimage, qr{\@pkgdir_internet.*?\$aptcmd2 = "--verbose --arch \$uarch \$dist \$rootimg_dir \$mirrorurl"}s, 'Ubuntu genimage still honors an explicit mirror configured in pkgdir' );
my $copycds_doc = slurp_repo_file('docs/source/guides/admin-guides/references/man8/copycds.8.rst');
like( $copycds_doc, qr/Ubuntu live-server media.*not a complete Ubuntu apt package mirror/s, 'copycds documentation explains Ubuntu live media package limits' );
my $linuximage_doc = slurp_repo_file('docs/source/guides/admin-guides/references/man5/linuximage.5.rst');
like( $linuximage_doc, qr/Ubuntu live-server media copied by copycds is not a complete apt package mirror.*HTTP\/HTTPS Ubuntu apt repository/, 'linuximage documentation explains Ubuntu live media package limits' );
my $osimage_doc = slurp_repo_file('docs/source/guides/admin-guides/references/man7/osimage.7.rst');
like( $osimage_doc, qr/Ubuntu live-server media copied by copycds is not a complete apt package mirror.*HTTP\/HTTPS Ubuntu apt repository/, 'osimage documentation explains Ubuntu live media package limits' );
done_testing();