code drop for the support that loading drivers from driver rpm. The change has affected the code logic for driver disk support.

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@13246 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
daniceexi 2012-07-05 14:59:08 +00:00
parent 46531485db
commit 161cdeb4ec
6 changed files with 1070 additions and 422 deletions

View File

@ -624,7 +624,7 @@ osimage => {
},
},
linuximage => {
cols => [qw(imagename template pkglist pkgdir otherpkglist otherpkgdir exlist postinstall rootimgdir kerneldir nodebootif otherifce netdrivers kernelver krpmver permission dump crashkernelsize partitionfile comments disable)],
cols => [qw(imagename template pkglist pkgdir otherpkglist otherpkgdir exlist postinstall rootimgdir kerneldir nodebootif otherifce netdrivers kernelver krpmver permission dump crashkernelsize partitionfile driverupdatesrc comments disable)],
keys => [qw(imagename)],
table_desc => 'Information about a Linux operating system image that can be used to deploy cluster nodes.',
descriptions => {
@ -647,6 +647,7 @@ linuximage => {
dump => qq{The NFS directory to hold the Linux kernel dump file (vmcore) when the node with this image crashes, its format is "nfs://<nfs_server_ip>/<kdump_path>". If you want to use the node's "xcatmaster" (its SN or MN), <nfs_server_ip> can be left blank. For example, "nfs:///<kdump_path>" means the NFS directory to hold the kernel dump file is on the node's SN, or MN if there's no SN.},
crashkernelsize => 'the size that assigned to the kdump kernel. If the kernel size is not set, 256M will be the default value.',
partitionfile => 'There are 2 format about this attribute. One is "<partition file absolute path>", the content of the partition file must use the corresponding format with the OS type. The other one is "s:<partition file absolute path>", the content of the partition file should be a shell script which must write the partition difinition into /tmp/partitionfile. This attribute only works for diskful install.',
driverupdatesrc => 'The source of the drivers which need to be loaded during the boot. Two types of driver update source are supported: Driver update disk and Driver rpm package. The value for this attribute should be comma separated sources. Each source should be the format tab:full_path_of_srouce_file. The tab keyword can be: dud (for Driver update disk) and rpm (for driver rpm). If missing the tab, the rpm format is the default. e.g. dud:/install/dud/dd.img,rpm:/install/rpm/d.rpm',
comments => 'Any user-written notes.',
disable => "Set to 'yes' or '1' to comment out this row.",
},
@ -2104,6 +2105,11 @@ push(@{$defspec{node}->{'attrs'}}, @nodeattrs);
tabentry => 'linuximage.partitionfile',
access_tabentry => 'linuximage.imagename=attr:imagename',
},
{attr_name => 'driverupdatesrc',
only_if => 'imagetype=linux',
tabentry => 'linuximage.driverupdatesrc',
access_tabentry => 'linuximage.imagename=attr:imagename',
},
####################
# nimimage table#
####################

View File

@ -21,6 +21,8 @@ Getopt::Long::Configure("pass_through");
use File::Path;
use File::Copy;
use File::Temp qw/mkdtemp/;
use File::Find;
use File::Basename;
use Socket;
@ -839,6 +841,8 @@ sub mkinstall
my $platform;
my $xcatmaster;
my $partfile;
my $netdrivers;
my $driverupdatesrc;
my $ient = $rents{$node}->[0];
if ($ient and $ient->{xcatmaster})
@ -885,6 +889,12 @@ sub mkinstall
if ($ref1->{'partitionfile'}) {
$img_hash{$imagename}->{partitionfile} = $ref1->{'partitionfile'};
}
if ($ref1->{'driverupdatesrc'}) {
$img_hash{$imagename}->{driverupdatesrc}=$ref1->{'driverupdatesrc'};
}
if ($ref1->{'netdrivers'}) {
$img_hash{$imagename}->{netdrivers}=$ref1->{'netdrivers'};
}
}
# if the install template wasn't found, then lets look for it in the default locations.
unless($img_hash{$imagename}->{template}){
@ -932,6 +942,9 @@ sub mkinstall
$pkgdir="$installroot/$os/$arch";
}
$pkglistfile=$ph->{pkglist};
$netdrivers = $ph->{netdrivers};
$driverupdatesrc = $ph->{driverupdatesrc};
}
else {
$os = $ent->{os};
@ -1108,9 +1121,16 @@ sub mkinstall
if($esxi){
copyesxiboot($pkgdir, "$tftpdir/xcat/$os/$arch");
}else{
copy($kernpath,"$tftpdir/xcat/$os/$arch");
copy($initrdpath,"$tftpdir/xcat/$os/$arch/initrd.img");
&insert_dd($callback, $os, $arch, "$tftpdir/xcat/$os/$arch/initrd.img");
my $tftppath;
if ($profile) {
$tftppath = "/$tftpdir/xcat/$os/$arch/$profile";
} else {
$tftppath = "/$tftpdir/xcat/$os/$arch";
}
mkpath ("$tftppath");
copy($kernpath,"$tftppath");
copy($initrdpath,"$tftppath/initrd.img");
&insert_dd($callback, $os, $arch, "$tftppath/initrd.img", $driverupdatesrc, $netdrivers);
}
$doneimgs{"$os|$arch"} = 1;
}
@ -1228,8 +1248,13 @@ sub mkinstall
$kcmdline .= " --- xcat/$os/$arch/$_";
}
}else{
$k = "xcat/$os/$arch/vmlinuz";
$i = "xcat/$os/$arch/initrd.img";
if ($profile) {
$k = "xcat/$os/$arch/$profile/vmlinuz";
$i = "xcat/$os/$arch/$profile/initrd.img";
} else {
$k = "xcat/$os/$arch/vmlinuz";
$i = "xcat/$os/$arch/initrd.img";
}
}
$bptab->setNodeAttribs(
@ -1576,31 +1601,530 @@ sub copyesxiboot {
}
}
# Get the driver update disk from /install/driverdisk/<os>/<arch>
# Take out the drivers from driver update disk and insert them
# into the initrd
# callback subroutine for 'find' command to return the path
my $driver_name;
my $real_path;
sub get_path ()
{
if ($File::Find::name =~ /\/$driver_name/) {
$real_path = $File::Find::name;
}
}
# callback subroutine for 'find' command to return the path for all the matches
my @all_real_path;
sub get_all_path ()
{
if ($File::Find::name =~ /\/$driver_name/) {
push @all_real_path, $File::Find::name;
}
}
# Get the driver disk or driver rpm from the osimage.driverupdatesrc
# The valid value: dud:/install/dud/dd.img,rpm:/install/rpm/d.rpm, if missing the tag: 'dud'/'rpm'
# the 'rpm' is default.
#
# If cannot find the driver disk from osimage.driverupdatesrc, will try to search driver disk
# from /install/driverdisk/<os>/<arch>
#
# For driver rpm, the driver list will be gotten from osimage.netdrivers. If not set, copy all the drivers from driver
# rpm to the initrd.
#
sub insert_dd {
my $callback = shift;
my $os = shift;
my $arch = shift;
my $img = shift;
my $driverupdatesrc = shift;
my $drivers = shift;
my $install_dir = xCAT::Utils->getInstallDir();
# Find out the dirver disk which need to be inserted into initrd
if (! -d "$install_dir/driverdisk/$os/$arch") {
return ();
my $cmd;
my @inserted_dd = ();
my @dd_drivers = ();
my @dd_list;
my @rpm_list;
my @driver_list;
my @rpm_drivers;
# Parse the parameters to the the source of Driver update disk and Driver rpm, and driver list as well
if ($driverupdatesrc) {
my @srcs = split(',', $driverupdatesrc);
foreach my $src (@srcs) {
if ($src =~ /dud:(.*)/i) {
push @dd_list, $1;
} elsif ($src =~ /rpm:(.*)/i) {
push @rpm_list, $1;
} else {
push @rpm_list, $src;
}
}
}
if (! @dd_list) {
# get Driver update disk from the default path if not specified in osimage
# check the Driver Update Disk images, it can be .img or .iso
if (-d "$install_dir/driverdisk/$os/$arch") {
$cmd = "find $install_dir/driverdisk/$os/$arch -type f";
@dd_list = xCAT::Utils->runcmd($cmd, -1);
}
}
my $cmd = "find $install_dir/driverdisk/$os/$arch -type f";
my @dd_list = xCAT::Utils->runcmd($cmd, -1);
chomp(@dd_list);
if (!@dd_list) {
return ();
foreach (split /,/,$drivers) {
unless (/\.ko$/) {
s/$/.ko/;
}
push @driver_list, $_;
}
chomp(@dd_list);
chomp(@rpm_list);
unless (@dd_list || @rpm_list ) {
return undef;
}
# Create the tmp dir for dd hack
my $dd_dir = mkdtemp("/tmp/ddtmpXXXXXXX");
if (<$install_dir/$os/$arch/Packages/dracut*>) { #new style, skip the fanagling, copy over the dds and append them...
# regenerate the original initrd for non dracut or need to add the drivers from rpm packages
# dracut + drvier rpm
# !dracut + driver rpm
# !dracut + driver disk
if (!<$install_dir/$os/$arch/Packages/dracut*> || @rpm_list) {
mkpath "$dd_dir/initrd_img"; # The dir for the new initrd
# unzip the initrd image
$cmd = "gunzip -c $img > $dd_dir/initrd";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not gunzip the initial initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return undef;
}
# Extract the files from original initrd
$cmd = "cd $dd_dir/initrd_img; cpio -id --quiet < ../initrd";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not extract files from the initial initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return undef;
}
if (@rpm_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";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not extract files from the rpm $rpm.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
} else {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not read the rpm $rpm.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
}
# The rh6 has different initrd format with old version (rh 5.x)
# The new format of initrd is made by dracut, it has the /lib/modules/<kernel>
# directory like the root image
# If the os has dracut rpm packet, then copy the drivers to the /lib/modules/<kernel>
# and recreate the dependency by the depmod command
if (<$install_dir/$os/$arch/Packages/dracut*>) { #rh6, fedora13 ...
# 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) {
# Copy the firmware to the rootimage
if (-d "$dd_dir/rpm/lib/firmware") {
if (! -d "$dd_dir/initrd_img/lib") {
mkpath "$dd_dir/initrd_img/lib";
}
$cmd = "cp -rf $dd_dir/rpm/lib/firmware $dd_dir/initrd_img/lib";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not copy firmware to the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
# Copy the drivers to the initrd
# Figure out the kernel version
my @kernelpaths = <$dd_dir/initrd_img/lib/modules/*>;
my @kernelvers;
foreach (@kernelpaths) {
if (basename($_) =~ /^[\d\.]+/) {
push @kernelvers, basename($_);
}
}
foreach my $kernelver (@kernelvers) {
if (@driver_list) {
foreach my $driver (@driver_list) {
$driver_name = $driver;
$real_path = "";
find(\&get_path, <$dd_dir/rpm/lib/modules/$kernelver/*>);
if ($real_path && $real_path =~ m!$dd_dir/rpm(/lib/modules/$kernelver/.*?)[^\/]*$!) {
if (! -d "$dd_dir/initrd_img$1") {
mkpath "$dd_dir/initrd_img$1";
}
$cmd = "cp -rf $real_path $dd_dir/initrd_img$1";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not copy driver $driver to the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
} else {
push @rpm_drivers, $driver;
}
}
}
} else {
# copy all the drviers to the rootimage
if (-d "$dd_dir/rpm/lib/modules/$kernelver") {
$cmd = "cp -rf $dd_dir/rpm/lib/modules/$kernelver $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 /lib/modules/$kernelver to the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
} else {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not find /lib/modules/$kernelver from the driver rpms.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
# regenerate the modules dependency
foreach my $kernelver (@kernelvers) {
$cmd = "depmod -b $dd_dir/initrd_img $kernelver";
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);
}
}
}
}
} else {# non dracut mode, for rh5, fedora12 ...
# For non-dracut mode, the drviers need to be merged into the initrd with the specific format
# Create directory for the driver modules hack
mkpath "$dd_dir/modules";
# Extract files from the modules.cgz of initrd
$cmd = "cd $dd_dir/modules; gunzip -c $dd_dir/initrd_img/modules/modules.cgz | cpio -id";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not gunzip modules.cgz from the initial initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return undef;
}
my @modinfo = ();
foreach my $dd (@dd_list) {
mkpath "$dd_dir/mnt";
mkpath "$dd_dir/dd_modules";
$cmd = "mount -o loop $dd $dd_dir/mnt";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not mount the driver update disk.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return undef;
}
$cmd = "cd $dd_dir/dd_modules; gunzip -c $dd_dir/mnt/modules.cgz | cpio -id";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not gunzip the modules.cgz from the driver update disk.";
xCAT::MsgUtils->message("E", $rsp, $callback);
system("umount -f $dd_dir/mnt");
return undef;
}
# Copy all the driver files out
$cmd = "cp -rf $dd_dir/dd_modules/* $dd_dir/modules";
xCAT::Utils->runcmd($cmd, -1);
# Copy the firmware into the initrd
mkpath "$dd_dir/initrd_img/firmware";
$cmd = "cp -rf $dd_dir/dd_modules/firmware/* $dd_dir/initrd_img/firmware";
xCAT::Utils->runcmd($cmd, -1);
my $drivername;
# Get the entries from modinfo
open (DDMODINFO, "<", "$dd_dir/mnt/modinfo");
while (<DDMODINFO>) {
if ($_ =~ /^Version/) { next; }
if ($_ =~ /^(\S+)/) {
push @dd_drivers, $1;
$drivername=$1;
}
push @modinfo, $_;
}
close (DDMODINFO);
# Append the modules.alias
if (-r "$dd_dir/mnt/modules.alias") {
$cmd = "cat $dd_dir/mnt/modules.alias >> $dd_dir/initrd_img/modules/modules.alias";
xCAT::Utils->runcmd($cmd, -1);
}
# Append the modules.dep
my $depfile;
my $target;
open($target,">>","$dd_dir/initrd_img/modules/modules.dep");
open($depfile,"<","$dd_dir/mnt/modules.dep");
my $curline;
while ($curline=<$depfile>) {
if ($curline !~ /:/) { #missing the rather important first half of the equation here....
$curline = $drivername.": ".$curline;
}
print $target $curline;
}
close($target);
close($depfile);
# Append the pcitable
if (-r "$dd_dir/mnt/pcitable") {
$cmd = "cat $dd_dir/mnt/pcitable >> $dd_dir/initrd_img/modules/pcitable";
xCAT::Utils->runcmd($cmd, -1);
}
if (-r "$dd_dir/mnt/modules.pcimap") {
$cmd = "cat $dd_dir/mnt/modules.pcimap >> $dd_dir/initrd_img/modules/modules.pcimap";
xCAT::Utils->runcmd($cmd, -1);
}
$cmd = "umount -f $dd_dir/mnt";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not unmount the driver update disk.";
xCAT::MsgUtils->message("E", $rsp, $callback);
system("umount -f $dd_dir/mnt");
return undef;
}
# Clean the env
rmtree "$dd_dir/mnt";
rmtree "$dd_dir/dd_modules";
push @inserted_dd, $dd;
}
# Merge the drviers from rpm packages to the initrd
if (@rpm_list) {
# Copy the firmware to the rootimage
if (-d "$dd_dir/rpm/lib/firmware") {
if (! -d "$dd_dir/initrd_img/lib") {
mkpath "$dd_dir/initrd_img/lib";
}
$cmd = "cp -rf $dd_dir/rpm/lib/firmware $dd_dir/initrd_img";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not copy firmware to the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
# Copy the drivers to the initrd
# Figure out the kernel version
my @kernelpaths = <$dd_dir/modules/*>;
my @kernelvers;
foreach (@kernelpaths) {
push @kernelvers, basename($_);
}
foreach my $kernelver (@kernelvers) {
# find the $kernelver/$arch dir in the $dd_dir/modules
my $arch4modules;
foreach (<$dd_dir/modules/$kernelver/*>) {
if (basename($_) =~ $arch) {
$arch4modules = basename($_);
}
}
if (!$arch4modules) {
$arch4modules = basename(<$dd_dir/modules/$kernelver/*>);
}
if (! -d "$dd_dir/modules/$kernelver/$arch4modules/") {
next;
}
if (@driver_list) {
# copy all the specific drviers to the initrd
foreach my $driver (@driver_list) {
$driver_name = $driver;
$real_path = "";
find(\&get_path, <$dd_dir/rpm/lib/modules/$kernelver/*>);
if ($real_path ) {
$cmd = "cp -rf $real_path $dd_dir/modules/$kernelver/$arch4modules/";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not copy driver $driver to the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
} else {
push @rpm_drivers, $driver;
}
}
}
} else {
# copy all the drviers to the initrd
if (-d "$dd_dir/rpm/lib/modules/$kernelver") {
find(\&get_all_path, <$dd_dir/rpm/lib/modules/$kernelver/*>);
foreach my $driverpath (@all_real_path) {
$cmd = "cp -rf $driverpath $dd_dir/modules/$kernelver/$arch4modules/";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not copy $driverpath to the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
if ($driverpath =~ s/([^\/]*)\.ko//) {
push @rpm_drivers, $1;
}
}
} else {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not find /lib/modules/$kernelver from the driver rpms.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
# Append the modules.dep to the one in the initrd
if (-f "$dd_dir/rpm/lib/modules/$kernelver/modules.dep") {
$cmd = "cat $dd_dir/rpm/lib/modules/$kernelver/modules.dep >> $dd_dir/initrd_img/modules/modules.dep";
xCAT::Utils->runcmd($cmd, -1);
}
}
}
# Regenerate the modules.dep
# 'depmod' command only can handle the drivers in /lib/modules/kernelver strcuture, so copy the drivers to a temporary
# dirctory $dd_dir/depmod/lib/modules/$mk, run 'depmod' and copy the modules.dep to the correct dir
my ($mk, $ma);
$mk = <$dd_dir/modules/*>;
if (-d $mk) {
$mk = basename($mk);
$ma = <$dd_dir/modules/$mk/*>;
if (-d $ma) {
mkpath "$dd_dir/depmod/lib/modules/$mk";
xCAT::Utils->runcmd("cp -rf $ma/* $dd_dir/depmod/lib/modules/$mk", -1);
$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);
}
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");
}
# remove the path and postfix of the driver modules from the new generated modules.dep since original format has not path and postfix
my @newdep;
if (open (DEP, "<$dd_dir/initrd_img/modules/modules.dep")) {
while (<DEP>) {
s/\/lib\/modules\/$mk\/([^\.]+)\.ko/$1/g;
if (/:\s*\S+/) {
push @newdep, $_;
}
}
close (DEP);
}
if (open (NEWDEP, ">$dd_dir/initrd_img/modules/modules.dep")) {
print NEWDEP @newdep;
close (NEWDEP);
}
}
}
# Append the modinfo into the module-info
open (MODINFO, "<", "$dd_dir/initrd_img/modules/module-info");
open (MODINFONEW, ">", "$dd_dir/initrd_img/modules/module-info.new");
my $removeflag = 0;
my @orig_drivers;
while (<MODINFO>) {
my $line = $_;
if ($line =~ /^(\S+)/) {
if (grep /$1/, @dd_drivers) {
$removeflag = 1;
next;
} else {
push @orig_drivers, $1;
$removeflag = 0;
}
}
if ($removeflag == 1) { next; }
print MODINFONEW $line;
}
print MODINFONEW @modinfo;
# add the drivers from rpm
foreach my $dr (@rpm_drivers) {
$dr =~ s/\.ko//;
if (! grep /^$dr$/, (@orig_drivers,@dd_drivers)) {
print MODINFONEW $dr."\n";
}
}
close (MODINFONEW);
close (MODINFO);
move ("$dd_dir/initrd_img/modules/module-info.new", "$dd_dir/initrd_img/modules/module-info");
# Repack the modules
$cmd = "cd $dd_dir/modules; find . -print | cpio -o -H crc | gzip -9 > $dd_dir/initrd_img/modules/modules.cgz";
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 modules.cgz.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return undef;
}
} # End of non dracut
# Repack the initrd
$cmd = "cd $dd_dir/initrd_img; find .|cpio -H newc -o|gzip -9 -c - > $dd_dir/initrd.img";
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 undef;
}
copy ("$dd_dir/initrd.img", $img);
}
# dracut + driver disk, just append the driver disk to the initrd
if (<$install_dir/$os/$arch/Packages/dracut*> && @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");
@ -1627,323 +2151,39 @@ sub insert_dd {
} else { #there should be no else...
die "This should never occur";
}
chdir($dd_dir."/dd");
$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";
}
my $ddhdl;
my $inithdl;
open($inithdl,">>",$img);
open($ddhdl,"<","../dd.gz");
binmode($ddhdl);
binmode($inithdl);
{
local $/ = \32768;
while (my $block = <$ddhdl>) { print $inithdl $block; }
}
chdir("/");
xCAT::Utils->runcmd("rm -rf $dd_dir");
my $rsp;
push @{$rsp->{data}}, "Inserted the driver update disk:".join(',',@dd_list).".";
xCAT::MsgUtils->message("I", $rsp, $callback);
return @dd_list;
return;
chdir($dd_dir."/dd");
$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";
}
my $ddhdl;
my $inithdl;
open($inithdl,">>",$img);
open($ddhdl,"<","../dd.gz");
binmode($ddhdl);
binmode($inithdl);
{
local $/ = \32768;
while (my $block = <$ddhdl>) { print $inithdl $block; }
}
chdir("/");
push @inserted_dd, @dd_list;
}
mkpath "$dd_dir/initrd_img"; # The dir for the new initrd
# unzip the initrd image
$cmd = "gunzip -c $img > $dd_dir/initrd";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not gunzip the initial initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return undef;
}
# Extract the files from original initrd
$cmd = "cd $dd_dir/initrd_img; cpio -id --quiet < ../initrd";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not extract files from the initial initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return undef;
}
# Create directory for the driver modules hack
mkpath "$dd_dir/modules";
my @inserted_dd = ();
my @dd_drivers = ();
# The rh6 has different initrd format with old version (rh 5.x)
# The new format of initrd is made by dracut, it has the /lib/modules/<kernel>
# directory like the root image
# If the os has dracut rpm packet, then copy the drivers to the /lib/modules/<kernel>
# and recreate the dependency by the depmod command
$cmd = "find $install_dir/$os/$arch/ | grep dracut";
my @dracut = xCAT::Utils->runcmd($cmd, -1);
if (grep (/dracut-.*\.rpm/, @dracut)) {#dracut mode, for rh6, fedora13 ...
#copy the firmware into the initrd
if (-d "$dd_dir/mnt/firmware") {
$cmd = "cp -rf $dd_dir/mnt/firmware/* $dd_dir/initrd_img/lib/firmware";
xCAT::Utils->runcmd($cmd, -1);
}
# Figure out the kernel version of the initrd
my $kernelver;
opendir (KERNEL, "$dd_dir/initrd_img/lib/modules");
while ($kernelver = readdir(KERNEL)) {
if ($kernelver =~ /^\./ || $kernelver !~ /^\d/) {
$kernelver = "";
next;
}
if (-d "$dd_dir/initrd_img/lib/modules/$kernelver") {
last;
}
$kernelver = "";
}
# The initrd has problem
if ($kernelver eq "") {
return ();
}
# Copy the drivers to the lib/modules/<$kernelver>/
if (! -d "$dd_dir/initrd_img/lib/modules/$kernelver/kernel/drivers/driverdisk") {
mkpath "$dd_dir/initrd_img/lib/modules/$kernelver/kernel/drivers/driverdisk";
}
foreach my $dd (@dd_list) {
mkpath "$dd_dir/mnt";
mkpath "$dd_dir/dd_modules";
$cmd = "mount -o loop $dd $dd_dir/mnt";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not mount the driver update disk.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return undef;
}
$cmd = "cd $dd_dir/dd_modules; gunzip -c $dd_dir/mnt/modules.cgz | cpio -id";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not gunzip the modules.cgz from the driver update disk.";
xCAT::MsgUtils->message("E", $rsp, $callback);
system("umount -f $dd_dir/mnt");
return undef;
}
# Get all the drivers which belong to $kernelver/$arch
$cmd = "find $dd_dir/dd_modules/$kernelver/$arch/ -type f";
my @drivers = xCAT::Utils->runcmd($cmd, -1);
foreach my $d (@drivers) {
chomp($d);
# The drivers in the initrd is in zip format
$cmd = "gzip $d";
xCAT::Utils->runcmd($cmd, -1);
$d .= ".gz";
my $driver_name = $d;
$driver_name =~ s/.*\///;
# If the driver file existed, then over write
$cmd = "find $dd_dir/initrd_img/lib/modules/$kernelver -type f -name $driver_name";
my @exist_file = xCAT::Utils->runcmd($cmd, -1);
if (! @exist_file) {
$cmd = "cp $d $dd_dir/initrd_img/lib/modules/$kernelver/kernel/drivers/driverdisk";
} else {
$cmd = "cp $d $exist_file[0]";
}
xCAT::Utils->runcmd($cmd, -1);
}
$cmd = "umount -f $dd_dir/mnt";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not unmount the driver update disk.";
xCAT::MsgUtils->message("E", $rsp, $callback);
system("umount -f $dd_dir/mnt");
return undef;
}
# Clean the env
rmtree "$dd_dir/mnt";
rmtree "$dd_dir/dd_modules";
push @inserted_dd, $dd;
}
# Generate the dependency relationship
$cmd = "chroot $dd_dir/initrd_img/ depmod $kernelver";
xCAT::Utils->runcmd($cmd, -1);
} else {
# Extract files from the modules.cgz of initrd
$cmd = "cd $dd_dir/modules; gunzip -c $dd_dir/initrd_img/modules/modules.cgz | cpio -id";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not gunzip modules.cgz from the initial initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return undef;
}
my @modinfo = ();
foreach my $dd (@dd_list) {
mkpath "$dd_dir/mnt";
mkpath "$dd_dir/dd_modules";
$cmd = "mount -o loop $dd $dd_dir/mnt";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not mount the driver update disk.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return undef;
}
$cmd = "cd $dd_dir/dd_modules; gunzip -c $dd_dir/mnt/modules.cgz | cpio -id";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not gunzip the modules.cgz from the driver update disk.";
xCAT::MsgUtils->message("E", $rsp, $callback);
system("umount -f $dd_dir/mnt");
return undef;
}
# Copy all the driver files out
$cmd = "cp -rf $dd_dir/dd_modules/* $dd_dir/modules";
xCAT::Utils->runcmd($cmd, -1);
# Copy the firmware into the initrd
mkpath "$dd_dir/initrd_img/firmware";
$cmd = "cp -rf $dd_dir/dd_modules/firmware/* $dd_dir/initrd_img/firmware";
xCAT::Utils->runcmd($cmd, -1);
# Get the entries from modinfo
my $drivername;
open (DDMODINFO, "<", "$dd_dir/mnt/modinfo");
while (<DDMODINFO>) {
if ($_ =~ /^Version/) { next; }
if ($_ =~ /^(\S+)/) {
push @dd_drivers, $1;
$drivername=$1;
}
push @modinfo, $_;
}
close (DDMODINFO);
# Append the modules.alias
$cmd = "cat $dd_dir/mnt/modules.alias >> $dd_dir/initrd_img/modules/modules.alias";
xCAT::Utils->runcmd($cmd, -1);
# Append the modules.dep
my $depfile;
my $target;
open($target,">>","$dd_dir/initrd_img/modules/modules.dep");
open($depfile,"<","$dd_dir/mnt/modules.dep");
my $curline;
while ($curline=<$depfile>) {
if ($curline !~ /:/) { #missing the rather important first half of the equation here....
$curline = $drivername.": ".$curline;
}
print $target $curline;
}
close($target);
close($depfile);
# Append the pcitable
if (-r "$dd_dir/mnt/pcitable") {
$cmd = "cat $dd_dir/mnt/pcitable >> $dd_dir/initrd_img/modules/pcitable";
xCAT::Utils->runcmd($cmd, -1);
}
if (-r "$dd_dir/mnt/modules.pcimap") {
$cmd = "cat $dd_dir/mnt/modules.pcimap >> $dd_dir/initrd_img/modules/modules.pcimap";
xCAT::Utils->runcmd($cmd, -1);
}
$cmd = "umount -f $dd_dir/mnt";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not unmount the driver update disk.";
xCAT::MsgUtils->message("E", $rsp, $callback);
system("umount -f $dd_dir/mnt");
return undef;
}
# Clean the env
rmtree "$dd_dir/mnt";
rmtree "$dd_dir/dd_modules";
push @inserted_dd, $dd;
}
# Append the modinfo into the module-info
open (MODINFO, "<", "$dd_dir/initrd_img/modules/module-info");
open (MODINFONEW, ">", "$dd_dir/initrd_img/modules/module-info.new");
my $removeflag = 0;
while (<MODINFO>) {
my $line = $_;
if ($line =~ /^(\S+)/) {
if (grep /$1/, @dd_drivers) {
$removeflag = 1;
next;
} else {
$removeflag = 0;
}
}
if ($removeflag == 1) { next; }
print MODINFONEW $line;
}
print MODINFONEW @modinfo;
close (MODINFONEW);
close (MODINFO);
move ("$dd_dir/initrd_img/modules/module-info.new", "$dd_dir/initrd_img/modules/module-info");
# Repack the modules
$cmd = "cd $dd_dir/modules; find . -print | cpio -o -H crc | gzip -9 > $dd_dir/initrd_img/modules/modules.cgz";
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 modules.cgz.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return undef;
}
} # End of non dracut
# Repack the initrd
$cmd = "cd $dd_dir/initrd_img; find .|cpio -H newc -o|gzip -9 -c - > $dd_dir/initrd.img";
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 undef;
}
copy ("$dd_dir/initrd.img", $img);
# clean the env
rmtree $dd_dir;
my $rsp;
push @{$rsp->{data}}, "Inserted the driver update disk:".join(',',@inserted_dd).".";
if (@dd_list) {
push @{$rsp->{data}}, "Inserted the driver update disk:".join(',',@inserted_dd).".";
}
if (@driver_list) {
push @{$rsp->{data}}, "Inserted the drivers:".join(',', sort(@rpm_drivers))." from driver packages.";
} elsif (@rpm_list) {
push @{$rsp->{data}}, "Inserted the drivers from driver packages:".join(',', sort(@rpm_list)).".";
}
xCAT::MsgUtils->message("I", $rsp, $callback);
return @inserted_dd;

View File

@ -132,7 +132,7 @@ sub process_request {
return 1;
}
(my $ref_linuximage_tab) = $linuximagetab->getAttribs({imagename => $imagename}, 'pkglist', 'pkgdir', 'otherpkglist', 'otherpkgdir', 'postinstall', 'rootimgdir', 'kerneldir', 'krpmver', 'nodebootif', 'otherifce', 'kernelver', 'netdrivers', 'permission');
(my $ref_linuximage_tab) = $linuximagetab->getAttribs({imagename => $imagename}, 'pkglist', 'pkgdir', 'otherpkglist', 'otherpkgdir', 'postinstall', 'rootimgdir', 'kerneldir', 'krpmver', 'nodebootif', 'otherifce', 'kernelver', 'netdrivers', 'permission','driverupdatesrc');
unless ($ref_linuximage_tab) {
$callback->({error=>["Cannot find $imagename from the linuximage table."],errorcode=>[1]});
return 1;
@ -164,6 +164,7 @@ sub process_request {
$otherpkglist = $ref_linuximage_tab->{'otherpkglist'};
$postinstall_filename = $ref_linuximage_tab->{'postinstall'};
$destdir = $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?
# currently, one message is output to indicate the users there will be some updates
@ -294,6 +295,7 @@ sub process_request {
if ($postinstall_filename) { $cmd .= " --postinstall $postinstall_filename"; }
if ($destdir) { $cmd .= " --rootimgdir $destdir"; }
if ($tempfile) { $cmd .= " --tempfile $tempfile"; }
if ($driverupdatesrc) { $cmd .= " --driverupdatesrc $driverupdatesrc"; }
if ($imagename) {
$cmd.= " $imagename";

View File

@ -22,6 +22,8 @@ use File::Copy;
use File::Temp qw/mkdtemp/;
my $httpmethod = "http";
my $httpport = "80";
use File::Find;
use File::Basename;
use Socket;
@ -646,6 +648,8 @@ sub mkinstall
my $plat = "";
my $tftpdir;
my $partfile;
my $netdrivers;
my $driverupdatesrc;
if ($resents->{$node} and $resents->{$node}->[0]->{tftpdir}) {
$tftpdir = $resents->{$node}->[0]->{tftpdir};
} else {
@ -668,7 +672,7 @@ sub mkinstall
if (!$linuximagetab) {
$linuximagetab=xCAT::Table->new('linuximage', -create=>1);
}
(my $ref1) = $linuximagetab->getAttribs({imagename => $imagename}, 'template', 'pkgdir', 'pkglist');
(my $ref1) = $linuximagetab->getAttribs({imagename => $imagename}, 'template', 'pkgdir', 'pkglist', 'driverupdatesrc', 'netdrivers');
if ($ref1) {
if ($ref1->{'template'}) {
$img_hash{$imagename}->{template}=$ref1->{'template'};
@ -682,6 +686,12 @@ sub mkinstall
if ($ref1->{'partitionfile'}) {
$img_hash{$imagename}->{partitionfile}=$ref1->{'partitionfile'};
}
if ($ref1->{'driverupdatesrc'}) {
$img_hash{$imagename}->{driverupdatesrc}=$ref1->{'driverupdatesrc'};
}
if ($ref1->{'netdrivers'}) {
$img_hash{$imagename}->{netdrivers}=$ref1->{'netdrivers'};
}
}
} else {
$callback->(
@ -702,6 +712,8 @@ sub mkinstall
}
$pkglistfile=$ph->{pkglist};
$partfile=$ph->{partitionfile};
$netdrivers = $ph->{netdrivers};
$driverupdatesrc = $ph->{driverupdatesrc};
}
else {
$os = $ent->{os};
@ -827,26 +839,27 @@ sub mkinstall
#TODO: driver slipstream, targetted for network.
unless ($doneimgs{"$os|$arch|$tftpdir"})
{
mkpath("/$tftpdir/xcat/$os/$arch");
my $tftppath;
if ($profile) {
$tftppath = "/$tftpdir/xcat/$os/$arch/$profile";
} else {
$tftppath = "/$tftpdir/xcat/$os/$arch";
}
mkpath("$tftppath");
if ($arch =~ /x86_64/)
{
copy("$pkgdir/1/boot/$arch/loader/linux",
"/$tftpdir/xcat/$os/$arch/");
copy("$pkgdir/1/boot/$arch/loader/initrd",
"/$tftpdir/xcat/$os/$arch/");
@dd_drivers = &insert_dd($callback, $os, $arch, "/$tftpdir/xcat/$os/$arch/initrd");
copy("$pkgdir/1/boot/$arch/loader/linux", "$tftppath");
copy("$pkgdir/1/boot/$arch/loader/initrd", "$tftppath");
@dd_drivers = &insert_dd($callback, $os, $arch, "$tftppath/initrd", $driverupdatesrc, $netdrivers);
} elsif ($arch =~ /x86/) {
copy("$pkgdir/1/boot/i386/loader/linux",
"/$tftpdir/xcat/$os/$arch/");
copy("$pkgdir/1/boot/i386/loader/initrd",
"/$tftpdir/xcat/$os/$arch/");
@dd_drivers = &insert_dd($callback, $os, $arch, "/$tftpdir/xcat/$os/$arch/initrd");
copy("$pkgdir/1/boot/i386/loader/linux", "$tftppath");
copy("$pkgdir/1/boot/i386/loader/initrd", "$tftppath");
@dd_drivers = &insert_dd($callback, $os, $arch, "$tftppath/initrd", $driverupdatesrc, $netdrivers);
}
elsif ($arch =~ /ppc/)
{
copy("$pkgdir/1/suseboot/inst64",
"/$tftpdir/xcat/$os/$arch");
@dd_drivers = &insert_dd($callback, $os, $arch, "/$tftpdir/xcat/$os/$arch/inst64");
copy("$pkgdir/1/suseboot/inst64", "$tftppath");
@dd_drivers = &insert_dd($callback, $os, $arch, "$tftppath/inst64", $driverupdatesrc, $netdrivers);
}
$doneimgs{"$os|$arch|$tftpdir"} = 1;
}
@ -953,23 +966,39 @@ sub mkinstall
{
$kcmdline .= " dhcptimeout=150";
}
my $kernelpath;
my $initrdpath;
if ($arch =~ /x86/)
{
if ($profile) {
$kernelpath = "xcat/$os/$arch/$profile/linux";
$initrdpath = "xcat/$os/$arch/$profile/initrd";
} else {
$kernelpath = "xcat/$os/$arch/linux";
$initrdpath = "xcat/$os/$arch/initrd";
}
$bptab->setNodeAttribs(
$node,
{
kernel => "xcat/$os/$arch/linux",
initrd => "xcat/$os/$arch/initrd",
kernel => $kernelpath,
initrd => $initrdpath,
kcmdline => $kcmdline
}
);
}
elsif ($arch =~ /ppc/)
{
if ($profile) {
$kernelpath = "xcat/$os/$arch/profile/inst64";
} else {
$kernelpath = "xcat/$os/$arch/inst64";
}
$bptab->setNodeAttribs(
$node,
{
kernel => "xcat/$os/$arch/inst64",
kernel => $kernelpath,
initrd => "",
kcmdline => $kcmdline
}
@ -1324,26 +1353,78 @@ sub copycd
}
}
# Get the driver update disk from /install/driverdisk/<os>/<arch>
# Take out the drivers from driver update disk and insert them
# into the initrd
# callback subroutine for 'find' command to return the path
my $driver_name;
my $real_path;
sub get_path ()
{
if ($File::Find::name =~ /\/$driver_name/) {
$real_path = $File::Find::name;
}
}
sub insert_dd {
# Get the driver disk or driver rpm from the osimage.driverupdatesrc
# The valid value: dud:/install/dud/dd.img,rpm:/install/rpm/d.rpm, if missing the tag: 'dud'/'rpm'
# the 'rpm' is default.
#
# If cannot find the driver disk from osimage.driverupdatesrc, will try to search driver disk
# from /install/driverdisk/<os>/<arch>
#
# For driver rpm, the driver list will be gotten from osimage.netdrivers. If not set, copy all the drivers from driver
# rpm to the initrd.
#
sub insert_dd () {
my $callback = shift;
my $os = shift;
my $arch = shift;
my $img = shift;
my $driverupdatesrc = shift;
my $drivers = shift;
my $install_dir = xCAT::Utils->getInstallDir();
# Find out the dirver disk which need to be insert into initrd
if (! -d "$install_dir/driverdisk/$os/$arch") {
return ();
my $cmd;
my @dd_list;
my @rpm_list;
my @driver_list;
my @rpm_drivers;
# Parse the parameters to the the source of Driver update disk and Driver rpm, and driver list as well
if ($driverupdatesrc) {
my @srcs = split(',', $driverupdatesrc);
foreach my $src (@srcs) {
if ($src =~ /dud:(.*)/i) {
push @dd_list, $1;
} elsif ($src =~ /rpm:(.*)/i) {
push @rpm_list, $1;
} else {
push @rpm_list, $src;
}
}
}
my $cmd = "find $install_dir/driverdisk/$os/$arch -type f";
my @dd_list = xCAT::Utils->runcmd($cmd, -1);
if (! @dd_list) {
# get Driver update disk from the default path if not specified in osimage
# check the Driver Update Disk images, it can be .img or .iso
if (-d "$install_dir/driverdisk/$os/$arch") {
$cmd = "find $install_dir/driverdisk/$os/$arch -type f";
@dd_list = xCAT::Utils->runcmd($cmd, -1);
}
}
foreach (split /,/,$drivers) {
unless (/\.ko$/) {
s/$/.ko/;
}
push @driver_list, $_;
}
chomp(@dd_list);
if (!@dd_list) {
chomp(@rpm_list);
unless (@dd_list || @rpm_list ) {
return undef;
}
@ -1354,25 +1435,125 @@ sub insert_dd {
my $pkgdir="$install_dir/$os/$arch";
# Unzip the original initrd
if ($arch =~/ppc/) {
$cmd = "gunzip --quiet -c $pkgdir/1/suseboot/initrd64 > $dd_dir/initrd";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not gunzip the initial initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return ();
}
# 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) {
if ($arch =~ /ppc/) {
$cmd = "gunzip --quiet -c $pkgdir/1/suseboot/initrd64 > $dd_dir/initrd";
} elsif ($arch =~ /x86/) {
$cmd = "gunzip --quiet -c $img > $dd_dir/initrd";
}
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not gunzip the initial initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return ();
}
# Unpack the initrd
$cmd = "cd $dd_dir/initrd_img; cpio -id --quiet < $dd_dir/initrd";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not extract files from the initial initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return ();
}
# Start to load the drivers from rpm packages
if (@rpm_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";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not extract files from the rpm $rpm.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
} else {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not read the rpm $rpm.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
# Copy the firmware to the rootimage
if (-d "$dd_dir/rpm/lib/firmware") {
if (! -d "$dd_dir/initrd_img/lib") {
mkpath "$dd_dir/initrd_img/lib";
}
$cmd = "cp -rf $dd_dir/rpm/lib/firmware $dd_dir/initrd_img/lib";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not copy firmware to the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
# Copy the drivers to the rootimage
# Figure out the kernel version
my @kernelpaths = <$dd_dir/initrd_img/lib/modules/*>;
my @kernelvers;
foreach (@kernelpaths) {
push @kernelvers, basename($_);
}
foreach my $kernelver (@kernelvers) {
if (@driver_list) {
# copy the specific drivers to initrd
foreach my $driver (@driver_list) {
$driver_name = $driver;
$real_path = "";
find(\&get_path, <$dd_dir/rpm/lib/modules/$kernelver/*>);
if ($real_path && $real_path =~ m!$dd_dir/rpm(/lib/modules/$kernelver/.*?)[^\/]*$!) {
if (! -d "$dd_dir/initrd_img$1") {
mkpath "$dd_dir/initrd_img$1";
}
$cmd = "cp -rf $real_path $dd_dir/initrd_img$1";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not copy driver $driver to the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
} else {
push @rpm_drivers, $driver;
}
}
}
} else {
# copy all the drviers to the initrd
if (-d "$dd_dir/rpm/lib/modules/$kernelver") {
$cmd = "cp -rf $dd_dir/rpm/lib/modules/$kernelver $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 /lib/modules/$kernelver to the initrd.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
} else {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update failed. Could not find /lib/modules/$kernelver from the driver rpms.";
xCAT::MsgUtils->message("I", $rsp, $callback);
}
}
# Unpack the initrd
$cmd = "cd $dd_dir/initrd_img; cpio -id --quiet < $dd_dir/initrd";
xCAT::Utils->runcmd($cmd, -1);
if ($::RUNCMD_RC != 0) {
my $rsp;
push @{$rsp->{data}}, "Handle the driver update disk failed. Could not extract files from the initial initrd.";
xCAT::MsgUtils->message("E", $rsp, $callback);
return ();
}
# regenerate the modules dependency
foreach my $kernelver (@kernelvers) {
$cmd = "cd $dd_dir/initrd_img; depmod -b . $kernelver";
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);
}
}
}
} # end of loading drivers from rpm packages
}
# Create the dir for driver update disk
@ -1394,41 +1575,54 @@ sub insert_dd {
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);
if ($arch =~ /x86/) {
my $rdhandle;
my $ddhandle;
open($rdhandle,">>",$img);
open ($ddhandle,"<","$dd_dir/initrd.gz");
binmode($rdhandle);
binmode($ddhandle);
{ local $/ = 32768; my $block; while ($block = <$ddhandle>) { print $rdhandle $block; } }
close($rdhandle);
close($ddhandle);
} elsif ($arch =~/ppc/) {
# make sure the src kernel existed
$cmd = "gunzip -c $pkgdir/1/suseboot/linux64.gz > $dd_dir/kernel";
xCAT::Utils->runcmd($cmd, -1);
# create the zimage
$cmd = "env -u POSIXLY_CORRECT /lib/lilo/scripts/make_zimage_chrp.sh --vmlinux $dd_dir/kernel --initrd $dd_dir/initrd.gz --output $img";
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 ();
if ($arch =~/ppc/ || @rpm_list) {
if ($arch =~/ppc/) {
# make sure the src kernel existed
$cmd = "gunzip -c $pkgdir/1/suseboot/linux64.gz > $dd_dir/kernel";
xCAT::Utils->runcmd($cmd, -1);
# create the zimage
$cmd = "env -u POSIXLY_CORRECT /lib/lilo/scripts/make_zimage_chrp.sh --vmlinux $dd_dir/kernel --initrd $dd_dir/initrd.gz --output $img";
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 ();
}
} elsif ($arch =~/x86/) {
copy ("$dd_dir/initrd.gz", "$img");
}
} elsif ($arch =~ /x86/) {
my $rdhandle;
my $ddhandle;
open($rdhandle,">>",$img);
open ($ddhandle,"<","$dd_dir/initrd.gz");
binmode($rdhandle);
binmode($ddhandle);
{ local $/ = 32768; my $block; while ($block = <$ddhandle>) { print $rdhandle $block; } }
close($rdhandle);
close($ddhandle);
}
# clean the env
system("rm -rf $dd_dir");
my $rsp;
push @{$rsp->{data}}, "Inserted the driver update disk:".join(',', sort(@dd_list)).".";
if (@dd_list) {
push @{$rsp->{data}}, "Inserted the driver update disk:".join(',', sort(@dd_list)).".";
}
if (@driver_list) {
push @{$rsp->{data}}, "Inserted the drivers:".join(',', sort(@rpm_drivers))." from driver packages.";
} elsif (@rpm_list) {
push @{$rsp->{data}}, "Inserted the drivers from driver packages:".join(',', sort(@rpm_list)).".";
}
xCAT::MsgUtils->message("I", $rsp, $callback);
my @dd_files = ();

View File

@ -85,6 +85,7 @@ GetOptions(
'otherpkglist=s' => \$otherpkglist, #internal flag
'postinstall=s' => \$postinstall_filename, #internal flag
'rootimgdir=s' => \$destdir, #internal flag
'driverupdatesrc=s' => \$driverupdatesrc, #internal flag
'interactive' =>\$prompt,
);
@ -435,7 +436,7 @@ foreach my $dd (@dd_drivers) {
unless (grep { $_ eq $dd} @ndrivers) {
push @new_order, $dd;
}
print "Added driver $dd from driver update disk.\n";
print "Added driver $dd from driver update disk or driver rpm.\n";
}
@ndrivers = (@new_order, @ndrivers);
@ -1495,18 +1496,68 @@ sub get_path ()
}
}
#load the driver update disk, and return the driver names by loading order
my @all_real_path;
sub get_all_path ()
{
if ($File::Find::name =~ /\/$driver_name/) {
push @all_real_path, $File::Find::name;
}
}
# Load driver disk and driver rpm to the initrd
# Get the driver disk or driver rpm from the osimage.driverupdatesrc
# The valid value: dud:/install/dud/dd.img,rpm:/install/rpm/d.rpm, if missing the tag: 'dud'/'rpm'
# the 'rpm' is default.
#
# If cannot find the driver disk from osimage.driverupdatesrc, will try to search driver disk
# from /install/driverdisk/<os>/<arch>
#
# For driver rpm, the driver list will be gotten from osimage.netdrivers. If not set, copy all the drivers from driver
# rpm to the initrd.
#
# Return the driver names by loading order
sub load_dd ()
{
# Get the Driver Update Disk images, it can be .img or .iso
if (! -d "$installroot/driverdisk/$osver/$arch") {
return ();
my @dd_list;
my @rpm_list;
my @driver_list;
my @rpm_drivers;
# Parse the parameters to the the source of Driver update disk and Driver rpm, and driver list as well
if ($driverupdatesrc) {
my @srcs = split(',', $driverupdatesrc);
foreach my $src (@srcs) {
if ($src =~ /dud:(.*)/i) {
push @dd_list, $1;
} elsif ($src =~ /rpm:(.*)/i) {
push @rpm_list, $1;
} else {
push @rpm_list, $src;
}
}
}
if (! @dd_list) {
# get Driver update disk from the default path if not specified in osimage
# check the Driver Update Disk images, it can be .img or .iso
if (-d "$installroot/driverdisk/$osver/$arch") {
@dd_list = `find $installroot/driverdisk/$osver/$arch -type f`;
}
}
my @dd_list = `find $installroot/driverdisk/$osver/$arch -type f`;
chomp(@dd_list);
foreach (split /,/,$netdriver) {
unless (/\.ko$/) {
s/$/.ko/;
}
push @driver_list, $_;
}
if (! @dd_list) {
chomp(@dd_list);
chomp(@rpm_list);
unless (@dd_list || @rpm_list ) {
return ();
}
@ -1515,7 +1566,7 @@ sub load_dd ()
mkpath "$dd_dir/mnt";
mkpath "$dd_dir/mods";
my @dd_drivers = (); #dirver name
my @dd_drivers = (); #driver name
# Loading drivers from each Driver Disk
foreach my $dd (@dd_list) {
@ -1589,6 +1640,59 @@ sub load_dd ()
}
}
# Loading the drivers from rpm packages
if (@rpm_list) {
if (@rpm_list) {
# Extract the files from rpm to the tmp dir
mkpath "$dd_dir/rpm";
foreach my $rpm (@rpm_list) {
if (-r $rpm) {
if (system ("cd $dd_dir/rpm; rpm2cpio $rpm | cpio -idum")) {
print "Error: Cannot extract the files from the rpm $rpm.\n";
}
} else {
print "Error: Cannot read the rpm $rpm.\n";
}
}
# Copy the firmware to the rootimage
if (-d "$dd_dir/rpm/lib/firmware") {
system ("cp -rf $dd_dir/rpm/lib/firmware $rootimg_dir/lib");
}
# Copy the drivers to the rootimage
if (-d "$dd_dir/rpm/lib/modules/$kernelver") {
if (@driver_list) {
foreach my $driver (@driver_list) {
$driver_name = $driver;
$real_path = "";
find(\&get_path, <$dd_dir/rpm/lib/modules/$kernelver/*>);
if ($real_path && $real_path =~ m!$dd_dir/rpm(/lib/modules/$kernelver/.*?)[^\/]*$!) {
if (! -d "$rootimg_dir$1") {
mkpath "$rootimg_dir$1";
}
system ("cp -rf $real_path $rootimg_dir$1");
push @rpm_drivers, $driver;
} else {
print "Error: cannot find the driver $driver from the driver rpms\n";
}
}
} else {
# copy all the drviers to the rootimage
system ("cp -rf $dd_dir/rpm/lib/modules/$kernelver $rootimg_dir/lib/modules/");
find(\&get_all_path, <$dd_dir/rpm/lib/modules/$kernelver/*>);
foreach (@all_real_path) {
if (basename($_) =~ /\.ko$/) {
push @rpm_drivers, basename($_);
}
}
}
} else {
print "Warning: cannot find the kernel $kernelver from drvier rpms\n";
}
}
push @dd_drivers, @rpm_drivers;
}
# Generate the dependency relationship
system ("chroot '$rootimg_dir' depmod $kernelver");

View File

@ -101,6 +101,7 @@ GetOptions(
'otherpkglist=s' => \$otherpkglist, #internal flag
'postinstall=s' => \$postinstall_filename, #internal flag
'rootimgdir=s' => \$destdir, #internal flag
'driverupdatesrc=s' => \$driverupdatesrc, #internal flag
'interactive' =>\$prompt,
);
@ -711,7 +712,7 @@ foreach my $dd (@dd_drivers) {
unless (grep { $_ eq $dd} @ndrivers) {
push @new_order, $dd;
}
print "Added driver $dd from driver update disk.\n";
print "Added driver $dd from driver update disk or driver rpm.\n";
}
@ndrivers = (@new_order, @ndrivers);
@ -1549,19 +1550,68 @@ sub get_path ()
}
}
#load the driver update disk, and return the driver names by loading order
my @all_real_path;
sub get_all_path ()
{
if ($File::Find::name =~ /\/$driver_name/) {
push @all_real_path, $File::Find::name;
}
}
# Load driver disk and driver rpm to the initrd
# Get the driver disk or driver rpm from the osimage.driverupdatesrc
# The valid value: dud:/install/dud/dd.img,rpm:/install/rpm/d.rpm, if missing the tag: 'dud'/'rpm'
# the 'rpm' is default.
#
# If cannot find the driver disk from osimage.driverupdatesrc, will try to search driver disk
# from /install/driverdisk/<os>/<arch>
#
# For driver rpm, the driver list will be gotten from osimage.netdrivers. If not set, copy all the drivers from driver
# rpm to the initrd.
#
# Return the driver names by loading order
sub load_dd()
{
# check the Driver Update Disk images, it can be .img or .iso
if (! -d "$installroot/driverdisk/$osver/$arch") {
return ();
my @dd_list;
my @rpm_list;
my @driver_list;
my @rpm_drivers;
# Parse the parameters to the the source of Driver update disk and Driver rpm, and driver list as well
if ($driverupdatesrc) {
my @srcs = split(',', $driverupdatesrc);
foreach my $src (@srcs) {
if ($src =~ /dud:(.*)/i) {
push @dd_list, $1;
} elsif ($src =~ /rpm:(.*)/i) {
push @rpm_list, $1;
} else {
push @rpm_list, $src;
}
}
}
if (! @dd_list) {
# get Driver update disk from the default path if not specified in osimage
# check the Driver Update Disk images, it can be .img or .iso
if (-d "$installroot/driverdisk/$osver/$arch") {
@dd_list = `find $installroot/driverdisk/$osver/$arch -type f`;
}
}
my @dd_list = `find $installroot/driverdisk/$osver/$arch -type f`;
chomp(@dd_list);
foreach (split /,/,$netdriver) {
unless (/\.ko$/) {
s/$/.ko/;
}
push @driver_list, $_;
}
if (! @dd_list) {
return ();
chomp(@dd_list);
chomp(@rpm_list);
unless (@dd_list || @rpm_list ) {
return undef;
}
# Create the work space, it should be cleaned at end of genimage
@ -1569,7 +1619,7 @@ sub load_dd()
mkpath "$dd_dir/mnt";
mkpath "$dd_dir/mods";
my @dd_drivers = (); #dirver names
my @dd_drivers = (); #driver names
# Load drivers from each Driver Disk
# For multiple dd, if want to make it has order, rename the dd with a number
@ -1692,6 +1742,58 @@ sub load_dd()
}
}
# Loading the drivers from rpm packages
if (@rpm_list) {
# Extract the files from rpm to the tmp dir
mkpath "$dd_dir/rpm";
foreach my $rpm (@rpm_list) {
if (-r $rpm) {
if (system ("cd $dd_dir/rpm; rpm2cpio $rpm | cpio -idum")) {
print "Error: Cannot extract the files from the rpm $rpm.\n";
}
} else {
print "Error: Cannot read the rpm $rpm.\n";
}
}
# Copy the firmware to the rootimage
if (-d "$dd_dir/rpm/lib/firmware") {
system ("cp -rf $dd_dir/rpm/lib/firmware $rootimg_dir/lib");
}
# Copy the drivers to the rootimage
if (-d "$dd_dir/rpm/lib/modules/$kernelver") {
#mkpath "$rootimg_dir/lib/modules/$kernelver/updates/";
if (@driver_list) {
foreach my $driver (@driver_list) {
$driver_name = $driver;
$real_path = "";
find(\&get_path, <$dd_dir/rpm/lib/modules/$kernelver/*>);
if ($real_path && $real_path =~ m!$dd_dir/rpm(/lib/modules/$kernelver/.*?)[^\/]*$!) {
if (! -d "$rootimg_dir$1") {
mkpath "$rootimg_dir$1";
}
system ("cp -rf $real_path $rootimg_dir$1");
push @rpm_drivers, $driver;
} else {
print "Error: cannot find the driver $driver from the driver rpms\n";
}
}
} else {
# copy all the drviers to the rootimage
system ("cp -rf $dd_dir/rpm/lib/modules/$kernelver $rootimg_dir/lib/modules/");
find(\&get_all_path, <$dd_dir/rpm/lib/modules/$kernelver/*>);
foreach (@all_real_path) {
if (basename($_) =~ /\.ko$/) {
push @rpm_drivers, basename($_);
}
}
}
} else {
print "Warning: cannot find the kernel $kernelver from drvier rpms\n";
}
push @dd_drivers, @rpm_drivers;
}
# Generate the dependency relationship
system ("chroot '$rootimg_dir' depmod $kernelver");