mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-04 20:17:55 +00:00
Merge pull request #7775 from VersatusHPC/fix/anaconda-driver-disk-kernel-arg
fix(anaconda): load the driver disk that is added to the initrd
This commit is contained in:
@@ -84,6 +84,42 @@ sub _centos_linux_distname
|
||||
}
|
||||
|
||||
|
||||
sub _driver_disk_marker_path
|
||||
{
|
||||
my $initrd = shift;
|
||||
|
||||
return unless defined($initrd) && length($initrd);
|
||||
return "$initrd.xcat-driver-disk";
|
||||
}
|
||||
|
||||
|
||||
sub _set_driver_disk_marker
|
||||
{
|
||||
my ($initrd, $present) = @_;
|
||||
my $marker = _driver_disk_marker_path($initrd);
|
||||
|
||||
return $present ? 0 : 1 unless defined($marker);
|
||||
unless ($present) {
|
||||
return 1 unless -e $marker;
|
||||
return unlink($marker) ? 1 : 0;
|
||||
}
|
||||
|
||||
open(my $marker_fh, '>', $marker) or return 0;
|
||||
return close($marker_fh) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
sub _driver_disk_kernel_arg
|
||||
{
|
||||
my ($kversion, $initrd) = @_;
|
||||
my $marker = _driver_disk_marker_path($initrd);
|
||||
|
||||
return '' unless defined($marker) && -f $initrd && -f $marker;
|
||||
return '' if xCAT::Utils->version_cmp($kversion, "7.0") < 0;
|
||||
return " inst.dd=/dd.img";
|
||||
}
|
||||
|
||||
|
||||
sub handled_commands
|
||||
{
|
||||
return {
|
||||
@@ -1375,7 +1411,7 @@ sub mkinstall
|
||||
unless ($noupdateinitrd) {
|
||||
copy($kernpath, "$tftppath");
|
||||
copy($initrdpath, "$tftppath/initrd.img");
|
||||
&insert_dd($callback, $os, $arch, "$tftppath/initrd.img", "$tftppath/vmlinuz", $driverupdatesrc, $netdrivers, $osupdir, $ignorekernelchk);
|
||||
insert_dd($callback, $os, $arch, "$tftppath/initrd.img", "$tftppath/vmlinuz", $driverupdatesrc, $netdrivers, $osupdir, $ignorekernelchk);
|
||||
}
|
||||
}
|
||||
xCAT::MsgUtils->trace($verbose_on_off, "d", "anaconda->mkinstall: copy initrd.img and vmlinuz to $tftppath");
|
||||
@@ -1536,7 +1572,9 @@ sub mkinstall
|
||||
}
|
||||
|
||||
|
||||
#TODO: dd=<url> for driver disks
|
||||
$kcmdline .= _driver_disk_kernel_arg(
|
||||
$kversion, "$tftppath/initrd.img"
|
||||
);
|
||||
if (defined($sent->{serialport})) {
|
||||
unless ($sent->{serialspeed}) {
|
||||
xCAT::MsgUtils->report_node_error($callback, $node, "serialport defined, but no serialspeed for this node in nodehm table");
|
||||
@@ -2579,6 +2617,13 @@ sub insert_dd {
|
||||
my $osupdirlist = shift;
|
||||
my $ignorekernelchk = shift;
|
||||
|
||||
unless (_set_driver_disk_marker($img, 0)) {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "Handle the driver update disk failed. Could not clear the initrd driver disk marker.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
return ();
|
||||
}
|
||||
|
||||
my $install_dir = xCAT::TableUtils->getInstallDir();
|
||||
|
||||
my $cmd;
|
||||
@@ -3363,12 +3408,19 @@ EOMS
|
||||
if ( (&using_dracut($os)) && @dd_list) { #new style, skip the fanagling, copy over the dds and append them...
|
||||
mkpath("$dd_dir/dd");
|
||||
if (scalar(@dd_list) == 1) { #only one, just append it..
|
||||
copy($dd_list[0], "$dd_dir/dd/dd.img");
|
||||
unless (copy($dd_list[0], "$dd_dir/dd/dd.img") && -s "$dd_dir/dd/dd.img") {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "Handle the driver update disk failed. Could not copy the driver disk.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
rmtree $dd_dir;
|
||||
return ();
|
||||
}
|
||||
} elsif (scalar(@dd_list) > 1) {
|
||||
unless (-x "/usr/bin/createrepo" and -x "/usr/bin/mkisofs") {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "Merging multiple driver disks requires createrepo and mkisofs utilities";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
rmtree $dd_dir;
|
||||
return ();
|
||||
}
|
||||
mkpath("$dd_dir/newddimg");
|
||||
@@ -3382,28 +3434,78 @@ EOMS
|
||||
$repodir =~ s/\/repodata\z//;
|
||||
xCAT::Utils->runcmd("createrepo $repodir", -1);
|
||||
}
|
||||
chdir("$dd_dir/newddimg");
|
||||
unless (chdir("$dd_dir/newddimg")) {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "Handle the driver update disk failed. Could not enter the merged driver disk directory.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
rmtree $dd_dir;
|
||||
return ();
|
||||
}
|
||||
xCAT::Utils->runcmd("mkisofs -J -R -o $dd_dir/dd/dd.img .", -1);
|
||||
if ($::RUNCMD_RC != 0 || !-s "$dd_dir/dd/dd.img") {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "Handle the driver update disk failed. Could not merge the driver disks.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
chdir("/");
|
||||
rmtree $dd_dir;
|
||||
return ();
|
||||
}
|
||||
} else { #there should be no else...
|
||||
die "This should never occur";
|
||||
}
|
||||
|
||||
chdir($dd_dir . "/dd");
|
||||
unless (chdir($dd_dir . "/dd")) {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "Handle the driver update disk failed. Could not enter the driver disk directory.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
chdir("/");
|
||||
rmtree $dd_dir;
|
||||
return ();
|
||||
}
|
||||
$cmd = "find .|cpio -H newc -o|gzip -9 -c - > ../dd.gz";
|
||||
xCAT::Utils->runcmd($cmd, -1);
|
||||
unless (-f "../dd.gz") {
|
||||
die "Error attempting to archive driver disk";
|
||||
if ($::RUNCMD_RC != 0 || !-s "../dd.gz") {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "Handle the driver update disk failed. Could not archive the driver disk.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
chdir("/");
|
||||
rmtree $dd_dir;
|
||||
return ();
|
||||
}
|
||||
my $ddhdl;
|
||||
my $inithdl;
|
||||
open($inithdl, ">>", $img);
|
||||
open($ddhdl, "<", "../dd.gz");
|
||||
unless (open($ddhdl, "<", "../dd.gz")) {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "Handle the driver update disk failed. Could not append the driver disk to the initrd.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
chdir("/");
|
||||
rmtree $dd_dir;
|
||||
return ();
|
||||
}
|
||||
unless (open($inithdl, ">>", $img)) {
|
||||
close($ddhdl);
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "Handle the driver update disk failed. Could not append the driver disk to the initrd.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
chdir("/");
|
||||
rmtree $dd_dir;
|
||||
return ();
|
||||
}
|
||||
binmode($ddhdl);
|
||||
binmode($inithdl);
|
||||
{
|
||||
local $/ = \32768;
|
||||
while (my $block = <$ddhdl>) { print $inithdl $block; }
|
||||
}
|
||||
close($ddhdl);
|
||||
unless (close($inithdl) && _set_driver_disk_marker($img, 1)) {
|
||||
my $rsp;
|
||||
push @{ $rsp->{data} }, "Handle the driver update disk failed. Could not record the driver disk in the initrd.";
|
||||
xCAT::MsgUtils->message("E", $rsp, $callback);
|
||||
chdir("/");
|
||||
rmtree $dd_dir;
|
||||
return ();
|
||||
}
|
||||
chdir("/");
|
||||
push @inserted_dd, @dd_list;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Cwd qw(getcwd);
|
||||
use File::Slurper qw(write_text);
|
||||
use File::Spec;
|
||||
use File::Temp qw(tempdir);
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use lib "$FindBin::Bin/../../perl-xCAT";
|
||||
use lib "$FindBin::Bin/../../xCAT-server/lib/perl";
|
||||
use Test::More;
|
||||
|
||||
use XCAT::Test::File qw(repo_path);
|
||||
|
||||
my $plugin = repo_path('xCAT-server/lib/xcat/plugins/anaconda.pm');
|
||||
plan skip_all => 'anaconda.pm not found' unless -r $plugin;
|
||||
$ENV{XCATROOT} ||= repo_path('xCAT-server');
|
||||
require $plugin;
|
||||
|
||||
my $tempdir = tempdir(CLEANUP => 1);
|
||||
my $initrd = File::Spec->catfile($tempdir, 'initrd.img');
|
||||
my $driver_disk = File::Spec->catfile($tempdir, 'vendor-dd.img');
|
||||
write_text($initrd, "base initrd\n");
|
||||
write_text($driver_disk, "driver disk\n");
|
||||
my $base_size = -s $initrd;
|
||||
|
||||
sub insert_driver_disk {
|
||||
my ($source, $fail_archive) = @_;
|
||||
my $cwd = getcwd();
|
||||
my @inserted;
|
||||
my @messages;
|
||||
{
|
||||
no warnings qw(redefine once);
|
||||
my $real_runcmd = \&xCAT::Utils::runcmd;
|
||||
local *xCAT::TableUtils::getInstallDir = sub { return $tempdir; };
|
||||
local *xCAT::MsgUtils::message = sub {
|
||||
my $rsp = $_[2];
|
||||
push @messages, @{ $rsp->{data} || [] };
|
||||
return;
|
||||
};
|
||||
local *xCAT::Utils::runcmd = sub {
|
||||
my ($class, $command, @arguments) = @_;
|
||||
if ($fail_archive && $command =~ /cpio -H newc -o/) {
|
||||
$::RUNCMD_RC = 1;
|
||||
return;
|
||||
}
|
||||
return $real_runcmd->($class, $command, @arguments);
|
||||
};
|
||||
@inserted = xCAT_plugin::anaconda::insert_dd(
|
||||
sub { return; },
|
||||
'rhels9.6', 'x86_64', $initrd, undef,
|
||||
$source, '', '', 0,
|
||||
);
|
||||
}
|
||||
chdir($cwd) or die "Unable to restore $cwd: $!";
|
||||
return ( \@inserted, \@messages );
|
||||
}
|
||||
|
||||
my ($inserted) = insert_driver_disk("dud:$driver_disk");
|
||||
is_deeply($inserted, [$driver_disk], 'insert_dd reports the driver disk it appended');
|
||||
cmp_ok(-s $initrd, '>', $base_size, 'the driver disk archive is appended to the initrd');
|
||||
|
||||
my $marker = xCAT_plugin::anaconda::_driver_disk_marker_path($initrd);
|
||||
ok(-f $marker, 'successful injection records the driver disk beside the initrd');
|
||||
|
||||
is(
|
||||
xCAT_plugin::anaconda::_driver_disk_kernel_arg('6.10', $initrd),
|
||||
'',
|
||||
'anaconda before 7 continues to auto-load the embedded driver disk',
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::anaconda::_driver_disk_kernel_arg('9.6', $initrd),
|
||||
' inst.dd=/dd.img',
|
||||
'anaconda 7 and newer is given the inst.dd argument it reads',
|
||||
);
|
||||
write_text($initrd, "reused initrd\n");
|
||||
is(
|
||||
xCAT_plugin::anaconda::_driver_disk_kernel_arg('9.6', $initrd),
|
||||
' inst.dd=/dd.img',
|
||||
'a later nodeset --noupdateinitrd run reuses the persistent marker',
|
||||
);
|
||||
|
||||
write_text($initrd, "fresh initrd\n");
|
||||
my ($without_disk) = insert_driver_disk(undef);
|
||||
is_deeply($without_disk, [], 'an image without a driver disk reports no insertion');
|
||||
ok(!-e $marker, 'rebuilding without a driver disk clears a stale marker');
|
||||
is(
|
||||
xCAT_plugin::anaconda::_driver_disk_kernel_arg('9.6', $initrd),
|
||||
'',
|
||||
'an image without an injected driver disk receives no kernel argument',
|
||||
);
|
||||
|
||||
my $missing_disk = File::Spec->catfile($tempdir, 'missing-dd.img');
|
||||
my ($failed, $copy_messages) = insert_driver_disk("dud:$missing_disk");
|
||||
is_deeply($failed, [], 'a driver disk that cannot be copied is not reported as inserted');
|
||||
like(join("\n", @{$copy_messages}), qr/Could not copy the driver disk/, 'the failed copy takes the expected error path');
|
||||
ok(!-e $marker, 'failed injection leaves no driver disk marker');
|
||||
|
||||
($inserted) = insert_driver_disk("dud:$driver_disk");
|
||||
ok(-f $marker, 'the marker exists before an archive failure is exercised');
|
||||
my ($archive_failed, $archive_messages) = insert_driver_disk("dud:$driver_disk", 1);
|
||||
is_deeply($archive_failed, [], 'a driver disk that cannot be archived is not reported as inserted');
|
||||
like(join("\n", @{$archive_messages}), qr/Could not archive the driver disk/, 'the failed archive takes the expected error path');
|
||||
ok(!-e $marker, 'a failed driver disk archive leaves no marker');
|
||||
|
||||
ok(
|
||||
xCAT_plugin::anaconda::_set_driver_disk_marker(undef, 0),
|
||||
'clearing a marker for an unavailable initrd is a no-op',
|
||||
);
|
||||
|
||||
done_testing();
|
||||
Reference in New Issue
Block a user