diff --git a/.github/workflows/xcat_test.yml b/.github/workflows/xcat_test.yml index 074cce85d..43616e034 100644 --- a/.github/workflows/xcat_test.yml +++ b/.github/workflows/xcat_test.yml @@ -13,9 +13,9 @@ jobs: - name: Enable postscript test namespaces run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 - name: Install lifecycle test dependencies - run: sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests ucf debconf-utils systemd + run: sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests ucf debconf-utils systemd libxml-simple-perl - name: Test Debian package lifecycle - run: prove -v xCAT-test/native/xcatd_debian_lifecycle.t + run: prove -v xCAT-test/native/xcatd_debian_lifecycle.t xCAT-test/native/xcatd_restart_callers.t - name: Prepare xCAT syslog directory if: ${{ !cancelled() }} run: sudo install -d -o syslog -g adm -m 0750 /var/log/xcat diff --git a/xCAT-test/native/xcatd_restart_callers.t b/xCAT-test/native/xcatd_restart_callers.t new file mode 100644 index 000000000..0182651ac --- /dev/null +++ b/xCAT-test/native/xcatd_restart_callers.t @@ -0,0 +1,72 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use FindBin; +use lib "$FindBin::Bin/../lib"; +use Test::More; +use XCAT::Test::File qw(repo_path); +use XCAT::Test::Lifecycle; + +plan skip_all => 'Run on Linux; missing namespace or RPM spec tools fail' unless $^O eq 'linux'; + +sub succeeds { + my ($label, @result) = @_; + is($result[0], 0, $label) or diag "$result[1]$result[2]"; +} + +for my $live (0, 1) { + for my $event (qw(upgrade remove purge abort-upgrade)) { + for my $installed (0, 1) { + my $root = XCAT::Test::Lifecycle->new; + $root->{live} = $live; + $root->record_command('/opt/xcat/sbin/restartxcatd') if $installed; + $root->write('/calls', ''); + succeeds("Debian perl-xCAT $event (proc=$live)", $root->run('/bin/sh', + '/source/perl-xCAT/debian/postrm', $event, '2.20.0')); + is($root->read('/calls'), $live && $installed && $event eq 'upgrade' ? "restartxcatd <-r>\n" : '', + 'only an upgrade with proc and an installed helper requests a fast reload'); + } + } +} + +for my $package (qw(xCAT-OpenStack xCAT-UI perl-xCAT)) { + my $records = XCAT::Test::Lifecycle::checked('rpmspec', '-q', '--qf', "%{NAME}\x1e%{POSTIN}\x1e", + '--define', 'version 2.20.0', '--define', 'release 1', '--define', 'gitinfo test', + repo_path("$package/$package.spec")); + my %scriptlets = split /\x1e/, $records; + my $script = $scriptlets{$package}; + die "Missing $package post-install script" unless defined($script) && $script ne '(none)'; + for my $live (0, 1) { + for my $event (1, 2) { + for my $installed (0, 1) { + my $root = XCAT::Test::Lifecycle->new; + $root->{live} = $live; + $root->write('/postin', $script); + $root->write('/calls', ''); + $root->write('/etc/profile.d/xcat.sh', "printf 'profile\\n' >> /calls\n"); + for my $name (qw(restartxcatd xcatd chtab)) { + $root->record_command("/opt/xcat/sbin/$name") if $installed || $name eq 'chtab'; + } + $root->record_command('/etc/init.d/httpd'); + $root->record_command('/test-bin/hostname'); + $root->write('/etc/redhat-release', 'test'); + $root->write('/etc/shadow', "root:*:0:0:0:0:0:0:0\n"); + $root->write('/etc/php.ini', "output_buffering = 4096\n"); + $root->write('/opt/xcat/ui/.fixture', ''); + succeeds("$package event $event (proc=$live)", $root->run('env', + 'RPM_INSTALL_PREFIX0=/opt/xcat', '/bin/sh', '/postin', $event)); + my $calls = $root->read('/calls'); + if ($package eq 'perl-xCAT') { + is($calls, $live && $installed && $event == 2 ? "profile\n" : '', + 'upgrade detects the server without a legacy init script'); + } else { + my @restarts = $calls =~ /^(restartxcatd[^\n]*)$/mg; + is_deeply(\@restarts, $installed && ($package eq 'xCAT-UI' || $live) ? ['restartxcatd'] : [], + 'package preserves fast restart semantics'); + } + } + } + } +} + +done_testing(); diff --git a/xCAT-test/unit/imgport_restart.t b/xCAT-test/unit/imgport_restart.t new file mode 100644 index 000000000..36ca61294 --- /dev/null +++ b/xCAT-test/unit/imgport_restart.t @@ -0,0 +1,49 @@ +#!/usr/bin/env perl +use strict; +use warnings; +no warnings 'once'; +use FindBin; +use lib "$FindBin::Bin/../lib", "$FindBin::Bin/../../perl-xCAT", "$FindBin::Bin/../../xCAT-server/lib/perl"; +use Test::More; +use File::Path qw(make_path); +use File::Temp qw(tempdir); +use File::Slurper qw(read_binary write_binary); +use Capture::Tiny qw(capture); +use XCAT::Test::File qw(repo_path); + +my $root = tempdir(CLEANUP => 1); +local $ENV{XCATROOT} = repo_path('xCAT-server'); +local $ENV{XCATCFG} = "$root/cfg"; +make_path($ENV{XCATCFG}, "$root/xcat/sbin", "$root/xcat/lib/perl/xCAT_plugin", "$root/import"); +require(repo_path('xCAT-server/lib/xcat/plugins/imgport.pm')); +local $::XCATROOT = "$root/xcat"; +write_binary("$root/xcat/sbin/restartxcatd", "#!/bin/sh\nprintf 'restart' >> '$root/calls'\n" . + "for arg do printf ' <%s>' \"\$arg\" >> '$root/calls'; done\nprintf '\\n' >> '$root/calls'\n"); +chmod 0755, "$root/xcat/sbin/restartxcatd" or die "chmod: $!"; +write_binary("$root/calls", ''); + +{ + no warnings 'redefine'; + local *xCAT::TableUtils::getInstallDir = sub { "$root/install" }; + for my $case ([first => 0], [second => 1], [third => 0]) { + my ($kit, $has_plugin) = @$case; + make_path("$root/import/$kit/plugins"); + write_binary("$root/import/$kit/plugins/example.pm", "plugin fixture\n") if $has_plugin; + my $data = { + osimage => {osvers => 'test', osarch => 'x86_64', profile => 'compute', provmethod => 'install'}, + linuximage => {}, kit => {$kit => {kitdir => "$root/kits/$kit"}}, + }; + my @messages; + my ($out, $err, $result) = capture { + xCAT_plugin::imgport::make_files($data, "$root/import", sub { push @messages, $_[0] }); + }; + is($result, 1, "import succeeds (plugin=$has_plugin)") or diag "$out$err"; + ok(!grep({ $_->{error} } @messages), 'import reports no errors'); + if ($has_plugin) { + is(read_binary("$root/xcat/lib/perl/xCAT_plugin/example.pm"), "plugin fixture\n", 'plugin reaches the daemon directory'); + is(read_binary("$root/calls"), "restart\n", 'plugin import requests a fast restart'); + } + } +} +is(read_binary("$root/calls"), "restart\n", 'imports without plugins do not request another restart'); +done_testing(); diff --git a/xCAT-test/unit/xcatd_restart_callers.t b/xCAT-test/unit/xcatd_restart_callers.t deleted file mode 100644 index 2cfdf73f5..000000000 --- a/xCAT-test/unit/xcatd_restart_callers.t +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env perl -use strict; -use warnings; - -use File::Spec; -use FindBin; -use Test::More; - -my $repo_root = File::Spec->catdir( $FindBin::Bin, '..', '..' ); - -sub read_file { - my ($path) = @_; - open( my $fh, '<', $path ) or die "Unable to read $path: $!"; - my $contents = do { local $/; <$fh> }; - close($fh); - return $contents; -} - -my $unit = read_file( - File::Spec->catfile( $repo_root, 'xCAT-server', 'etc', 'init.d', 'xcatd.service' ) -); -unlike( $unit, qr{/etc/init\.d/xcatd}, - 'the native systemd unit does not invoke the legacy script' ); -like( $unit, qr{^ExecStart=.*?/usr/sbin/xcatd}m, - 'the native systemd unit starts xcatd directly' ); - -my $imgport = read_file( - File::Spec->catfile( $repo_root, 'xCAT-server', 'lib', 'xcat', 'plugins', 'imgport.pm' ) -); -like( $imgport, qr{system\("\$::XCATROOT/sbin/restartxcatd"\)}, - 'imgport preserves the xcatd fast-restart path' ); -unlike( $imgport, qr{xCAT::Utils->restartservice\("xcatd"\)}, - 'imgport does not replace a fast restart with a full service restart' ); -unlike( $imgport, qr{system\("/etc/init\.d/xcatd}, - 'imgport no longer hard-codes the legacy init path' ); - -my %reload_callers = ( - 'xCAT-OpenStack Debian scriptlet' => 'xCAT-OpenStack/debian/postinst', - 'xCAT-rmc Debian scriptlet' => 'xCAT-rmc/debian/postinst', - 'perl-xCAT Debian scriptlet' => 'perl-xCAT/debian/postrm', -); - -foreach my $name ( sort keys %reload_callers ) { - my $caller = read_file( - File::Spec->catfile( $repo_root, split( '/', $reload_callers{$name} ) ) - ); - like( $caller, qr{/sbin/restartxcatd -r}, - "$name preserves xcatd fast-reload semantics" ); - unlike( $caller, qr{systemctl restart xcatd|/etc/init\.d/xcatd}, - "$name does not perform a full restart or require the legacy init path" ); -} - -my %restart_callers = ( - 'xCAT-OpenStack RPM scriptlet' => 'xCAT-OpenStack/xCAT-OpenStack.spec', - 'xCAT-UI RPM scriptlet' => 'xCAT-UI/xCAT-UI.spec', -); - -foreach my $name ( sort keys %restart_callers ) { - my $caller = read_file( - File::Spec->catfile( $repo_root, split( '/', $restart_callers{$name} ) ) - ); - like( $caller, qr{/sbin/restartxcatd}, - "$name preserves xcatd fast-restart semantics" ); - unlike( $caller, qr{systemctl restart xcatd|/etc/init\.d/xcatd}, - "$name does not perform a full restart or require the legacy init path" ); -} - -my $xcatsn_deb = read_file( - File::Spec->catfile( $repo_root, 'xCATsn', 'debian', 'postinst' ) -); -like( $xcatsn_deb, - qr{systemctl start xcatd\.service.*?elif \[ -x /etc/init\.d/xcatd \]}s, - 'xCATsn Debian starts xcatd under the native service manager' ); - -my $xcatsn_spec = read_file( - File::Spec->catfile( $repo_root, 'xCATsn', 'xCATsn.spec' ) -); -like( $xcatsn_spec, - qr{systemctl restart xcatd\.service.*?elif \[ -x /etc/init\.d/xcatd \]}s, - 'xCATsn RPM retains its existing service-node restart with a legacy fallback' ); - -my $perl_xcat_spec = read_file( - File::Spec->catfile( $repo_root, 'perl-xCAT', 'perl-xCAT.spec' ) -); -unlike( $perl_xcat_spec, qr{/etc/init\.d/xcatd}, - 'perl-xCAT upgrade logic no longer assumes the legacy init path exists' ); -like( $perl_xcat_spec, qr{\$RPM_INSTALL_PREFIX0/sbin/xcatd}, - 'perl-xCAT detects the installed server independently of its init system' ); - -done_testing();