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:
		| @@ -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# | ||||
| #################### | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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"; | ||||
|   | ||||
| @@ -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 = (); | ||||
|   | ||||
| @@ -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"); | ||||
|  | ||||
|   | ||||
| @@ -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"); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user