git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@10359 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			358 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			358 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| package xCAT_plugin::genimage;
 | |
| BEGIN
 | |
| {
 | |
|     $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | |
| }
 | |
| use lib "$::XCATROOT/lib/perl";
 | |
| use xCAT::Utils;
 | |
| use xCAT::SvrUtils;
 | |
| use xCAT::Table;
 | |
| use Data::Dumper;
 | |
| use File::Path;
 | |
| use Getopt::Long;
 | |
| Getopt::Long::Configure("bundling");
 | |
| Getopt::Long::Configure("pass_through");
 | |
| 
 | |
| my $prinic; #TODO be flexible on node primary nic
 | |
| my $othernics; #TODO be flexible on node primary nic
 | |
| my $netdriver;
 | |
| my $arch;
 | |
| my $profile;
 | |
| my $osver;
 | |
| my $rootlimit;
 | |
| my $tmplimit;
 | |
| my $installroot = "/install";
 | |
| my $kerneldir;
 | |
| my $kernelver = ""; 
 | |
| my $imagename;
 | |
| my $pkglist;
 | |
| my $srcdir;
 | |
| my $destdir;
 | |
| my $srcdir_otherpkgs;
 | |
| my $otherpkglist;
 | |
| my $postinstall_filename;
 | |
| my $rootimg_dir;
 | |
| my $mode;
 | |
| my $permission; #the permission works only for statelite mode currently
 | |
| my $krpmver;
 | |
| my $kerneldir;
 | |
| my $mode;
 | |
| 
 | |
| 
 | |
| 
 | |
| sub handled_commands {
 | |
|      return {
 | |
|             genimage => "genimage",
 | |
|    }
 | |
| }
 | |
| 
 | |
| sub process_request {
 | |
|    my $request = shift;
 | |
|    my $callback = shift;
 | |
|    my $doreq = shift;
 | |
|    my $installroot = xCAT::Utils->getInstallDir();
 | |
| 
 | |
|    @ARGV = @{$request->{arg}};
 | |
| 
 | |
|    #my $rsp;
 | |
|    #$rsp->{data}->[0]="genimage plugin gets called with ARGV=@ARGV" ;
 | |
|    #$callback->($rsp);
 | |
| 
 | |
|    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,
 | |
|        'g=s' => \$krpmver,
 | |
|        'm=s' => \$mode,
 | |
|        'kerneldir=s' => \$kerneldir,   
 | |
|        'permission=s' => \$permission
 | |
|        );
 | |
| 
 | |
|    my $osimagetab;
 | |
|    my $linuximagetab;
 | |
|    my $ref_linuximage_tab;
 | |
|    my $ref_osimage_tab;
 | |
|    my %keyhash = ();
 | |
|    my %updates_os = ();    # the hash for updating osimage table
 | |
|    my %updates_linux = (); # the hash for updating linuximage table
 | |
| 
 | |
|    #always save the input values to the db
 | |
|    if ($arch)    { $updates_os{'osarch'}=$arch; }
 | |
|    if ($profile) { $updates_os{'profile'} = $profile; }
 | |
|    if ($osver)    { $updates_os{'osvers'} = $osver; }
 | |
| 
 | |
|    if ($netdriver) { $updates_linux{'netdrivers'} = $netdriver; }
 | |
|    if ($prinic)    { $updates_linux{'nodebootif'} = $prinic; }
 | |
|    if ($othernics) { $updates_linux{'otherifce'} = $othernics; }
 | |
|    if ($kernelver) { $updates_linux{'kernelver'} = $kernelver; }
 | |
|    if ($krpmver)   { $updates_linux{'krpmver'} = $krpmver; }
 | |
|    if ($kerneldir) { $updates_linux{'kerneldir'} = $kerneldir; }  
 | |
|    if ($permission){ $updates_linux{'permission'} = $permission; }
 | |
| 
 | |
|     # get the info from the osimage and linuximage table
 | |
|     $osimagetab = xCAT::Table->new('osimage', -create=>1);
 | |
|     unless ($osimagetab) {
 | |
| 	$callback->({error=>["The osimage table cannot be open."],errorcode=>[1]});
 | |
|         return 1;
 | |
|     }
 | |
|     
 | |
|     $linuximagetab = xCAT::Table->new('linuximage', -create=>1);
 | |
|     unless($linuximagetab) {
 | |
| 	$callback->({error=>["The linuximage table cannot be open."],errorcode=>[1]});
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|    
 | |
| 
 | |
|    if (@ARGV > 0) {
 | |
|        $imagename=$ARGV[0];
 | |
|        if ($arch or $osver or $profile) {
 | |
| 	   $callback->({error=>["-o, -p and -a options are not allowed when a image name is specified."],errorcode=>[1]});
 | |
| 	   return 1;
 | |
|        }
 | |
|        
 | |
|        (my $ref_osimage_tab) = $osimagetab->getAttribs({imagename => $imagename}, 'osvers', 'osarch', 'profile', 'provmethod');
 | |
|        unless ($ref_osimage_tab) {
 | |
| 	   $callback->({error=>["Cannot find image \'$imagename\' from the osimage table."],errorcode=>[1]});	   
 | |
| 	   return 1;
 | |
|        }
 | |
|        
 | |
|        (my $ref_linuximage_tab) = $linuximagetab->getAttribs({imagename => $imagename}, 'pkglist', 'pkgdir', 'otherpkglist', 'otherpkgdir', 'postinstall', 'rootimgdir', 'kerneldir', 'krpmver', 'nodebootif', 'otherifce', 'kernelver', 'netdrivers', 'permission');
 | |
|        unless ($ref_linuximage_tab) {
 | |
| 	   $callback->({error=>["Cannot find $imagename from the linuximage table."],errorcode=>[1]});
 | |
| 	   return 1;
 | |
|        }
 | |
|        
 | |
|        $osver=$ref_osimage_tab->{'osvers'};
 | |
|        $arch=$ref_osimage_tab->{'osarch'};
 | |
|        $profile=$ref_osimage_tab->{'profile'};
 | |
|        my $provmethod=$ref_osimage_tab->{'provmethod'}; # TODO: not necessary, and need to update both statelite and stateless modes
 | |
|        
 | |
|        unless ($osver and $arch and $profile and $provmethod) {
 | |
| 	   $callback->({error=>["osimage.osvers, osimage.osarch, osimage.profile and osimage.provmethod must be specified for the image $imagename in the database."],errorcode=>[1]});
 | |
| 	   return 1;
 | |
|        }
 | |
|        
 | |
|        unless ($provmethod eq 'netboot' || $provmethod eq 'statelite') {
 | |
| 	   $callback->({error=>["\'$imagename\' cannot be used to build diskless image. Make sure osimage.provmethod is 'netboot'."],errorcode=>[1]});
 | |
| 	   return 1;
 | |
|        }
 | |
|        
 | |
|        unless ( $ref_linuximage_tab->{'pkglist'}) {
 | |
| 	   $callback->({error=>["A .pkglist file must be specified for image \'$imagename\' in the linuximage table."],errorcode=>[1]});
 | |
| 	   return 1;
 | |
|        }
 | |
|        $pkglist = $ref_linuximage_tab->{'pkglist'};
 | |
|        
 | |
|        $srcdir = $ref_linuximage_tab->{'pkgdir'};
 | |
|        $srcdir_otherpkgs = $ref_linuximage_tab->{'otherpkgdir'};
 | |
|        $otherpkglist = $ref_linuximage_tab->{'otherpkglist'};
 | |
|        $postinstall_filename = $ref_linuximage_tab->{'postinstall'};
 | |
|        $destdir = $ref_linuximage_tab->{'rootimgdir'};
 | |
|        
 | |
|        # 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
 | |
|        
 | |
|        if ($prinic) {
 | |
| 	   if ($prinic ne $ref_linuximage_tab->{'nodebootif'}) {
 | |
| 	        $callback->({info=>["The primary nic is different from the value in linuximage table, will update it."]});
 | |
| 		$updates{'nodebootif'} = $prinic;
 | |
| 	   }
 | |
|        } else {
 | |
| 	   $prinic = $ref_linuximage_tab->{'nodebootif'};
 | |
|        }
 | |
|        if ($othernics) {
 | |
| 	   if ($othernics ne $ref_linuximage_tab->{'otherifce'}) {
 | |
| 	       $callback->({info=>["The other ifces are different from  the value in linuximage table, will update it."]});
 | |
| 	       $updates{'otherifce'} = $othernics;
 | |
| 	   }
 | |
|        } else {
 | |
| 	   $othernics = $ref_linuximage_tab->{'otherifce'};
 | |
|        }
 | |
|        if ($kernelver) {
 | |
| 	   if ($kernelver ne $ref_linuximage_tab->{'kernelver'}) {
 | |
| 	       $callback->({info=>["The kernelver is different from the value in linuximage table, will update it."]});
 | |
| 	       $updates{'kernelver'} = $kernelver;
 | |
| 	   }
 | |
|        } else {
 | |
| 	   $kernelver = $ref_linuximage_tab->{'kernelver'};
 | |
|        }
 | |
|        
 | |
|        if ($krpmver) {
 | |
| 	   if ($krpmver ne $ref_linuximage_tab->{'krpmver'}) {
 | |
| 	       $callback->({info=>["The krpmver is different from the value in linuximage table, will update it."]});
 | |
| 	       $updates{'krpmver'} = $krpmver;
 | |
| 	   }
 | |
|        } else {
 | |
| 	   $krpmver = $ref_linuximage_tab->{'krpmver'};
 | |
|        }
 | |
| 
 | |
|        if ($kerneldir) {
 | |
| 	   if ($kerneldir ne $ref_linuximage_tab->{'kerneldir'}) {
 | |
| 	       print "The kerneldir is different from the value in linuximage table, will update it\n";
 | |
| 	       $updates{'kerneldir'} = $kerneldir;
 | |
| 	   }
 | |
|        } else {
 | |
| 	   $kerneldir = $ref_linuximage_tab->{'kerneldir'};
 | |
|        }
 | |
|        if ($netdriver) {
 | |
| 	   if ($netdriver ne $ref_linuximage_tab->{'netdrivers'}) {
 | |
| 	       $callback->({info=>["The netdrivers is different from the value in linuximage table, will update it."]});
 | |
| 	       $updates{'netdrivers'} = $netdriver;
 | |
| 	   }
 | |
|        } else {
 | |
| 	   $netdriver = $ref_linuximage_tab->{'netdrivers'};
 | |
|        }
 | |
|        
 | |
|        if ($permission) {
 | |
| 	   if ($permission ne $ref_linuximage_tab->{'permission'}) {
 | |
| 	       $callback->({info=>["The permission is different from the value in linuximage table, will update it."]});
 | |
| 	       $updates{'permission'} = $permission;
 | |
| 	   }
 | |
|        } else {
 | |
| 	   $permission = $ref_linuximage_tab->{'permission'};
 | |
|        }
 | |
|     }
 | |
| 
 | |
|     
 | |
|    ### Get the Profile ####
 | |
|    my $osfamily = $osver;
 | |
|    $osfamily  =~ s/\d+//g;
 | |
|    $osfamily  =~ s/\.//g;
 | |
|    if($osfamily =~ /rh/){
 | |
|        $osfamily = "rh";
 | |
|    }
 | |
| 
 | |
|    # OS version on s390x can contain 'sp', e.g. sles11sp1
 | |
|    # If the $osfamily contains 'sles' and 'sp', the $osfamily = sles
 | |
|    if ($osfamily =~ /sles/ && $osfamily =~ /sp/) {
 | |
|        $osfamily = "sles";
 | |
|    }
 | |
| 
 | |
|    $osfamily =~ s/ //g;
 | |
| 
 | |
|    #-m flag is used only for ubuntu, debian and ferdora12, for others genimage will create
 | |
|    #initrd.gz for both netboot and statelite, no -m is needed.
 | |
|    if ($mode) {
 | |
|        if (($osfamily ne "ubuntu") && ($osfamily ne "debian") && ($osver !~ /fedora12/)) {
 | |
| 	   $mode="";
 | |
| 	   $callback->({error=>["-m flag is valid for Ubuntu, Debian and Fedora12 only."],errorcode=>[1]});
 | |
| 	   return 1;
 | |
|        }
 | |
|    }
 | |
| 
 | |
|    $profDir = "$::XCATROOT/share/xcat/netboot/$osfamily";
 | |
|    unless(-d $profDir){
 | |
|        $callback->({error=>["Unable to find genimage script in $profDir."],errorcode=>[1]});
 | |
|        return 1;
 | |
|    }
 | |
| 
 | |
|    if ($krpmver) {
 | |
|        if ($osfamily ne "sles") {
 | |
| 	   $krpmver="";
 | |
| 	   $callback->({error=>["-g flag is valid for Sles only."],errorcode=>[1]});
 | |
| 	   return 1;
 | |
|        }
 | |
|    }   
 | |
| 
 | |
|    my $cmd="cd $profDir; ./genimage";
 | |
|    if ($arch) { $cmd .= " -a $arch";}
 | |
|    if ($osver) { $cmd .= " -o $osver";}
 | |
|    if ($profile) { $cmd .= " -p $profile";}
 | |
| 
 | |
|    if ($netdriver) { $cmd .= " -n $netdriver";}
 | |
|    if ($prinic) { $cmd .= " -i $prinic";}
 | |
|    if ($othernics) { $cmd .= " -r $othernics";}
 | |
|    if ($rootlimit) { $cmd .= " -l $rootlimit";}
 | |
|    if ($tmplimit) { $cmd .= " -t $tmplimit";}
 | |
|    if ($kernelver) { $cmd .= " -k $kernelver";}
 | |
|    if ($krpmver) { $cmd .= " -g $krpmver";}
 | |
|    if ($mode) { $cmd .= " -m $mode";}
 | |
|    if ($permission) { $cmd .= " --permission $permission"; }
 | |
|    if ($kerneldir) { $cmd .= " --kerneldir $kerneldir"; }
 | |
|    
 | |
|    $cmd.= " --internal";
 | |
|    if ($srcdir) { $cmd .= " --srcdir $srcdir";}
 | |
|    if ($pkglist) { $cmd .= " --pkglist $pkglist";}
 | |
|    if ($srcdir_otherpkgs) { $cmd .= " --otherpkgdir $srcdir_otherpkgs"; }
 | |
|    if ($otherpkglist) { $cmd .= " --otherpkglist $otherpkglist"; }  
 | |
|    if ($postinstall_filename)  { $cmd .= " --postinstall $postinstall_filename"; }
 | |
|    if ($destdir) { $cmd .= " --rootimgdir $destdir"; } 
 | |
| 
 | |
|    if ($imagename) {
 | |
|        $cmd.= " $imagename";
 | |
|    }
 | |
|    
 | |
|    # now run the specific genimage command
 | |
|    $callback->({info=>["$cmd"]});
 | |
|    $::CALLBACK=$callback;
 | |
|    #my $output = xCAT::Utils->runcmd("$cmd", 0, 1); # non-stream 
 | |
|    my $output = xCAT::Utils->runcmd("$cmd", 0, 1, 1); # stream output 
 | |
|    open(FILE, ">/tmp/genimageoutput");
 | |
|    foreach my $entry (@$output) {
 | |
|     print FILE $entry;
 | |
|     print FILE "\n";
 | |
|    }
 | |
|    close FILE; 
 | |
| 
 | |
|    #save the new settings to the osimage and linuximage tables
 | |
|    $cmd="cat /tmp/genimageoutput";
 | |
|    $output = xCAT::Utils->runcmd("$cmd", 0, 1); 
 | |
|    if ($output && (@$output > 0)) {
 | |
|        my $i=0;
 | |
|        while ($i < @$output) {
 | |
| 	   if ( $output->[$i] =~ /The output for table updates starts here/) {
 | |
| 	       #print "----got here $i\n";
 | |
|                my $tn;
 | |
|                my %keyhash;
 | |
|                my %updates;
 | |
| 	       my $s1=$output->[$i +1];
 | |
|                my $s2=$output->[$i +2];
 | |
|                my $s3=$output->[$i +3];
 | |
|                if ($s1 =~ /^table::(.*)$/) {
 | |
| 		   $tn=$1;
 | |
| 	       }              
 | |
|                if ($s2 =~ /^imagename::(.*)$/) {
 | |
| 		   $keyhash{'imagename'} = $1;
 | |
| 	       }    
 | |
| 
 | |
| 	       if ($tn eq 'osimage') {
 | |
| 		   %updates=%updates_os;
 | |
| 	       } elsif ($tn eq 'linuximage') {
 | |
| 		   %updates=%updates_linux;
 | |
| 	       }
 | |
| 
 | |
| 	       my @a=split("::", $s3);
 | |
| 	       for (my $j=0; $j < @a; $j=$j+2) {
 | |
| 		   $updates{$a[$j]} = $a[$j+1];
 | |
| 	       }
 | |
| 	       splice(@$output, $i, 5);
 | |
| 	       if (($tn) && (keys(%keyhash) > 0) && (keys(%updates) > 0)) {
 | |
| 		   my $tab= xCAT::Table->new($tn, -create=>1);
 | |
| 		   if ($tab) {
 | |
| 		      $tab->setAttribs(\%keyhash, \%updates); 
 | |
| 		      #print "table=$tn,%keyhash,%updates\n";
 | |
| 		      #print Dumper(%keyhash);
 | |
| 		      #print Dumper(%updates);
 | |
| 		   }
 | |
| 	       }
 | |
| 	   } else {
 | |
| 	       $i++;
 | |
| 	   }
 | |
|        } 
 | |
|        # remove tmp file
 | |
|        #`rm /tmp/genimageoutput`; 
 | |
|        #remove the database upgrade section
 | |
|        # runcmd_S displays the output
 | |
|        #$callback->({info=>$output}); 
 | |
|    }
 | |
| }
 | |
| 
 | |
| 1;
 |