diff --git a/xCAT-client/pods/man1/geninitrd.1.pod b/xCAT-client/pods/man1/geninitrd.1.pod new file mode 100644 index 000000000..65de247df --- /dev/null +++ b/xCAT-client/pods/man1/geninitrd.1.pod @@ -0,0 +1,100 @@ +=head1 NAME + +B - Generate an initrd (initial ramfs) which to be used for statefull install or stateless netboot. + +=head1 SYNOPSIS + +B + +B [B<-h> | B<--help>] + + +=head1 DESCRIPTION + +Generate the initrd for the osimage: B which is an xCAT object of I type. + +B + +=over 2 + +If the B 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>. + +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 - 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 - comma separated driver rpm packages (full path should be specified) + +B - 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 + +=over 2 + +If the B 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 - 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 - comma separated driver rpm packages (full path should be specified) + +=back + + +=head1 Parameters + +I specifies the name of an os image definition to be used. The specification for the image is storted in the I table and I 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: + + geninitrd myimagename + +=back + + +=head1 FILES + +/opt/xcat/bin/geninitrd + +/opt/xcat/bin/genimage + +/opt/xcat/share/xcat/netboot//genimage + + +=head1 SEE ALSO + +L, L diff --git a/xCAT-client/pods/man8/nodeset.8.pod b/xCAT-client/pods/man8/nodeset.8.pod index 0c5584924..e0a2e6b74 100644 --- a/xCAT-client/pods/man8/nodeset.8.pod +++ b/xCAT-client/pods/man8/nodeset.8.pod @@ -6,6 +6,8 @@ B - set the boot state for a noderange B [I] [I|I|I|I|I|I|I|I|I>]] +B I [I> I<--noupdateinitrd>] + B [I<-h>|I<--help>|I<-v>|I<--version>] =head1 B @@ -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 table and I table. If the is omitted, the os image name will be obtained from I 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=> If you would like to run a task after deployment, you can define that task with this attribute. diff --git a/xCAT-server/lib/xcat/plugins/anaconda.pm b/xCAT-server/lib/xcat/plugins/anaconda.pm index e836eed19..3b637c0c2 100644 --- a/xCAT-server/lib/xcat/plugins/anaconda.pm +++ b/xCAT-server/lib/xcat/plugins/anaconda.pm @@ -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/ # 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; diff --git a/xCAT-server/lib/xcat/plugins/genimage.pm b/xCAT-server/lib/xcat/plugins/genimage.pm index 6284a16eb..9108dec90 100644 --- a/xCAT-server/lib/xcat/plugins/genimage.pm +++ b/xCAT-server/lib/xcat/plugins/genimage.pm @@ -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); diff --git a/xCAT-server/lib/xcat/plugins/geninitrd.pm b/xCAT-server/lib/xcat/plugins/geninitrd.pm index ec13e052a..18782cb99 100644 --- a/xCAT-server/lib/xcat/plugins/geninitrd.pm +++ b/xCAT-server/lib/xcat/plugins/geninitrd.pm @@ -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 [-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"; diff --git a/xCAT-server/lib/xcat/plugins/sles.pm b/xCAT-server/lib/xcat/plugins/sles.pm index 75d31229b..febea7b88 100644 --- a/xCAT-server/lib/xcat/plugins/sles.pm +++ b/xCAT-server/lib/xcat/plugins/sles.pm @@ -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);