From d226d3d75dfc5c0ed9ae8de2c41a5c6f2ca692dc Mon Sep 17 00:00:00 2001 From: arifali Date: Mon, 30 Apr 2012 00:03:11 +0000 Subject: [PATCH] ubuntu: add new genimage which has a few additions for dracut, when available, and re-enabled busybox-static, as that is available in ubuntu10.10. this current one works with 10.10 git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@12400 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- .../share/xcat/netboot/ubuntu/compute.pkglist | 1 + .../share/xcat/netboot/ubuntu/genimage | 1678 +++++++++++++++++ 2 files changed, 1679 insertions(+) create mode 100755 xCAT-server/share/xcat/netboot/ubuntu/genimage diff --git a/xCAT-server/share/xcat/netboot/ubuntu/compute.pkglist b/xCAT-server/share/xcat/netboot/ubuntu/compute.pkglist index eed35bbc1..007b22e76 100644 --- a/xCAT-server/share/xcat/netboot/ubuntu/compute.pkglist +++ b/xCAT-server/share/xcat/netboot/ubuntu/compute.pkglist @@ -10,3 +10,4 @@ vim ntp rsyslog rsync +busybox-static diff --git a/xCAT-server/share/xcat/netboot/ubuntu/genimage b/xCAT-server/share/xcat/netboot/ubuntu/genimage new file mode 100755 index 000000000..97aa75d51 --- /dev/null +++ b/xCAT-server/share/xcat/netboot/ubuntu/genimage @@ -0,0 +1,1678 @@ +#!/usr/bin/env perl +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; +} +use lib "$::XCATROOT/lib/perl"; + +use File::Basename; +use File::Path; +use File::Copy qw/copy cp mv move/; +use File::Find; +use Getopt::Long; +use Cwd qw(realpath); +use xCAT::Utils; +use File::Temp qw/mkdtemp/; + +use FindBin; +use lib "$FindBin::Bin/../imgutils"; +use imgutils; + +#use strict; +Getopt::Long::Configure("bundling"); +Getopt::Long::Configure("pass_through"); + +my $dracutmode; #Indicate whether this is a dracut style initrd +my $dracutdir = "dracut"; # The default directory name of dracut +my $prinic; #TODO be flexible on node primary nic +my $othernics; #TODO be flexible on node primary nic +my $netdriver; +my @yumdirs; +my $arch; +my %libhash; +my @filestoadd; +my $profile; +my $osver; +my $pathtofiles=dirname($0); +my $fullpath=realpath($pathtofiles); +my $name = basename($0); +my $onlyinitrd=0; +if ($name =~ /geninitrd/) { + $onlyinitrd=1; +} +my $rootlimit; +my $tmplimit; +my $installroot = "/install"; +my $kerneldir; +my $kernelver = ""; #`uname -r`; +my $basekernelver; # = $kernelver; +my $customdir=$fullpath; +$customdir =~ s/.*share\/xcat/$installroot\/custom/; +my $imagename; +my $pkglist; +my $srcdir; +my $destdir; +my $srcdir_otherpkgs; +my $otherpkglist; +my $postinstall_filename; +my $rootimg_dir; +my $permission; # the permission works only for statelite mode currently +my $tempfile; +my $prompt; + + +sub xdie { + system("rm -rf /tmp/xcatinitrd.$$"); + umount_chroot($rootimg_dir); + die @_; +} + +$SIG{INT} = $SIG{TERM} = sub { xdie "Interrupted" }; +GetOptions( + 'a=s' => \$arch, + 'p=s' => \$profile, + 'o=s' => \$osver, + 'n=s' => \$netdriver, + 'i=s' => \$prinic, + 'r=s' => \$othernics, + 'l=s' => \$rootlimit, + 't=s' => \$tmplimit, + 'k=s' => \$kernelver, + 'permission=s' => \$permission, + 'kerneldir=s' => \$kerneldir, + 'tempfile=s' =>\$tempfile, #internal flag + 'pkglist=s' => \$pkglist, #internal flag + 'srcdir=s' => \$srcdir, #internal flag + 'otherpkgdir=s' => \$srcdir_otherpkgs, #internal flag + 'otherpkglist=s' => \$otherpkglist, #internal flag + 'postinstall=s' => \$postinstall_filename, #internal flag + 'rootimgdir=s' => \$destdir, #internal flag + 'interactive' =>\$prompt, +); + +if (@ARGV > 0) { + $imagename=$ARGV[0]; +} + +my %updates_os = (); # the hash for updating osimage table +my %updates = (); # the hash for updating linuximage table + + +$permission = "755" unless ($permission); +$updates{'permission'} = $permission if ( $tempfile ); + +unless ($arch) { + $arch = `uname -m`; + chomp($arch); + $arch = "x86" if ($arch =~ /i.86$/); +} + +$srcdir="$installroot/$osver/$arch" unless ($srcdir); +$updates{'pkgdir'} = $srcdir if ($tempfile); + +$srcdir_otherpkgs = "$installroot/post/otherpkgs/$osver/$arch" unless ($srcdir_otherpkgs); +$updates{'otherpkgdir'} = $srcdir_otherpkgs if ($tempfile); + +$destdir="$installroot/netboot/$osver/$arch/$profile" unless ($destdir); +$updates{'rootimgdir'} = $destdir if ($tempfile); + +$rootimg_dir="$destdir/rootimg"; + +$kerneldir = "$installroot/kernels" unless ($kerneldir); # the default directory for 3rd-party kernel is "$installroot/kernels"; +#$updates{'kerneldir'} = $kerneldir if ($tempfile); + +# Get the subchannels of the given interface +my $subchn; +my $readChn; +my @chn; +if ($arch eq "s390x") { + $subchn = `cat /etc/sysconfig/network-scripts/ifcfg-$prinic | grep "SUBCHANNELS"`; + + if (!$subchn) { + print "SUBCHANNELS need to be given in /etc/sysconfig/network-scripts/ifcfg-$prinic"; + exit 1; + } else { + # Trim right + $subchn =~ s/\s*$//; + + # Trim left + $subchn =~ s/^\s*//; + + # Extract subchannels + $subchn =~ s/SUBCHANNELS=//g; + + # Extract read channel + @chn = split( ",", $subchn ); + $readChn = @chn[0]; + } +} + +unless ($osver and $profile) { + usage(); + exit 1; +} + +my @ndrivers; +if ($netdriver) { + if ( ($updates{'netdrivers'} ne $netdriver) and ($tempfile) ) { + $updates{'netdrivers'} = $netdriver; + } +} else { + if ($arch eq 'x86' or $arch eq 'x86_64') { + @ndrivers = qw/tg3 bnx2 bnx2x e1000 e1000e igb mlx_en virtio_net/; + } elsif ($arch eq 'ppc64') { + @ndrivers = qw/e1000 e1000e igb ibmveth ehea/; + } elsif ($arch eq 's390x') { + @ndrivers = qw/qdio ccwgroup/; + } +} +foreach (split /,/,$netdriver) { + unless (/\.ko$/) { + s/$/.ko/; + } + next if (/^$/); + push @ndrivers, $_; +} + +foreach (@ndrivers) { + unless (/\.ko$/) { + s/$/.ko/; + } +} + +my $uarch=$arch; +$uarch="amd64" if ($arch eq x86_64); + + +unless ($onlyinitrd) { + @aptdirs=(); + find(\&isaptdir, <$installroot/$osver/$arch/>); + # Add the dir for kernel deb to be installed + if ($kernelver) { + find(\&isaptdir, <$kerneldir/>); + if (!grep /$kerneldir/, @aptdirs) { + print "The repository for $kerneldir should be created before running the geniamge. Try to run [createrepo $kerneldir].\n"; + } + } + unless (scalar(@aptdirs)) { + print "Need $installroot/$osver/$arch/ available from a system that has ran copycds on $osver $arch\n"; + exit 1; + } + + my $aptconfig; + open($aptconfig,">","/tmp/genimage.$$.apt.list"); + my $repnum=0; + foreach $srcdir (@aptdirs) { + print $aptconfig "deb file://$srcdir main stable\n\n"; + $repnum += 1; + } + $repnum-=1; + close($aptconfig); + mkpath "$rootimg_dir/etc"; + + + + my $fd; + open($fd,">>","$rootimg_dir/etc/fstab"); + print $fd "#Dummy fstab for dpkg postscripts to see\n"; + close($fd); + + my $non_interactive; + if (!$prompt) { $non_interactive="-y"; } + + my @line=split(" ",`ls -lh $installroot/$osver/$arch/dists/ | grep dr`); + my $dist = $line[@line-1]; + + my $aptgetcmd = "chroot $rootimg_dir apt-get update && chroot $rootimg_dir apt-get $non_interactive "; + my $aptcachecmd = "chroot $rootimg_dir apt-get update && chroot $rootimg_dir apt-cache $non_interactive "; + my $aptcmd1 = "debootstrap"; + my $aptcmd2 = "--arch $uarch $dist $rootimg_dir file://$installroot/$osver/$arch/"; + + mkpath("$rootimg_dir/var/lib/dpkg"); + mkpath("$rootimg_dir/var/lib/apt"); + + unless ($imagename) { + $pkglist= imgutils::get_profile_def_filename($osver, $profile, $arch, $customdir, "pkglist"); + unless ($pkglist) { + $pkglist= imgutils::get_profile_def_filename($osver, $profile, $arch, $pathtofiles, "pkglist"); + } + } + + if ($pkglist) { + $updates{'pkglist'} = $pkglist if ($tempfile); + } else { + print "Unable to find package list for $profile!"; + exit 1; + } + + my %pkg_hash=imgutils::get_package_names($pkglist); + my $index=1; + my $pass; + foreach $pass (sort (keys(%pkg_hash))) { + my $pkgnames = ""; + foreach (keys(%{$pkg_hash{$pass}})) { + if (($_ eq "PRE_REMOVE") || ($_ eq "POST_REMOVE") || ($_ eq "ENVLIST")) { next;} + my $pa=$pkg_hash{$pass}{$_}; + my @npa = (); + # replace the kernel package with the name has the specific version + foreach my $p (@$pa) { + print "$p\n"; + if ($p =~ /^linux-image-server$/ && $kernelver) { + my $kernelname = "linux-image-".$kernelver."-server"; + my $searchkern = $aptcachecmd . " search $kernelname"; + my @kernpkgs = `$searchkern`; + my $found = 0; + foreach my $k (@kernpkgs) { + if ($k =~ /\s*linux-image-server[^\s]*\s+([\w\.-]+)/) { + my $version = $1; + my $relversion = $kernelver; + $relversion =~ s/\.[^\.]+$//; + if ($version == $relversion) { + $found++; + } + } + } + if ($found eq 0) { + print "Cannot find the kernel with version $kernelver.\n"; + exit 1; + } + push @npa, $kernelname; + } + elsif ($p =~ /^@/) { + push @npa, "\"$p\""; + } + else { + push @npa, $p; + } + } + $pkgnames .= join(',', @npa); + } + my $envlist; + if(exists $pkg_hash{$pass}{ENVLIST}){ + $envlist = join(',', @{$pkg_hash{$pass}{ENVLIST}}); + } + + print "$envlist $aptcmd1 --include=$pkgnames $aptcmd2\n"; + my $rc = system("$envlist $aptcmd1 --include=$pkgnames $aptcmd2"); + if ($rc) { + print "apt invocation failed\n"; + exit 1; + } + } + + mount_chroot($rootimg_dir); + + # Add the local repo from MN temporarily for apt-get update/upgrade + open($aptconfig,">","$rootimg_dir/etc/apt/sources.list"); + print $aptconfig "deb file://$installroot/$osver/$arch/ $dist main\n"; + close($aptconfig); + + #Now let's handle extra packages + unless ($imagename) { + $otherpkglist = imgutils::get_profile_def_filename($osver, $profile, $arch, $customdir, "otherpkgs.pkglist"); + unless ($otherpkglist) { $otherpkglist=imgutils::get_profile_def_filename($osver, $profile, $arch, $pathtofiles, "otherpkgs.pkglist"); } + } + my %extra_hash=(); + if ($otherpkglist) { + $updates{'otherpkglist'} = $otherpkglist if ($tempfile); + %extra_hash = imgutils::get_package_names($otherpkglist); + } + my %extrapkgnames; + + if (keys(%extra_hash) > 0) { + open($aptconfig,">>","$rootimg_dir/etc/apt/sources.list.d/genimage.$$.apt.list"); + my $index=1; + foreach $pass (sort (keys(%extra_hash))) { + foreach (keys(%{$extra_hash{$pass}})) { + if (($_ eq "PRE_REMOVE") || ($_ eq "POST_REMOVE") || ($_ eq "ENVLIST")) { next;} + print $aptconfig "deb file://$srcdir_otherpkgs/$_ . /"; + $index++; + my $pa=$extra_hash{$pass}{$_}; + $extrapkgnames{$pass} .= " " . join(' ', @$pa); + } + } + close($aptconfig); + $index--; + + foreach $pass (sort (keys(%extra_hash))) { + my $envlist; + if(exists($extra_hash{$pass}{ENVLIST})){ + $envlist = join(' ', @{$extra_hash{$pass}{ENVLIST}}); + } + # remove the packages that are specified in the otherpkgs.list files with leading '-' + my $aptgetcmd_remove= "$aptgetcmd remove "; + if (exists ($extra_hash{$pass}{'PRE_REMOVE'})) { + my $pa=$extra_hash{$pass}{'PRE_REMOVE'}; + my $rm_packges= join(' ', @$pa); + if ($rm_packges) { + print "$envlist $aptgetcmd_remove $rm_packges\n"; + $rc = system("$envlist $aptgetcmd_remove $rm_packges"); + } + } + + # mount /proc file system since several packages need it. + print "mount /proc file system\nchroot $rootimg_dir /bin/mount -t proc proc /proc\n"; + system("chroot $rootimg_dir /bin/mount -t proc proc /proc"); + + # install extra packages + my $aptgetcmd_base = $aptgetcmd; + $aptgetcmd .= " install "; + # append extra pkg names to yum command + if ($extrapkgnames{$pass}) { + $aptgetcmd .= " $extrapkgnames{$pass} "; + $aptgetcmd =~ s/ $/\n/; + + # debug + #print "aptgetcmd=$aptgetcmd\n"; + #my $repo=`cat /tmp/genimage.$$.yum.conf`; + #print "repo=$repo"; + + print "$envlist $aptgetcmd\n"; + my $rc = system("$envlist $aptgetcmd"); + if ($rc) { + print "apt-get invocation failed\n"; + exit 1; + } + } else { + print "No Packages marked for install\n"; + } + + # umount /proc file system that just mounted + print "umount /proc file system\nchroot $rootimg_dir /bin/umount /proc\n"; + system("chroot $rootimg_dir /bin/umount /proc"); + + # remove the packages that are specified in the otherpkgs.list files with leading '--' + if (exists ($extra_hash{$pass}{'POST_REMOVE'})) { + my $pa=$extra_hash{$pass}{'POST_REMOVE'}; + my $rm_packges= join(' ', @$pa); + if ($rm_packges) { + print "$envlist $aptgetcmd_remove $rm_packges\n"; + $rc = system("$envlist $aptgetcmd_remove $rm_packges"); + } + } + $aptgetcmd = $aptgetcmd_base; + } + } + + # run apt-get upgrade to update any installed debs + # needed when running genimage again after updating software in repositories + my $aptgetcmd_update = $yumcmd_base . " upgrade "; + $rc = system("$aptgetcmd_update"); + umount_chroot($rootimg_dir); + # ignore any return code + + # Add the local repo from MN + my $master = xCAT::Utils->get_site_Master(); + open($aptconfig,">","$rootimg_dir/etc/apt/sources.list"); + print $aptconfig "deb http://$master$installroot/$osver/$arch/ $dist main\n"; + close($aptconfig); + + postscripts(); #run 'postscripts' +} + +# Default to the first kernel found in the install image if nothing specified explicitly. +# A more accurate guess than whatever the image build server happens to be running +# If specified, that takes precedence. +# if image has one, that is used +# if all else fails, resort to uname -r like this script did before + +# Kernel name for s390x should be the same: vmlinuz-2.6.18-164.el5 +my @KVERS= <$rootimg_dir/boot/vmlinuz-*>; +foreach (@KVERS) { + s/vmlinuz-//; +} + +@KVERS= <$rootimg_dir/lib/modules/*> unless (scalar(@KVERS)); + +$basekernelver = basename(pop @KVERS) if (scalar(@KVERS)); + +$basekernelver = `uname -r` unless ($basekernelver); + +$kernelver = $basekernelver unless ($kernelver); +chomp($kernelver); + +#$updates{'kernelver'} = $kernelver if ($tempfile); + +# copy the kernel to $destdir +if ( -e "$rootimg_dir/boot/vmlinux-$kernelver") { + cp("$rootimg_dir/boot/vmlinux-$kernelver", "$destdir/kernel"); +} elsif ( -e "$rootimg_dir/boot/vmlinuz-$kernelver") { + cp("$rootimg_dir/boot/vmlinuz-$kernelver", "$destdir/kernel"); +} elsif ( -e "$rootimg_dir/boot/image-$kernelver") { + cp("$rootimg_dir/boot/image-$kernelver", "$destdir/kernel"); +} else { + xdie("couldn't find the kernel file matched $kernelver in $rootimg_dir/boot"); +} + +# Load driver update disk, and copy them to the root image +my @dd_drivers = &load_dd(); + +# Push the drivers into the @ndrivers base on the order +my @new_order = (); +foreach my $dd (@dd_drivers) { + unless (grep { $_ eq $dd} @ndrivers) { + push @new_order, $dd; + } + print "Added driver $dd from driver update disk.\n"; +} +@ndrivers = (@new_order, @ndrivers); + +open($moddeps,"<","$rootimg_dir/lib/modules/$kernelver/modules.dep"); +my @moddeps = <$moddeps>; +my @checkdeps = @ndrivers; +while (scalar @checkdeps) { + my $driver = pop @checkdeps; + my @lines = grep /\/$driver:/,@moddeps; + foreach (@lines) { + chomp; + s/.*://; + s/^\s*//; + my @deps = split /\s+/,$_; + my $dep; + foreach $dep (@deps) { + $dep =~ s/.*\///; + unless (grep { $_ eq $dep } @ndrivers) { #only add if not added + unshift (@checkdeps,$dep); #recursively check dependencies + unshift (@ndrivers,$dep); + print "Added $dep as an autodetected depedency\n"; + } + } + } +} +close($moddeps); +if (-d "$rootimg_dir/usr/share/dracut") { + $dracutmode = 1; + # get dracut version + my $dracutver = `chroot $rootimg_dir dpkg-query -W dracut | awk '{print \$2}'| aek -F- {print \$1}'`; + if ($dracutver =~ /^\d\d\d$/) { + if ($dracutver >= "009") { + $dracutdir = "dracut_009"; + } else { + $dracutdir = "dracut"; # The default directory + } + } + print "Enter the dracut mode. Dracut version: $dracutver. Dracut directory: $dracutdir.\n"; +} + +#-- run postinstall script +unless ($imagename) { + $postinstall_filename= imgutils::get_profile_def_filename($osver, $profile, $arch, $customdir, "postinstall"); + unless ($postinstall_filename) { + $postinstall_filename= imgutils::get_profile_def_filename($osver, $profile, $arch, $pathtofiles, "postinstall"); + } +} + +if (($postinstall_filename) && (-x $postinstall_filename)) { + + $updates{'postinstall'} = $postinstall_filename if ($tempfile); + + my $rc = system($postinstall_filename, $rootimg_dir,$osver,$arch,$profile); + if($rc) { + print "postinstall script failed\n"; + exit 1; + } +} + +# all the attributes have been gathered +# now, update the linuximage and osimage tables +# TODO: do statelite and stateless share the same attributes? +#BEGIN: PLEASE DO NOT CHANGE THE FOLLOWING CODE, genimage PLUGIN NEEDS TO PARSE THR OUTPUT +if ($tempfile) { + open(FILE, ">>$tempfile"); + if ($imagename) { + if (keys(%updates) > 0) { + print FILE "The output for table updates starts here\n"; + print FILE "table::linuximage\n"; + print FILE "imagename::$imagename\n"; + my @a=%updates; + print FILE join('::',@a) . "\n"; + print FILE "The output for table updates ends here\n"; + } + } else { + $updates_os{'profile'} = $profile; + $updates_os{'imagetype'} = 'linux'; + $updates_os{'provmethod'} = 'netboot'; + $updates_os{'osname'} = 'Linux'; + $updates_os{'osvers'} = $osver; + $updates_os{'osarch'} = $arch; + # update the imagename for stateless + print FILE "The output for table updates starts here\n"; + print FILE "table::osimage\n"; + print FILE "imagename::$osver-$arch-netboot-$profile\n"; + my @a=%updates_os; + print FILE join('::',@a) . "\n"; + print FILE "The output for table updates ends here\n"; + + print FILE "The output for table updates starts here\n"; + print FILE "table::linuximage\n"; + print FILE "imagename::$osver-$arch-netboot-$profile\n"; + my @a=%updates; + print FILE join('::',@a) . "\n"; + print FILE "The output for table updates ends here\n"; + + # update the imagename for statelite + $updates_os{'provmethod'} = 'statelite'; + print FILE "The output for table updates starts here\n"; + print FILE "table::osimage\n"; + print FILE "imagename::$osver-$arch-statelite-$profile\n"; + my @a=%updates_os; + print FILE join('::',@a) . "\n"; + print FILE "The output for table updates ends here\n"; + + print FILE "The output for table updates starts here\n"; + print FILE "table::linuximage\n"; + print FILE "imagename::$osver-$arch-statelite-$profile\n"; + my @a=%updates; + print FILE join('::',@a) . "\n"; + print FILE "The output for table updates ends here\n"; + } + close FILE; +} +#END + + +# statelite .statelite directory added here. +# this is where tmpfs will be created. + +mkpath "$rootimg_dir/.statelite"; # create place for NFS mounts. + +# this script will get the directories. +# TODO: the file is re-copied in liteimg.pm +my $cwd = $FindBin::Bin; +unless (-f "$cwd/../add-on/statelite/rc.statelite") { + print "Can't find $cwd/../add-on/statelite/rc.statelite!\n"; + exit 1; +} + +system("cp $cwd/../add-on/statelite/rc.statelite $rootimg_dir/etc/init.d/statelite"); +# also need to add this file: +# may have already been made into a symbolic link, if so ignore it + +unless ($dracutmode) { #in dracut mode, we delegate all this activity + unless (-l "$rootimg_dir/var/lib/dhclient" ) { + mkpath "$rootimg_dir/var/lib/dhclient/"; + system("touch $rootimg_dir/var/lib/dhclient/dhclient-$prinic.leases"); + } + + unless (-l "$rootimg_dir/var/lib/dhcp" ) { + mkpath "$rootimg_dir/var/lib/dhcp/"; + system("touch $rootimg_dir/var/lib/dhcp/dhclient-$prinic.leases"); + } +} + +if ($dracutmode) { + # modify etc/rc.sysinit, prevent remounting + # TODO: need to find one way to prevent remounting + my $SYSINITFILE; + my $TMPSYSINITFILE; + if (-f "$rootimg_dir/etc/rc.sysinit") { + # backup etc/rc.sysinit file before modifing it + system("cp -a $rootimg_dir/etc/rc.sysinit $rootimg_dir/etc/rc.sysinit.backup"); + open($SYSINITFILE, "$rootimg_dir/etc/rc.sysinit"); + open($TMPSYSINITFILE, '>', "/tmp/rc.sysinit.tmp"); + # find the following lines, + # if remount_needed ; then + # action $"Remounting root filesystem in read-write mode: " mount -n -o remount,rw / + # fi + # and change "if remount_needed ; then" to "if false; then" + while(<$SYSINITFILE>) { + if ($_ eq "if remount_needed ; then\n") { + $_ = "if false; then\n"; + } + print $TMPSYSINITFILE $_; + } + close($SYSINITFILE); + close($TMPSYSINITFILE); + cp("/tmp/rc.sysinit.tmp", "$rootimg_dir/etc/rc.sysinit"); + } +} + +# before mkinitrd, run depmod to generate modules.dep +system("chroot $rootimg_dir depmod $kernelver"); + +# for the genimage-enchement, need to create two initial ramdisks, +# one is for stateless +# the other one is for statelite + +if ($dracutmode) { + mkinitrd_dracut("statelite"); + mkinitrd_dracut("stateless"); +} else { + mkinitrd("statelite"); + mkinitrd("stateless"); +} + +sub getlibs { + my $file = shift; + my $liblist = `chroot $rootimg_dir ldd $file`; + my @libs = split/\n/,$liblist; + my @return; + foreach (@libs) { + unless (/=>/) { + (my $wjnk, my $lib,my $jnk) = split /\s+/,$_,3; + $lib =~ s/^\///; + $libhash{$lib}=1; + next; + } + (my $temp1,my $temp2) = split />/,$_,2; + (my $whitespace,$temp1,$temp2) = split /\s+/,$temp2,4; + unless ($temp1 =~ /\//) { + next; + } + $temp1 =~ s/^\///; + $libhash{$temp1}=1; + } +} + +sub mkinitrd_dracut { + my ($mode) = @_; # the mode is for statelite or stateless + my $dracutmpath = "$rootimg_dir/usr/share/dracut/modules.d/97xcat"; + mkpath($dracutmpath); + + my $perm = (stat("$fullpath/$dracutdir/check"))[2]; + cp("$fullpath/$dracutdir/check", $dracutmpath); + chmod($perm&07777, "$dracutmpath/check"); + + foreach (@ndrivers) { s/\.ko$//; } + + my $add_drivers = join(' ', @ndrivers); + my $DRACUTCONF; + + if ($mode eq "statelite") { + # for statelite + cp("$fullpath/$dracutdir/install.statelite","$dracutmpath/install"); + $perm = (stat("$fullpath/$dracutdir/install.statelite"))[2]; + chmod($perm&07777, "$dracutmpath/install"); + + cp("$fullpath/$dracutdir/xcat-prepivot.sh",$dracutmpath); + $perm = (stat("$fullpath/$dracutdir/xcat-prepivot.sh"))[2]; + chmod($perm&07777, "$dracutmpath/xcat-prepivot.sh"); + + # update etc/dracut.conf + open($DRACUTCONF, '>', "$rootimg_dir/etc/dracut.conf"); + print $DRACUTCONF qq{dracutmodules+="xcat nfs base network kernel-modules"\n}; + print $DRACUTCONF qq{add_drivers+="$add_drivers"\n}; + print $DRACUTCONF qq{filesystems+="nfs"\n}; + close $DRACUTCONF; + } elsif ($mode eq "stateless") { + cp("$fullpath/$dracutdir/install.netboot","$dracutmpath/install"); + $perm = (stat("$fullpath/$dracutdir/install.netboot"))[2]; + chmod($perm&07777, "$dracutmpath/install"); + + cp("$fullpath/$dracutdir/xcat-cmdline.sh","$dracutmpath/"); + $perm = (stat("$fullpath/$dracutdir/xcat-cmdline.sh"))[2]; + chmod($perm&07777, "$dracutmpath/xcat-cmdline.sh"); + + if ($prinic) { + my $optspec; + open($optspec,'>>',"$dracutmpath/xcat-cmdline.sh"); + print $optspec "PRINIC=$prinic\n"; + close $optspec; + } + + cp("$fullpath/$dracutdir/xcatroot","$dracutmpath/"); + $perm = (stat("$fullpath/$dracutdir/xcatroot"))[2]; + chmod($perm&07777, "$dracutmpath/xcatroot"); + + cp("$fullpath/$dracutdir/installkernel", "$dracutmpath/"); + $perm = (stat("$fullpath/$dracutdir/installkernel"))[2]; + chmod($perm&07777, "$dracutmpath/installkernel"); + + # update etc/dracut.conf + open($DRACUTCONF, '>', "$rootimg_dir/etc/dracut.conf"); + print $DRACUTCONF qq{dracutmodules+="xcat nfs base network kernel-modules"\n}; + print $DRACUTCONF qq{add_drivers+="$add_drivers"\n}; + close $DRACUTCONF; + } else { + xdie "the mode: $mode is not supported by genimage"; + } + + system("chroot $rootimg_dir dracut -f /tmp/initrd.$$.gz $kernelver"); + print "the initial ramdisk for $mode is generated successfully.\n"; + move("$rootimg_dir/tmp/initrd.$$.gz", "$destdir/initrd-$mode.gz"); +} + +sub mkinitrd { + my ($mode) = @_; # statelite or stateless + + if($mode eq "statelite") { + push @ndrivers, "fscache.ko"; + push @ndrivers, "sunrpc.ko"; + push @ndrivers, "lockd.ko"; + push @ndrivers, "nfs_acl.ko"; + push @ndrivers, "nfs.ko"; + + # Additional modules needed on s390x + if ($arch eq "s390x") { + # The network drivers need to be loaded in this order + unshift @ndrivers, "ccwgroup.ko"; + unshift @ndrivers, "qdio.ko"; + } + } + + mkpath("/tmp/xcatinitrd.$$/bin"); + + symlink("bin","/tmp/xcatinitrd.$$/sbin"); + mkpath("/tmp/xcatinitrd.$$/usr/bin"); + mkpath("/tmp/xcatinitrd.$$/usr/sbin"); + mkpath("/tmp/xcatinitrd.$$/usr/lib"); + mkpath("/tmp/xcatinitrd.$$/usr/lib64"); + mkpath("/tmp/xcatinitrd.$$/lib/firmware"); + mkpath("/tmp/xcatinitrd.$$/lib64/firmware"); + mkpath("/tmp/xcatinitrd.$$/proc"); + mkpath("/tmp/xcatinitrd.$$/sys"); + mkpath("/tmp/xcatinitrd.$$/dev/mapper"); + mkpath("/tmp/xcatinitrd.$$/sysroot"); + mkpath("/tmp/xcatinitrd.$$/etc/ld.so.conf.d"); + mkpath("/tmp/xcatinitrd.$$/etc/udhcpc"); + mkpath("/tmp/xcatinitrd.$$/usr/share/udhcpc"); + mkpath("/tmp/xcatinitrd.$$/var/lib/dhclient"); + my $inifile; + +# start writing to the init script. + open($inifile,">","/tmp/xcatinitrd.$$/init"); + print $inifile "#!/bin/busybox sh\n"; + +# add some functions + print $inifile < <\\ \\____/ | \\ | + /__/\\_ \\\\______ /\\____|__ /____| + \\/ \\/ \\/ +' + echo -e "\$RESET" +} + +EOS1 + + + print $inifile "busybox mount -t proc /proc /proc\n"; + print $inifile "busybox --install\n"; + print $inifile "mount -t sysfs /sys /sys\n"; + print $inifile "mount -o mode=0755 -t tmpfs /dev /dev\n"; + print $inifile "mkdir /dev/pts\n"; + print $inifile "mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts\n"; + print $inifile "mkdir /dev/shm\n"; + print $inifile "mkdir /dev/mapper\n"; + print $inifile "mknod /dev/null c 1 3\n"; + print $inifile "mknod /dev/zero c 1 5\n"; + print $inifile "mknod /dev/systty c 4 0\n"; + print $inifile "mknod /dev/tty c 5 0\n"; + print $inifile "mknod /dev/console c 5 1\n"; + print $inifile "mknod /dev/ptmx c 5 2\n"; + print $inifile "mknod /dev/rtc c 10 135\n"; + print $inifile "mknod /dev/tty0 c 4 0\n"; + print $inifile "mknod /dev/tty1 c 4 1\n"; + print $inifile "mknod /dev/tty2 c 4 2\n"; + print $inifile "mknod /dev/tty3 c 4 3\n"; + print $inifile "mknod /dev/tty4 c 4 4\n"; + print $inifile "mknod /dev/tty5 c 4 5\n"; + print $inifile "mknod /dev/tty6 c 4 6\n"; + print $inifile "mknod /dev/tty7 c 4 7\n"; + print $inifile "mknod /dev/tty8 c 4 8\n"; + print $inifile "mknod /dev/tty9 c 4 9\n"; + print $inifile "mknod /dev/tty10 c 4 10\n"; + print $inifile "mknod /dev/tty11 c 4 11\n"; + print $inifile "mknod /dev/tty12 c 4 12\n"; + print $inifile "mknod /dev/ttyS0 c 4 64\n"; + print $inifile "mknod /dev/ttyS1 c 4 65\n"; + print $inifile "mknod /dev/ttyS2 c 4 66\n"; + print $inifile "mknod /dev/ttyS3 c 4 67\n"; + + foreach (@ndrivers) { + print $inifile "insmod /lib/$_\n"; + } + + +# Start udev on s390x +if ($arch eq "s390x") { + print $inifile < /etc/sysconfig/network + +echo "ONBOOT=yes" > /etc/sysconfig/network-scripts/ifcfg-$prinic +echo "BOOTPROTO=dhcp" >> /etc/sysconfig/network-scripts/ifcfg-$prinic +echo "DEVICE=$prinic" >> /etc/sysconfig/network-scripts/ifcfg-$prinic +echo 'OPTIONS="layer2=1"' >> /etc/sysconfig/network-scripts/ifcfg-$prinic +echo "SUBCHANNELS=$subchn" >> /etc/sysconfig/network-scripts/ifcfg-$prinic + +# Turn on network devices +echo $subchn > /sys/bus/ccwgroup/drivers/qeth/group +echo 1 > /sys/bus/ccwgroup/drivers/qeth/$readChn/layer2 +echo 1 > /sys/bus/ccwgroup/drivers/qeth/$readChn/online +echo "alias $prinic qeth" >> /etc/modprobe.conf +echo `ifup $prinic` +sleep 4 +EOMS +} + + print $inifile < /dev/null && export DEBUG=1 + +# check the kernel parameter at first + +# if one parameter for the booting device is there, we will use it +# TODO +# ( netdevice is recognized by SLES, ) +# ( Dracut has one "network" module to handle the booting network devices, which use "ifname" ) +# ( What should the other redhat versions use ? netdev= and BOOTIF= ) + +# besides this action, the following code is also used to get the XCAT= value, which is for XCAT server +# TODO: does "anaconda.busybox sh" support "set " ? + +PRINIC=$prinic + +for i in `cat /proc/cmdline`; do + KEY=`echo \$i |awk -F= '{print \$1}'` + if [ "\$KEY" == 'netdev' ]; then + NETDEV=`echo \$i |awk -F= '{print \$2}'` + elif [ "\$KEY" == 'BOOTIF' ]; then + VALUE=`echo \$i |awk -F= '{print \$2}'|sed -e s/^01-// -e s/-/:/g` + BOOTIF=`ifconfig -a|grep -i "hwaddr \$VALUE"|awk '{print \$1}'` + elif [ "\$KEY" == 'XCAT' ]; then + VALUE=`echo \$i |awk -F= '{print \$2}'` + # format: XCAT=xcatmaster:3001 + XCATSERVER=\$VALUE + fi +done + +if [ -z "\$IFACE" ]; then + if [ ! -z "\$NETDEV" ]; then + IFACE=\$NETDEV + elif [ ! -z "\$BOOTIF" ]; then + IFACE=\$BOOTIF + elif [ ! -z "\$PRINIC" ]; then + IFACE=\$PRINIC + else + echo "\${RED}Couldn't find the proper booting device, switch to shell...\${RESET}" + shell + exit + fi +fi + +export IFACE=\$IFACE +echo network --device \$IFACE --bootproto dhcp >> /bin/netstart + +netstart \$IFACE +while ! ifconfig | grep inet; do + echo -e "\${RED}Failed to acquire address, retrying \${RESET}" + sleep 5 + netstart \$IFACE +done +ifconfig lo 127.0.0.1 +ifconfig lo up +cd / +for i in `cat /proc/cmdline`; do + KEY=`echo \$i |awk -F= '{print \$1}'` + if [ "\$KEY" == 'imgurl' ]; then + VALUE=`echo \$i |awk -F= '{print \$2}'` + if [ "http" == "`echo \$VALUE|awk -F: '{print \$1}'`" ]; then + #NOTE needs FT retry code to scale + #NOTE: should prob have max count + FILENAME=`echo \$VALUE|awk -F/ '{print \$NF}'` + while [ ! -r "\$FILENAME" ]; do + echo Getting \$VALUE... + if ! wget \$VALUE; then + ST=`expr \$RANDOM % 5` + sleep \$ST + rm -f \$FILENAME + fi + done + fi + if [ "nfs" == "`echo \$VALUE|awk -F: '{print \$1}'`" ]; then + NFS=1 + SERVER=`echo \$VALUE|awk -F/ '{print \$3}'` + ROOTDIR=`echo \$VALUE|awk -F/ '{for(i=4;i<=NF;i++) printf "/%s",\$i}'` + fi + # for NFS root + elif [ "\$KEY" == 'NFSROOT' ]; then + NFSROOT=1 + VALUE=`echo \$i |awk -F= '{print \$2}'` + SERVER=`echo \$VALUE|awk -F: '{print \$1}'` + ROOTDIR=`echo \$VALUE|awk -F/ '{for(i=2;i<=NF;i++) printf "/%s",\$i}'` + elif [ "\$KEY" == 'STATEMNT' ]; then + STATELITE=1 + VALUE=`echo \$i |awk -F= '{print \$2}'` + # the VALUE may be null + if [ ! -z \$VALUE ]; then + SNAPSHOTSERVER=`echo \$VALUE|awk -F: '{print \$1}'` + SNAPSHOTROOT=`echo \$VALUE|awk -F/ '{for(i=2;i<=NF;i++) printf "/%s",\$i}'` + # may be that there is not server and just a directory. + if [ -z \$SNAPSHOTROOT ] + then + SNAPSHOTROOT=\$SNAPSHOTSERVER + SNAPSHOTSERVER= + fi + fi + fi +done + +# show xCAT logo +fancydisplay + + +echo 0 > /proc/sys/vm/zone_reclaim_mode #Avoid kernel bug + +# STATELITE code here: +if [ "\$STATELITE" = "1" ]; then + echo Setting up Statelite + # for loop back mouting capability! + mknod /dev/loop0 b 7 0 + mkdir -p \$NEWROOT + MAXTRIES=5 + ITER=0 + ME=`hostname` + if [ "\$NFSROOT" = "1" ]; then + while ! mount.nfs \${SERVER}:\${ROOTDIR}/rootimg \$NEWROOT -r -n -o nolock,rsize=32768,tcp,nfsvers=3,timeo=14; do + ITER=\$(expr \$ITER + 1) + if [ "\$ITER" == "\$MAXTRIES" ]; then + echo "You are dead. rpower \$ME boot to play again." + echo "Possible problems: +1. This initrd wasn't craeted for the statelite node? +2. Is DNS set up? Maybe that's why I can't mount \${SERVER}. +3. The nfs modules aren't set right in this initfs?" + shell + exit + fi + echo -e "\${RED}Could not mount \$SERVER:\$ROOTDIR on \$NEWROOT \$RESET" + RS=`expr \$RANDOM % 30` + echo -e "Trying again in \$RS seconds" + sleep \$RS + done + elif [ "\$NFS" = "1" ]; then + echo -e "\${RED}The \"imgurl=\" value should not be nfs-type if statelite mode is enabled \$RESET" + shell + exit + else + # for statelite mode on top of the ramdisk +EOMS + print $inifile "if [ -r /rootimg-statelite.gz ]; then\n"; + print $inifile "echo Setting up RAM-root tmpfs.\n"; + if ($rootlimit) { + print $inifile " mount -o size=$rootlimit,mode=755 -t tmpfs rootfs \$NEWROOT \n"; + } else { + print $inifile " mount -o mode=755 -t tmpfs rootfs \$NEWROOT\n"; + } + print $inifile </dev/null && shell + + echo 0x100 > /proc/sys/kernel/real-root-dev + export keep_old_ip=yes + mount -n --bind /dev/ \$NEWROOT/dev + + umount /sys + umount /proc + + cp /etc/hostname /sysroot/etc/hostname + cp /etc/resolv.conf /sysroot/etc/resolv.conf + + if ! exec /sbin/pivot_root -c /dev/console \$NEWROOT /sbin/init; then + echo "" + echo -e "\${RED}Couldn't pivot_root. Something must be wrong with the root image.\${RESET}" + shell + fi + +fi +# END NFSROOT/Statelite code + +if [ -r /rootimg.sfs ]; then + echo Setting up squashfs with ram overlay. + mknod /dev/loop0 b 7 0 + mkdir -p /ro + mkdir -p /rw + mount -t squashfs /rootimg.sfs /ro + mount -t tmpfs rw /rw + mount -t aufs -o dirs=/rw:/ro mergedroot \$NEWROOT + mkdir -p \$NEWROOT/ro + mkdir -p \$NEWROOT/rw + mount --move /ro \$NEWROOT/ro + mount --move /rw \$NEWROOT/rw +EOMS + print $inifile "elif [ -r /rootimg.gz ]; then\n"; + print $inifile "echo Setting up RAM-root tmpfs.\n"; + if ($rootlimit) { + print $inifile " mount -o size=$rootlimit,mode=755 -t tmpfs rootfs \$NEWROOT\n"; + } else { + print $inifile " mount -o mode=755 -t tmpfs rootfs \$NEWROOT\n"; + } + print $inifile " cd \$NEWROOT\n"; + print $inifile " echo -n \"Extracting root filesystem:\"\n"; + print $inifile " if [ -x /bin/cpio ]; then\n"; + print $inifile " zcat /rootimg.gz |/bin/cpio -idum\n"; + print $inifile " else\n"; + print $inifile " zcat /rootimg.gz |cpio -idum\n"; + print $inifile " fi\n"; + print $inifile " echo Done\n"; + print $inifile "else\n"; + print $inifile " echo -n Failed to download image, panicing in 5...\n"; + print $inifile " for i in 4 3 2 1 0; do\n"; + print $inifile " /bin/sleep 5\n"; + print $inifile " echo -n \$i...\n"; + print $inifile " done\n"; + print $inifile " echo\n"; + print $inifile <dev/console 2>&1"; + close($inifile); + + open($inifile,">"."/tmp/xcatinitrd.$$/bin/netstart"); + print $inifile "#!/sbin/sh\n"; + print $inifile "udhcpc -n -q -i $prinic\n"; + close($inifile); + + open($inifile,">"."/tmp/xcatinitrd.$$/usr/share/udhcpc/default.script"); + +print $inifile <<'EOF'; +#!/bin/sh + +# udhcpc script edited by Tim Riker + +[ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1 + +RESOLV_CONF="/etc/resolv.conf" +[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" +[ -n "$subnet" ] && NETMASK="netmask $subnet" + +case "$1" in + deconfig) + /sbin/ifconfig $interface 0.0.0.0 + ;; + + renew|bound) + /sbin/ifconfig $interface $ip $BROADCAST $NETMASK + + if [ -n "$hostname" ] ; then + hostname $hostname + echo $hostname > /etc/hostname + fi + + if [ -n "$router" ] ; then + echo "deleting routers" + while route del default gw 0.0.0.0 dev $interface ; do + : + done + + for i in $router ; do + route add default gw $i dev $interface + done + fi + + echo -n > $RESOLV_CONF + [ -n "$domain" ] && echo search $domain >> $RESOLV_CONF + for i in $dns ; do + echo adding dns $i + echo nameserver $i >> $RESOLV_CONF + done + ;; +esac + +exit 0 +EOF + + close($inifile); + chmod(0755,"/tmp/xcatinitrd.$$/usr/share/udhcpc/default.script"); + + chmod(0755,"/tmp/xcatinitrd.$$/init"); + chmod(0755,"/tmp/xcatinitrd.$$/bin/netstart"); + @filestoadd=(); + foreach (@ndrivers) { + if (-f "$customdir/$_") { + push @filestoadd,[$_,"lib/$_"]; + } elsif (-f "$pathtofiles/$_") { + push @filestoadd,[$_,"lib/$_"]; + } + } + # add rsync for statelite + foreach ("bin/busybox","bin/bash", "sbin/mount.nfs", "usr/bin/rsync", "sbin/insmod") { + getlibs($_); + push @filestoadd,$_; + } + + # Additional binaries needed for udev on s390x + if ($arch eq "s390x") { + foreach ("sbin/udevsettle", "sbin/udevtrigger", "sbin/udevd", "sbin/depmod") { + getlibs($_); + push @filestoadd,$_; + } + } + + if ($arch =~ /x86_64/) { + push @filestoadd,"lib64/libnss_dns.so.2"; + push @filestoadd,"lib64/libresolv.so.2"; + } else { + push @filestoadd,"lib/libnss_dns.so.2"; + } + push @filestoadd,keys %libhash; + + find(\&isnetdriver, <$rootimg_dir/lib/modules/$kernelver/*>); + + foreach (@filestoadd) { + if (ref($_)) { + #print "$_->[0], $_->[1]\n"; + my $srcpath = "$rootimg_dir/".$_->[0]; + if (-f "$customdir/".$_->[0]) { + $srcpath="$customdir/".$_->[0]; + } elsif (-f "$pathtofiles/".$_->[0]) { + $srcpath="$pathtofiles/".$_->[0]; + } + mkpath(dirname("/tmp/xcatinitrd.$$/".$_->[1])); + copy($srcpath,"/tmp/xcatinitrd.$$/".$_->[1]); + chmod 0755,"/tmp/xcatinitrd.$$/".$_->[1]; + } else { + #print "$_\n"; + my $srcpath = "$rootimg_dir/$_"; + if (-f "$customdir/$_") { + $srcpath = "$customdir/$_"; + } elsif (-f "$pathtofiles/$_") { + $srcpath = "$pathtofiles/$_"; + } + mkpath(dirname("/tmp/xcatinitrd.$$/$_")); + copy("$srcpath","/tmp/xcatinitrd.$$/$_"); + chmod 0755,"/tmp/xcatinitrd.$$/".$_; + } + } + + # Copy udev and network scripts into initrd for s390x, which also works for other platforms + # udev + system("mkdir -p /tmp/xcatinitrd.$$/etc/udev"); + system("cp -r $rootimg_dir/etc/udev/* /tmp/xcatinitrd.$$/etc/udev"); + system("mkdir -p /tmp/xcatinitrd.$$/lib/udev"); + system("cp -r $rootimg_dir/lib/udev/* /tmp/xcatinitrd.$$/lib/udev"); + system("mkdir -p /tmp/xcatinitrd.$$/proc/self"); + system("cp -r /proc/self/oom_adj /tmp/xcatinitrd.$$/proc/self"); + + # Network related scripts + #system("echo $kernelver\n"); + #system("mkdir -p /tmp/xcatinitrd.$$/sbin"); + #system("cp -r $rootimg_dir/sbin/* /tmp/xcatinitrd.$$/sbin"); + #system("mkdir -p /tmp/xcatinitrd.$$/lib/modules/$kernelver"); + #system("cp -r $rootimg_dir/lib/modules/$kernelver/modules.dep /tmp/xcatinitrd.$$/lib/modules/$kernelver/modules.dep"); + #system("mkdir -p /tmp/xcatinitrd.$$/etc/init.d"); + #system("cp -r $rootimg_dir/etc/init.d/* /tmp/xcatinitrd.$$/etc/init.d"); + #system("mkdir -p /tmp/xcatinitrd.$$/lib64"); + #system("cp -r $rootimg_dir/lib64/* /tmp/xcatinitrd.$$/lib64"); + #system("mkdir -p /tmp/xcatinitrd.$$/var/run/netreport"); + symlink("busybox","/tmp/xcatinitrd.$$/bin/pivot_root"); + + #copy("$rootimg_dir/lib/modules/*d","/tmp/xcatinitrd.$$/$_"); + system("cd /tmp/xcatinitrd.$$;find .|cpio -H newc -o|gzip -9 -c - > $destdir/initrd-$mode.gz"); + system("rm -rf /tmp/xcatinitrd.$$"); + +} + +sub isaptdir { + if ($File::Find::name =~ /\/Packages.gz$/) { + my $location = $File::Find::name; + $location =~ s/\/Packages.gz$//; + push @aptdirs,$location; + } +} + +sub isnetdriver { + foreach (@ndrivers) { + if ($File::Find::name =~ /\/$_/) { + my $filetoadd = $File::Find::name; + $filetoadd =~ s!$rootimg_dir/!!; + push @filestoadd,[$filetoadd,"lib/$_"]; + } + } +} + + + + + + + +sub postscripts { + generic_post(); + + # TODO: workaround for kdump on RHEL6 + # add one fake command: fsck.nfs + unless ( -x "$rootimg_dir/sbin/fsck.nfs" ) { + system("echo true > $rootimg_dir/sbin/fsck.nfs; chmod a+x $rootimg_dir/sbin/fsck.nfs"); + } + + + if( ! -d "$rootimg_dir/opt/xcat/") { + mkdir "$rootimg_dir/opt/xcat/"; + } + copy ("$installroot/postscripts/xcatdsklspost", "$rootimg_dir/opt/xcat/"); + chmod '0755', "$rootimg_dir/opt/xcat/xcatdsklspost"; +} + + +sub using_systemd { + my $os = shift; + if ($os =~ /fedora(\d+)/) { + if ($1 >= 15) { + return 1; + } + } + + return 0; +} + + +sub generic_post { #This function is meant to leave the image in a state approximating a normal install + my $cfgfile; + unlink("$rootimg_dir/dev/null"); + system("mknod $rootimg_dir/dev/null c 1 3"); + open($cfgfile,">","$rootimg_dir/etc/fstab"); + print $cfgfile "devpts /dev/pts devpts gid=5,mode=620 0 0\n"; + print $cfgfile "tmpfs /dev/shm tmpfs defaults 0 0\n"; + print $cfgfile "proc /proc proc defaults 0 0\n"; + print $cfgfile "sysfs /sys sysfs defaults 0 0\n"; + + if (!&using_systemd($osver)) { + if ($tmplimit) { + print $cfgfile "tmpfs /tmp tmpfs defaults,size=$tmplimit 0 2\n"; + print $cfgfile "tmpfs /var/tmp tmpfs defaults,size=$tmplimit 0 2\n"; + } else { + print $cfgfile "tmpfs /tmp tmpfs defaults,size=10m 0 2\n"; + print $cfgfile "tmpfs /var/tmp tmpfs defaults,size=10m 0 2\n"; + } + } + + my $rootfs_name=$profile."_".$arch; + print $cfgfile "$rootfs_name / tmpfs rw 0 1\n"; + + open($cfgfile,">","$rootimg_dir/etc/resolv.conf"); + print $cfgfile "#Dummy resolv.conf to make boot cleaner"; + close($cfgfile); + + # Create the ifcfg-x file for diskless node. But keep the ONBOOT=no + # to skip the break of nfs-based boot + if ($prinic) { + open($cfgfile,">","$rootimg_dir/etc/network/interfaces"); + print $cfgfile "auto $prinic\niface $prinic inet dhcp\n"; + close($cfgfile); + } + foreach (split /,/,$othernics) { + if (/^$/) { next; } + open($cfgfile,">>","$rootimg_dir/etc/network/interfaces"); + print $cfgfile "auto $_\niface $_ inet dhcp\n"; + close($cfgfile); + } + + # securetty not needed on s390x + if ($arch ne "s390x") { + open($cfgfile,">>","$rootimg_dir/etc/securetty"); + print $cfgfile "ttyS0\n"; + print $cfgfile "ttyS1\n"; + close($cfgfile); + } + + my @passwd; + open($cfgfile,"<","$rootimg_dir/etc/passwd"); + @passwd = <$cfgfile>; + close($cfgfile); + open($cfgfile,">","$rootimg_dir/etc/passwd"); + foreach (@passwd) { + if (/^root:/) { + s/^root:\*/root:x/ + } + print $cfgfile $_; + } + close($cfgfile); + foreach (<$rootimg_dir/etc/skel/.*>) { + if (basename($_) eq '.' or basename($_) eq '..') { + next; + } + copy $_,"$rootimg_dir/root/"; + } + unless ( -r <$rootimg_dir/etc/rc3.d/S??network>) { + symlink "/etc/init.d/networking","$rootimg_dir/etc/rc3.d/S10networking"; + } + + # gettyset is not found on s390x + if ($arch ne "s390x") { + if (!&using_systemd($osver)) { + open($cfgfile,">","$rootimg_dir/etc/init.d/gettyset"); + print $cfgfile "#!/bin/bash\n"; + print $cfgfile "for i in `cat /proc/cmdline`; do\n"; + print $cfgfile ' KEY=`echo $i|cut -d= -f 1`'."\n"; + print $cfgfile " if [ \"\$KEY\" == \"console\" -a \"\$i\" != \"console=tty0\" ]; then\n"; + print $cfgfile " VALUE=`echo \$i | cut -d= -f 2`\n"; + print $cfgfile " COTTY=`echo \$VALUE|cut -d, -f 1`\n"; + print $cfgfile " COSPEED=`echo \$VALUE|cut -d, -f 2|cut -dn -f 1`\n"; + print $cfgfile " if echo \$VALUE | grep n8r; then\n"; + print $cfgfile " FLOWFLAG=\"-h\"\n"; + print $cfgfile " fi\n"; + print $cfgfile " if [ -x /sbin/initctl ]; then\n"; # Upstart style + print $cfgfile " initctl emit --no-wait fedora.serial-console-available \$COTTY \$COSPEED\n"; + print $cfgfile " else\n"; + print $cfgfile " echo xco:2345:respawn:/sbin/agetty \$FLOWFLAG \$COTTY \$COSPEED xterm >> /etc/inittab\n"; + print $cfgfile " init q\n"; + print $cfgfile " fi\n"; + print $cfgfile " fi\n"; + print $cfgfile "done\n"; + + close($cfgfile); + + chmod(0755,"$rootimg_dir/etc/init.d/gettyset"); + system("cd $rootimg_dir/etc/rc3.d; ln -sf ../init.d/gettyset S60gettyset"); + } + + copy("$installroot/postscripts/xcatpostinit", "$rootimg_dir/etc/init.d/xcatpostinit"); + chmod(0755, "$rootimg_dir/etc/init.d/xcatpostinit"); + system("cd $rootimg_dir/etc/rc3.d; ln -sf ../init.d/xcatpostinit S61xcatpostinit"); + } +} + + +my $driver_name; +my $real_path; +sub get_path () +{ + if ($File::Find::name =~ /\/$driver_name/) { + $real_path = $File::Find::name; + } +} + +#load the driver update disk, and 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 = `find $installroot/driverdisk/$osver/$arch -type f`; + chomp(@dd_list); + + if (! @dd_list) { + return (); + } + + # Create the work space for initrd hack + my $dd_dir = mkdtemp("/tmp/ddtmpXXXXXXX"); + mkpath "$dd_dir/mnt"; + mkpath "$dd_dir/mods"; + + my @dd_drivers = (); #dirver name + + # Loading drivers from each Driver Disk + foreach my $dd (@dd_list) { + my $rc = system ("mount -o loop $dd $dd_dir/mnt"); + if ($rc) { + print "mount the Driver Disk $dd failed.\n"; + next; + } + + if (! (-f "$dd_dir/mnt/rhdd" || -f "$dd_dir/mnt/modinfo" + || -f "$dd_dir/mnt/modules.dep" || -f "$dd_dir/mnt/modules.cgz")) { + print "The Driver Disk $dd has not correct format.\n"; + system ("umount -f $dd_dir/mnt"); + next; + } + + # Load the modinfo + open($modinfo, "<", "$dd_dir/mnt/modinfo"); + my @modinfo_lines = <$modinfo>; + my $mod_ver = shift @modinfo_lines; + chomp($mod_ver); + if ($mod_ver !~ /^Version 0/) { + print "The Driver Disk $dd has unknown version.\n"; + system ("umount -f $dd_dir/mnt"); + next; + } + + foreach my $line (@modinfo_lines) { + if ($line !~ /^Version/ && $line =~ /^(\w+)/) { + chomp($line); + if ($line =~ /^\s*$/) { next; } + $line =~ s/$/\.ko/; + push @dd_drivers, $line; + } + } + close($modinfo); + + # Copy the firmware + if (-d "$dd_dir/mnt/firmware") { + system ("cp -rf $dd_dir/mnt/firmware $rootimg_dir/lib/firmware"); + } + + # Load the modules.cgz + system ("cd $dd_dir/mods; gunzip -c $dd_dir/mnt/modules.cgz |cpio -id"); + if (! -d "$rootimg_dir/lib/modules/$kernelver/kernel/drivers/driverdisk") { + mkpath "$rootimg_dir/lib/modules/$kernelver/kernel/drivers/driverdisk"; + } + + # Copy the drivers to the root image + my @drivers = `find $dd_dir/mods/$kernelver/$arch/ -type f`; + + foreach my $d (@drivers) { + chomp($d); + $driver_name = $d; + $driver_name =~ s/.*\///; + $real_path = ""; + find (\&get_path, <$rootimg_dir/lib/modules/$kernelver/*>); + if ($real_path eq "") { + system ("cp $d $rootimg_dir/lib/modules/$kernelver/kernel/drivers/driverdisk"); + } else { + system ("cp $d $real_path"); + } + } + + rmtree "$dd_dir/mods/*"; + + my $rc = system ("umount -f $dd_dir/mnt"); + if ($rc) { + print "umount the directory $dd_dir/mnt failed\n"; + exit 1; + } + } + + # Generate the dependency relationship + system ("chroot '$rootimg_dir' depmod $kernelver"); + + # Clean the env + rmtree "$dd_dir"; + + return @dd_drivers; +} + +sub mount_chroot { + my $rootimage_dir = shift; + mkdir("$rootimage_dir/install"); + system("mount -o bind /dev $rootimage_dir/dev"); + system("mount -o bind /proc $rootimage_dir/proc"); + system("mount -o bind /sys $rootimage_dir/sys"); + system("mount -o bind /install $rootimage_dir/install"); +} + +sub umount_chroot { + my $rootimage_dir = shift; + system("umount $rootimage_dir/dev"); + system("umount $rootimage_dir/proc"); + system("umount $rootimage_dir/sys"); + system("umount $rootimage_dir/install"); + rmdir("$rootimage_dir/install"); +} + +sub usage { + print 'Usage: genimage [ -i ] [ -n ] [-r ] -o -p -k [--permission ] [--interactive]'."\n"; + print " --permission only works with statelite mode\n"; + print "Examples:\n"; + print " genimage -i eth0 -n tg3 -o centos5.1 -p compute \n"; + print " genimage -i eth0 -r eth1,eth2 -n tg3,bnx2 -o centos5.1 -p compute --interactive\n"; + print " genimage -i eth0 -n igb,e1000e,e1000,bnx2,tg3 -o centos5.4 -p nfsroot\n"; + print " genimage -i eth0 -n igb,e1000e,e1000,bnx2,tg3 -o centos5.4 -p nfsroot --permission 777\n"; + + return 0; +} + +