Code drop for the enhancement of driver enjection to initrd (port back from 2.8 branch) 1. support both stateful and stateless; 2. support to take drivers from osupdatedistro; 3. support the allupdate and updateonly in netdrivers attribute

This commit is contained in:
daniceexi 2013-09-26 05:47:22 -04:00
parent b892b556d3
commit b84251a03f
6 changed files with 387 additions and 93 deletions

View File

@ -0,0 +1,100 @@
=head1 NAME
B<genimage> - Generate an initrd (initial ramfs) which to be used for statefull install or stateless netboot.
=head1 SYNOPSIS
B<geninitrd> <imagename>
B<geninitrd> [B<-h> | B<--help>]
=head1 DESCRIPTION
Generate the initrd for the osimage: B<imagename> which is an xCAT object of I<osimage> type.
B<Diskfull Osimage>
=over 2
If the B<imagename> is a statefull one (The provmethod attribute for the osimage is 'install'),
this command is used to rebuild the initrd to inject the new drivers from driver rpms or
'update distro' and copy the rebuilt initrd and new kernel (If there's new kernel in 'update
distro') to the directory I</tftpboot/xcat/<imagename>>.
If the initrd has been rebuilt by geninitrd, when run nodeset, the I<--noupdateinitrd> option
should be used to skip the rebuilding of initrd to improve the performance.
Three attributes of osimage object can be used to specify the Driver RPM location and Driver names
for injecting new drviers to initrd.
B<netdrivers> - comma separated driver names that need to be injected to the initrd.
The postfix '.ko' can be ignored. The netdrivers attribute must be set to specify the new driver list.
If you want to load all the drivers from the driver rpms, using the keyword allupdate.
B<driverupdatesrc> - comma separated driver rpm packages (full path should be specified)
B<osupdatename> - comma separated 'osdistroupdate' object. Each 'osdistroupdate' object specifies a
Linux distro update. When run geninitrd, 'kernel-*.rpm' will be searched from osdistroupdate.dirpath
to get all the rpm packages and then search the drivers from the rpm packages.
Refer to the doc: https://sourceforge.net/apps/mediawiki/xcat/index.php?title=Using_Linux_Driver_Update_Disk
=back
B<Stateless Osimage>
=over 2
If the B<imagename> is a stateless one (The provmethod attribute for the osimage is 'netboot'),
this command is used to generate the initrd from the rootimg which generated by 'genimage' command.
So the 'genimage' must be run once before running the geninitrd command.
Two attributes of osimage object can be used to specify the Driver RPM location and Driver names
for injecting new drviers to initrd.
B<netdrivers> - comma separated driver names that need to be injected to the initrd.
The postfix '.ko' can be ignored. The netdrivers attribute must be set to specify the new driver list.
If you want to load all the drivers from the driver rpms, using the keyword allupdate.
B<driverupdatesrc> - comma separated driver rpm packages (full path should be specified)
=back
=head1 Parameters
I<imagename> specifies the name of an os image definition to be used. The specification for the image is storted in the I<osimage> table and I<linuximage> table.
=head1 RETURN VALUE
0 The command completed successfully.
1 An error has occurred.
=head1 EXAMPLES
=over 3
=item 1
To generate initrd for the osimage B<myimagename>:
geninitrd myimagename
=back
=head1 FILES
/opt/xcat/bin/geninitrd
/opt/xcat/bin/genimage
/opt/xcat/share/xcat/netboot/<OS>/genimage
=head1 SEE ALSO
L<geninitrd(1)|geninitrd.1>, L<genimage(1)|genimage.1>

View File

@ -6,6 +6,8 @@ B<nodeset> - set the boot state for a noderange
B<nodeset> [I<noderange>] [I<boot>|I<install>|I<stat>|I<iscsiboot>|I<netboot>|I<statelite>|I<offline>|I<runcmd=bmcsetup>|I<osimage[=<imagename>>]]
B<nodeset> I<noderange> [I<osimage=<imagename>> I<--noupdateinitrd>]
B<nodeset> [I<-h>|I<--help>|I<-v>|I<--version>]
=head1 B<Description>
@ -67,6 +69,11 @@ Cleanup the current pxe/tftp boot configuration files for the nodes requested
Prepare server for installing a node using the specified os image. The os image is defined in the I<osimage> table and I<linuximage> table. If the <imagename> is omitted, the os image name will be obtained from I<nodetype.provmethod> for the node.
=item B<--noupdateinitrd>
Skip the rebuilding of initrd when the 'netdrivers', 'drvierupdatesrc' or 'osupdatename' were set for injecting new drviers to initrd. But, the geninitrd command
should be run to rebuild the initrd for new drivers injecting. This is used to improve the performance of nodeset command.
=item B<runimage>=<task>>
If you would like to run a task after deployment, you can define that task with this attribute.

View File

@ -172,6 +172,7 @@ sub mknetboot
my $nodes = @{$req->{node}};
my @args = @{$req->{arg}} if(exists($req->{arg}));
my @nodes = @{$req->{node}};
my $noupdateinitrd = $req->{'noupdateinitrd'};
my $ostab = xCAT::Table->new('nodetype');
#my $sitetab = xCAT::Table->new('site');
my $linuximagetab;
@ -520,7 +521,7 @@ sub mknetboot
}
}
if ($docopy) {
if ($docopy && !$noupdateinitrd) {
mkpath("$tftppath");
if (-f "$rootimgdir/hypervisor") {
copy("$rootimgdir/hypervisor", "$tftppath");
@ -1576,7 +1577,8 @@ sub mksysclone
}
}
# copy postscripts
# copy postscripts, the xCAT scripts may update, but the image is captured long time ago
# should update the scripts at each nodeset
my $script1 = "configefi";
my $script2 = "updatenetwork";
my $pspath = "$installroot/sysclone/scripts/post-install/";
@ -2428,6 +2430,7 @@ sub insert_dd {
my @rpm_list;
my @driver_list;
my $Injectalldriver;
my $updatealldriver;
my @rpm_drivers;
@ -2472,6 +2475,9 @@ sub insert_dd {
if (/^allupdate$/) {
$Injectalldriver = 1;
next;
} elsif (/^updateonly$/) {
$updatealldriver = 1;
next;
}
unless (/\.ko$/) {
s/$/.ko/;
@ -2482,7 +2488,7 @@ sub insert_dd {
chomp(@dd_list);
chomp(@rpm_list);
unless (@dd_list || (@rpm_list && ($Injectalldriver || @driver_list))) {
unless (@dd_list || (@rpm_list && ($Injectalldriver || $updatealldriver || @driver_list))) {
return ();
}
@ -2493,7 +2499,7 @@ sub insert_dd {
# dracut + drvier rpm
# !dracut + driver rpm
# !dracut + driver disk
if (!<$install_dir/$os/$arch/Packages/dracut*> || (@rpm_list && ($Injectalldriver || @driver_list))) {
if (!<$install_dir/$os/$arch/Packages/dracut*> || (@rpm_list && ($Injectalldriver || $updatealldriver || @driver_list))) {
mkpath "$dd_dir/initrd_img"; # The dir for the new initrd
# unzip the initrd image
@ -2512,19 +2518,26 @@ sub insert_dd {
} elsif ( grep (/LZMA compressed data/, @format)) {
$initrdfmt = "lzma";
} else {
my $rsp;
push @{$rsp->{data}}, "Could not handle the format of the initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return ();
# check whether it can be handled by xz
$cmd = "xz -t $img";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Could not handle the format of the initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return ();
} else {
$initrdfmt = "lzma";
}
}
if ($initrdfmt eq "gzip") {
$cmd = "gunzip -c $img > $dd_dir/initrd";
} elsif ($initrdfmt eq "lzma") {
if (! -x "/usr/bin/lzma") {
if (! -x "/usr/bin/xz") {
my $rsp;
push @{$rsp->{data}}, "The format of initrd for the target node is \'lzma\', but this management node has not lzma command.";
push @{$rsp->{data}}, "The format of initrd for the target node is \'lzma\', but this management node has not xz command.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return ();
}
@ -2549,13 +2562,12 @@ sub insert_dd {
}
my $new_kernel_ver;
if (@rpm_list && ($Injectalldriver || @driver_list)) {
if (@rpm_list && ($Injectalldriver || $updatealldriver || @driver_list)) {
# Extract the files from rpm to the tmp dir
mkpath "$dd_dir/rpm";
foreach my $rpm (@rpm_list) {
if (-r $rpm) {
$cmd = "cd $dd_dir/rpm; rpm2cpio $rpm | cpio -idum";
#$cmd = "rpm -i --quiet --nodeps --force --ignorearch --ignoreos --nosignature --root $dd_dir/rpm $rpm";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
@ -2572,17 +2584,17 @@ sub insert_dd {
# and copy it to the /tftpboot
my @new_kernels = <$dd_dir/rpm/boot/vmlinuz*>;
foreach my $new_kernel (@new_kernels) {
if (-r $new_kernel && $new_kernel =~ /\/vmlinuz-(.*(x86_64|ppc64))$/) {
$new_kernel_ver = $1;
$cmd = "/bin/mv -f $new_kernel $kernelpath";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not move $new_kernel to $kernelpath.";
xCAT::MsgUtils->message("I", $rsp, $callback);
if (-r $new_kernel && $new_kernel =~ /\/vmlinuz-(.*(x86_64|ppc64|el\d+))$/) {
$new_kernel_ver = $1;
$cmd = "/bin/mv -f $new_kernel $kernelpath";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not move $new_kernel to $kernelpath.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
}
}
# To skip the conflict of files that some rpm uses the xxx.ko.new as the name of the driver
# Change it back to xxx.ko here
@ -2613,7 +2625,7 @@ sub insert_dd {
# For dracut mode, only copy the drivers from rpm packages to the /lib/modules/<kernel>
# The driver disk will be handled that append the whole disk to the orignial initrd
if (@rpm_list && ($Injectalldriver || @driver_list)) {
if (@rpm_list && ($Injectalldriver || $updatealldriver || @driver_list)) {
# Copy the firmware to the rootimage
if (-d "$dd_dir/rpm/lib/firmware") {
if (! -d "$dd_dir/initrd_img/lib/firmware") {
@ -2628,14 +2640,15 @@ sub insert_dd {
}
}
# if the new kernel from update distro is not existed in initrd, copy all the modules for the new kernel to initrd
if ((! -r "$dd_dir/initrd_img/lib/modules/$new_kernel_ver") && (-r "$dd_dir/rpm/lib/modules/$new_kernel_ver")) {
$cmd = "/bin/cp -rf $dd_dir/rpm/lib/modules/$new_kernel_ver $dd_dir/initrd_img/lib/modules/";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not copy $dd_dir/rpm/lib/modules/$new_kernel_ver to $dd_dir/initrd_img/lib/modules.";
xCAT::MsgUtils->message("E", $rsp, $callback);
# get the name list for all drivers in the original initrd if 'netdrivers=updateonly'
# then only the drivers in this list will be updated from the drvier rpms
if ($updatealldriver) {
$driver_name = "\*\.ko";
@all_real_path = ();
find(\&get_all_path, <$dd_dir/initrd_img/lib/modules/*>);
foreach my $real_path (@all_real_path) {
my $driver = basename($real_path);
push @driver_list, $driver;
}
}
@ -2643,9 +2656,19 @@ sub insert_dd {
# Figure out the kernel version
my @kernelpaths = <$dd_dir/initrd_img/lib/modules/*>;
my @kernelvers;
if ($new_kernel_ver) {
push @kernelvers, $new_kernel_ver;
}
# if new kernel is used, remove all the original kernel directories
foreach (@kernelpaths) {
if (basename($_) =~ /^[\d\.]+/) {
push @kernelvers, basename($_);
my $kernelv = basename($_);
if ($kernelv =~ /^[\d\.]+/) {
if ($new_kernel_ver) {
rmtree ("$dd_dir/initrd_img/lib/modules/$kernelv");
} else {
push @kernelvers, $kernelv;
}
}
}
@ -2655,6 +2678,7 @@ sub insert_dd {
}
if (@driver_list) {
foreach my $driver (@driver_list) {
$driver =~ s/\.gz$//;
$driver_name = $driver;
@all_real_path = ();
find(\&get_all_path, <$dd_dir/rpm/lib/modules/$kernelver/*>);
@ -2698,7 +2722,7 @@ sub insert_dd {
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not generate the depdency for the drivers in the initrd.";
push @{$rsp->{data}}, "Handle the driver update failed. Could not generate the drivers depdency for $kernelver in the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
@ -2817,7 +2841,7 @@ sub insert_dd {
}
# Merge the drviers from rpm packages to the initrd
if (@rpm_list && ($Injectalldriver || @driver_list)) {
if (@rpm_list && ($Injectalldriver || $updatealldriver || @driver_list)) {
# Copy the firmware to the rootimage
if (-d "$dd_dir/rpm/lib/firmware") {
if (! -d "$dd_dir/initrd_img/lib") {
@ -2837,18 +2861,44 @@ sub insert_dd {
mkpath ("$dd_dir/modules/$new_kernel_ver/$arch/");
}
# get the name list for all drivers in the original initrd if 'netdrivers=updateonly'
# then only the drivers in this list will be updated from the drvier rpms
if ($updatealldriver) {
$driver_name = "\*\.ko";
@all_real_path = ();
find(\&get_all_path, <$dd_dir/modules/*>);
foreach my $real_path (@all_real_path) {
my $driver = basename($real_path);
push @driver_list, $driver;
}
}
# Copy the drivers to the initrd
# Figure out the kernel version
my @kernelpaths = <$dd_dir/modules/*>;
my @kernelvers;
if ($new_kernel_ver) {
push @kernelvers, $new_kernel_ver;
}
foreach (@kernelpaths) {
push @kernelvers, basename($_);
my $kernelv = basename($_);
if ($kernelv =~ /^[\d\.]+/) {
if ($new_kernel_ver) {
rmtree ("$dd_dir/modules/$kernelv");
} else {
push @kernelvers, $kernelv;
}
}
}
foreach my $kernelver (@kernelvers) {
unless (-d "$dd_dir/rpm/lib/modules/$kernelver") {
next;
}
# create path for the new kernel in the modules package
unless (-d "$dd_dir/modules/$kernelver") {
mkpath ("$dd_dir/modules/$kernelver/$arch/");
}
# find the $kernelver/$arch dir in the $dd_dir/modules
my $arch4modules;
foreach (<$dd_dir/modules/$kernelver/*>) {
@ -2924,13 +2974,23 @@ sub insert_dd {
if (-d $ma) {
mkpath "$dd_dir/depmod/lib/modules/$mk";
xCAT::Utils->runcmd("/bin/cp -rf $ma/* $dd_dir/depmod/lib/modules/$mk", -1);
$cmd = "depmod -b $dd_dir/depmod/";
$cmd = "depmod -b $dd_dir/depmod/ $mk";
#$cmd = "depmod -b $dd_dir/depmod/";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not generate the depdency for the drivers in the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
# remove the .ko postfix from the driver name for rh5
$cmd = "/bin/sed ".'s/\.ko//g'." $dd_dir/depmod/lib/modules/$mk/modules.dep > $dd_dir/depmod/lib/modules/$mk/modules.dep1; mv -f $dd_dir/depmod/lib/modules/$mk/modules.dep1 $dd_dir/depmod/lib/modules/$mk/modules.dep";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not generate the depdency for the drivers in the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
if (-f "$dd_dir/depmod/lib/modules/$mk/modules.dep") {
copy ("$dd_dir/depmod/lib/modules/$mk/modules.dep", "$dd_dir/initrd_img/modules/modules.dep");
}
@ -3004,7 +3064,7 @@ sub insert_dd {
if ($initrdfmt eq "gzip") {
$cmd = "cd $dd_dir/initrd_img; find .|cpio -H newc -o|gzip -9 -c - > $dd_dir/initrd.img";
} elsif ($initrdfmt eq "lzma") {
$cmd = "cd $dd_dir/initrd_img; find .|cpio -H newc -o|lzma -C crc32 -9 > $dd_dir/initrd.img";
$cmd = "cd $dd_dir/initrd_img; find .|cpio -H newc -o|xz --format=lzma -C crc32 -9 > $dd_dir/initrd.img";
}
xCAT::Utils->runcmd($cmd, -1);
@ -3072,13 +3132,25 @@ sub insert_dd {
my $rsp;
if (@dd_list) {
push @{$rsp->{data}}, "Inserted the driver update disk:".join(',',@inserted_dd).".";
push @{$rsp->{data}}, "The driver update disk:".join(',',@inserted_dd)." have been injected to initrd.";
}
if (@driver_list) {
push @{$rsp->{data}}, "Inserted the drivers:".join(',', sort(@rpm_drivers))." from driver packages.";
} elsif (@rpm_list && ($Injectalldriver || @driver_list)) {
push @{$rsp->{data}}, "Inserted the drivers from driver packages:".join(',', sort(@rpm_list)).".";
# remove the duplicated names
my %dnhash;
foreach (@rpm_drivers) {
$dnhash{$_} = 1;
}
@rpm_drivers = keys %dnhash;
if (@rpm_list) {
if (@rpm_drivers) {
push @{$rsp->{data}}, "The drivers:".join(',', sort(@rpm_drivers))." from ".join(',', sort(@rpm_list))." have been injected to initrd.";
} elsif ($Injectalldriver) {
push @{$rsp->{data}}, "All the drivers from :".join(',', sort(@rpm_list))." have been injected to initrd.";
} else {
push @{$rsp->{data}}, "No driver was injected to initrd.";
}
}
xCAT::MsgUtils->message("I", $rsp, $callback);
return @inserted_dd;

View File

@ -10,6 +10,7 @@ use xCAT::SvrUtils;
use xCAT::Table;
#use Data::Dumper;
use File::Path;
use File::Copy;
use Getopt::Long;
Getopt::Long::Configure("bundling");
Getopt::Long::Configure("pass_through");
@ -169,6 +170,7 @@ sub process_request {
$otherpkglist = $ref_linuximage_tab->{'otherpkglist'};
$postinstall_filename = $ref_linuximage_tab->{'postinstall'};
$destdir = $ref_linuximage_tab->{'rootimgdir'};
$rootimg_dir = $ref_linuximage_tab->{'rootimgdir'};
$driverupdatesrc = $ref_linuximage_tab->{'driverupdatesrc'};
# TODO: how can we do if the user specifies one wrong value to the following attributes?
@ -363,6 +365,31 @@ sub process_request {
# print FILE "\n";
#}
#close FILE;
# update the generated initrd to /tftpboot/xcat so that don't need to rerun nodeset to update them
if (($::RUNCMD_RC == 0) && $imagename) {
my $tftpdir = "/tftpboot";
my @siteents = xCAT::TableUtils->get_site_attribute("tftpdir");
if ($#siteents >= 0)
{
$tftpdir = $siteents[0];
}
my $tftppath = "$tftpdir/xcat/osimage/$imagename";
my $installdir = "/install";
@siteents = xCAT::TableUtils->get_site_attribute("installdir");
if ($#siteents >= 0)
{
$installdir = $siteents[0];
}
unless (-d $tftppath) {
mkpath $tftppath;
}
copy("$rootimg_dir/initrd-stateless.gz", "$tftppath");
copy("$rootimg_dir/initrd-statelite.gz", "$tftppath");
copy("$rootimg_dir/kernel", "$tftppath");
}
#parse the output and save the image data to osimage and linuximage table
save_image_data($callback, $doreq, $tempfile);

View File

@ -7,6 +7,7 @@ BEGIN
use strict;
use lib "$::XCATROOT/lib/perl";
use File::Path;
use File::Copy;
use xCAT::MsgUtils;
use xCAT::TableUtils;
@ -25,8 +26,28 @@ sub preprocess_request
my $req = shift;
my $callback = shift;
unless (defined ($req->{arg}) && $req->{arg}->[0]) {
xCAT::MsgUtils->message("E", {error=>["An osimage name needs to be specified."], errorcode=>["1"]}, $callback);
my $usage = sub {
my $callback = shift;
xCAT::MsgUtils->message("I", {data=>["Usage: geninitrd <imagename> [-h | --help]"]}, $callback);
};
my $osimage;
if (defined ($req->{arg})) {
foreach (@{$req->{arg}}) {
if (/^-/) {
$usage->($callback);
return;
}else {
$osimage = $_;
}
}
} else {
$usage->($callback);
return;
}
unless ($osimage) {
$usage->($callback);
return;
}
@ -45,10 +66,11 @@ sub process_request
{
my $req = shift;
my $callback = shift;
my $doreq = shift;
if ($req->{command}->[0] eq 'geninitrd')
{
return geninitrd($req, $callback);
return geninitrd($req, $callback, $doreq);
}
}
@ -56,6 +78,7 @@ sub process_request
sub geninitrd {
my $req = shift;
my $callback = shift;
my $doreq = shift;
my $osimage = $req->{arg}->[0];
@ -68,7 +91,7 @@ sub geninitrd {
return;
}
my $oient = $osimagetab->getAttribs({imagename => $osimage}, 'osvers', 'osarch', 'osupdatename');
my $oient = $osimagetab->getAttribs({imagename => $osimage}, 'provmethod', 'osvers', 'osarch', 'osupdatename');
unless ($oient && $oient->{'osvers'} && $oient->{'osarch'} ) {
xCAT::MsgUtils->message("E", {error=>["The osimage [$osimage] was not defined or [osvers, osarch] attributes were not set."], errorcode=>["1"]}, $callback);
return;
@ -83,7 +106,7 @@ sub geninitrd {
return;
}
my $lient = $linuximagetab->getAttribs({imagename => $osimage}, 'pkgdir', 'driverupdatesrc', 'netdrivers');
my $lient = $linuximagetab->getAttribs({imagename => $osimage}, 'rootimgdir', 'pkgdir', 'driverupdatesrc', 'netdrivers');
unless ($lient && $lient->{'pkgdir'}) {
xCAT::MsgUtils->message("E", {error=>["The osimage [$osimage] was not defined or [pkgdir] attribute was not set."], errorcode=>["1"]}, $callback);
return;
@ -92,6 +115,27 @@ sub geninitrd {
$driverupdatesrc = $lient->{'driverupdatesrc'};
$netdrivers = $lient->{'netdrivers'};
# if the provmethod equals 'netboot', call the genimage --onlyinitrd directly
if ($oient->{'provmethod'} && ($oient->{'provmethod'} eq "netboot" || $oient->{'provmethod'} eq "statelite")) {
if ($lient->{'rootimgdir'}) {
unless (-d $lient->{'rootimgdir'}."/rootimg/lib/modules") {
xCAT::MsgUtils->message("E", {error=>["The genimage should be run before running geninitrd."], errorcode=>["1"]}, $callback);
return;
}
} else {
xCAT::MsgUtils->message("E", {error=>["The rootimgdir attribute for the osimage should be set."], errorcode=>["1"]}, $callback);
return;
}
my @output = `genimage $osimage --onlyinitrd`;
xCAT::MsgUtils->message("I", {data=>\@output}, $callback);
#$doreq->({ command => ['genimage'],
# arg => [$osimage, '--onlyinitrd'] }, $callback);
return;
} elsif (!$oient->{'provmethod'} || $oient->{'provmethod'} ne "install") {
xCAT::MsgUtils->message("E", {error=>["The attribute [provmethod] for osimage [$osimage] must be set to install, netboot or statelite."], errorcode=>["1"]}, $callback);
return;
}
# get the path list of the osdistroupdate
if ($oient->{'osupdatename'}) {
my @osupdatenames = split (/,/, $oient->{'osupdatename'});
@ -127,6 +171,9 @@ sub geninitrd {
$tftpdir = $t_entry;
}
my $tftppath = "$tftpdir/xcat/osimage/$osimage";
unless (-d $tftppath) {
mkpath $tftppath;
}
if ($arch =~ /x86/) {
if ($osvers =~ /(^ol[0-9].*)|(centos.*)|(rh.*)|(fedora.*)|(SL.*)/) {
$kernelpath = "$tftppath/vmlinuz";

View File

@ -55,6 +55,7 @@ sub mknetboot
my $globaltftpdir = "/tftpboot";
my $nodes = @{$req->{node}};
my @nodes = @{$req->{node}};
my $noupdateinitrd = $req->{'noupdateinitrd'};
my $ostab = xCAT::Table->new('nodetype');
#my $sitetab = xCAT::Table->new('site');
my $linuximagetab;
@ -404,7 +405,7 @@ sub mknetboot
}
}
if ($docopy) {
if ($docopy && !$noupdateinitrd) {
mkpath("$tftppath");
copy("$rootimgdir/kernel", "$tftppath");
if ($statelite) {
@ -1689,6 +1690,7 @@ sub insert_dd () {
my @rpm_list;
my @driver_list;
my $Injectalldriver;
my $updatealldriver;
my @rpm_drivers;
@ -1734,6 +1736,9 @@ sub insert_dd () {
if (/^allupdate$/) {
$Injectalldriver = 1;
next;
} elsif (/^updateonly$/) {
$updatealldriver = 1;
next;
}
unless (/\.ko$/) {
s/$/.ko/;
@ -1744,7 +1749,7 @@ sub insert_dd () {
chomp(@dd_list);
chomp(@rpm_list);
unless (@dd_list || (@rpm_list && ($Injectalldriver || @driver_list))) {
unless (@dd_list || (@rpm_list && ($Injectalldriver || $updatealldriver || @driver_list))) {
return ();
}
@ -1757,7 +1762,7 @@ sub insert_dd () {
# Unzip the original initrd
# This only needs to be done for ppc or handling the driver rpm
# For the driver disk against x86, append the driver disk to initrd directly
if ($arch =~/ppc/ || (@rpm_list && ($Injectalldriver || @driver_list))) {
if ($arch =~/ppc/ || (@rpm_list && ($Injectalldriver || $updatealldriver || @driver_list))) {
if ($arch =~ /ppc/) {
$cmd = "gunzip --quiet -c $pkgdir/1/suseboot/initrd64 > $dd_dir/initrd";
} elsif ($arch =~ /x86/) {
@ -1782,7 +1787,7 @@ sub insert_dd () {
}
# Start to load the drivers from rpm packages
if (@rpm_list && ($Injectalldriver || @driver_list)) {
if (@rpm_list && ($Injectalldriver || $updatealldriver || @driver_list)) {
# Extract the files from rpm to the tmp dir
mkpath "$dd_dir/rpm";
my $new_kernel_ver;
@ -1802,19 +1807,19 @@ sub insert_dd () {
}
# get the new kernel if it exists in the update distro
my @new_kernels = <$dd_dir/rpm/boot/vmlinuz*>;
my @new_kernels = <$dd_dir/rpm/boot/vmlinu*>;
foreach my $new_kernel (@new_kernels) {
if (-r $new_kernel && $new_kernel =~ /\/vmlinuz-(.*(x86_64|ppc64))$/) {
$new_kernel_ver = $1;
$cmd = "/bin/mv -f $new_kernel $dd_dir/rpm/newkernel";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not move $new_kernel to $dd_dir/rpm/newkernel.";
xCAT::MsgUtils->message("I", $rsp, $callback);
if (-r $new_kernel && $new_kernel =~ /\/vmlinu[zx]-(.*(x86_64|ppc64|default))$/) {
$new_kernel_ver = $1;
$cmd = "/bin/mv -f $new_kernel $dd_dir/rpm/newkernel";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not move $new_kernel to $dd_dir/rpm/newkernel.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
}
}
# To skip the conflict of files that some rpm uses the xxx.ko.new as the name of the driver
# Change it back to xxx.ko here
@ -1851,14 +1856,45 @@ sub insert_dd () {
# if the new kernel from update distro is not existed in initrd, create the path for it
if (! -r "$dd_dir/initrd_img/lib/modules/$new_kernel_ver/") {
mkpath ("$dd_dir/initrd_img/lib/modules/$new_kernel_ver/");
# link the /modules to this new kernel dir
unlink "$dd_dir/initrd_img/modules";
$cmd = "/bin/ln -sf lib/modules/$new_kernel_ver/initrd $dd_dir/initrd_img/modules";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not create link to the new kernel dir.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
# get the name list for all drivers in the original initrd if 'netdrivers=updateonly'
# then only the drivers in this list will be updated from the drvier rpms
if ($updatealldriver) {
$driver_name = "\*\.ko";
@all_real_path = ();
find(\&get_all_path, <$dd_dir/initrd_img/lib/modules/*>);
foreach my $real_path (@all_real_path) {
my $driver = basename($real_path);
push @driver_list, $driver;
}
}
# Copy the drivers to the rootimage
# Figure out the kernel version
my @kernelpaths = <$dd_dir/initrd_img/lib/modules/*>;
my @kernelvers;
if ($new_kernel_ver) {
push @kernelvers, $new_kernel_ver;
}
foreach (@kernelpaths) {
push @kernelvers, basename($_);
my $kernelv = basename($_);
if ($kernelv =~ /^[\d\.]+/) {
if ($new_kernel_ver) {
rmtree ("$dd_dir/initrd_img/lib/modules/$kernelv");
} else {
push @kernelvers, $kernelv;
}
}
}
foreach my $kernelver (@kernelvers) {
@ -1871,7 +1907,6 @@ sub insert_dd () {
$driver_name = $driver;
@all_real_path = ();
find(\&get_all_path, <$dd_dir/rpm/lib/modules/$kernelver/*>);
#if ($real_path && $real_path =~ m!$dd_dir/rpm(/lib/modules/$kernelver/.*?)[^\/]*$!) {
# NOTE: for the initrd of sles that the drivers are put in the /lib/modules/$kernelver/initrd/
foreach my $real_path (@all_real_path) {
if ($real_path && $real_path =~ m!$dd_dir/rpm/lib/modules/$kernelver/!) {
@ -1895,8 +1930,7 @@ sub insert_dd () {
$driver_name = "\*\.ko";
@all_real_path = ();
find(\&get_all_path, <$dd_dir/rpm/lib/modules/$kernelver/*>);
foreach $real_path (@all_real_path) {
#if ($real_path && $real_path =~ m!$dd_dir/rpm(/lib/modules/$kernelver/.*?)[^\/]*$!) {
foreach my $real_path (@all_real_path) {
# NOTE: for the initrd of sles that the drivers are put in the /lib/modules/$kernelver/initrd/
if ($real_path && $real_path =~ m!$dd_dir/rpm/lib/modules/$kernelver/!) {
if (! -d "$dd_dir/initrd_img/lib/modules/$kernelver/initrd") {
@ -1928,34 +1962,32 @@ sub insert_dd () {
}
}
} # end of loading drivers from rpm packages
}
# Create the dir for driver update disk
mkpath("$dd_dir/initrd_img/cus_driverdisk");
# Create the dir for driver update disk
mkpath("$dd_dir/initrd_img/cus_driverdisk");
# insert the driver update disk into the cus_driverdisk dir
foreach my $dd (@dd_list) {
copy($dd, "$dd_dir/initrd_img/cus_driverdisk");
}
# insert the driver update disk into the cus_driverdisk dir
foreach my $dd (@dd_list) {
copy($dd, "$dd_dir/initrd_img/cus_driverdisk");
}
# Repack the initrd
# In order to avoid the runcmd add the '2>&1' at end of the cpio
# cmd, the echo cmd is added at the end
$cmd = "cd $dd_dir/initrd_img; find . -print | cpio -H newc -o > $dd_dir/initrd | echo";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not pack the hacked initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return ();
}
# Repack the initrd
# In order to avoid the runcmd add the '2>&1' at end of the cpio
# cmd, the echo cmd is added at the end
$cmd = "cd $dd_dir/initrd_img; find . -print | cpio -H newc -o > $dd_dir/initrd | echo";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not pack the hacked initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return ();
}
# zip the initrd
#move ("$dd_dir/initrd.new", "$dd_dir/initrd");
$cmd = "gzip -f $dd_dir/initrd";
xCAT::Utils->runcmd($cmd, -1);
# zip the initrd
#move ("$dd_dir/initrd.new", "$dd_dir/initrd");
$cmd = "gzip -f $dd_dir/initrd";
xCAT::Utils->runcmd($cmd, -1);
if ($arch =~/ppc/ || (@rpm_list && ($Injectalldriver || @driver_list))) {
if ($arch =~/ppc/) {
if (-r "$dd_dir/rpm/newkernel") {
# if there's new kernel from update distro, then use it
@ -1999,12 +2031,21 @@ sub insert_dd () {
my $rsp;
if (@dd_list) {
push @{$rsp->{data}}, "Inserted the driver update disk:".join(',', sort(@dd_list)).".";
push @{$rsp->{data}}, "The driver update disk:".join(',',@dd_list)." have been injected to initrd.";
}
if (@driver_list) {
push @{$rsp->{data}}, "Inserted the drivers:".join(',', sort(@rpm_drivers))." from driver packages.";
} elsif (@rpm_list && ($Injectalldriver || @driver_list)) {
push @{$rsp->{data}}, "Inserted the drivers from driver packages:".join(',', sort(@rpm_list)).".";
# remove the duplicated names
my %dnhash;
foreach (@rpm_drivers) {
$dnhash{$_} = 1;
}
@rpm_drivers = keys %dnhash;
if (@rpm_list) {
if (@rpm_drivers) {
push @{$rsp->{data}}, "The drivers:".join(',', sort(@rpm_drivers))." from ".join(',', sort(@rpm_list))." have been injected to initrd.";
} else {
push @{$rsp->{data}}, "No driver was injected to initrd.";
}
}
xCAT::MsgUtils->message("I", $rsp, $callback);