git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@14012 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			1617 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			1617 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| #!/usr/bin/perl
 | |
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | |
| 
 | |
| package xCAT::Template;
 | |
| use strict;
 | |
| use xCAT::Table;
 | |
| use File::Basename;
 | |
| use File::Path;
 | |
| #use Data::Dumper;
 | |
| use Sys::Syslog;
 | |
| use xCAT::ADUtils; #to allow setting of one-time machine passwords
 | |
| use xCAT::Utils;
 | |
| use xCAT::TableUtils;
 | |
| use xCAT::NetworkUtils;
 | |
| BEGIN
 | |
| {
 | |
|       $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| my $netdnssupport = eval {
 | |
|     require Net::DNS;
 | |
|     1;
 | |
| };
 | |
| 
 | |
| my $tmplerr;
 | |
| my $table;
 | |
| my $key;
 | |
| my $field;
 | |
| my $idir;
 | |
| my $node;
 | |
| my %loggedrealms;
 | |
| my $lastmachinepass;
 | |
| my %tab_replacement=(
 | |
|      "noderes:nfsserver"=>"noderes:xcatmaster",
 | |
|      "noderes:tftpserver"=>"noderes:xcatmaster",
 | |
|     );
 | |
| 
 | |
| 
 | |
| 
 | |
| sub subvars { 
 | |
|   my $self = shift;
 | |
|   my $inf = shift;
 | |
|   my $outf = shift;
 | |
|   $tmplerr=undef; #clear tmplerr since we are starting fresh
 | |
|   $node = shift;
 | |
|   my $pkglistfile=shift;
 | |
|   my $media_dir = shift;
 | |
|   my $platform=shift;
 | |
|   my $partitionfile=shift;
 | |
|   my %namedargs = @_; #further expansion of this function will be named arguments, should have happened sooner.
 | |
|   unless ($namedargs{reusemachinepass}) {
 | |
| 	$lastmachinepass="";
 | |
|   }
 | |
| 
 | |
|   my $outh;
 | |
|   my $inh;
 | |
|   $idir = dirname($inf);
 | |
|   open($inh,"<",$inf);
 | |
|   unless ($inh) {
 | |
|     return "Unable to open $inf, aborting";
 | |
|   }
 | |
|   mkpath(dirname($outf));
 | |
|   open($outh,">",$outf);
 | |
|   unless($outh) {
 | |
|     return "Unable to open $outf for writing/creation, aborting";
 | |
|   }
 | |
|   my $inc;
 | |
|   #First load input into memory..
 | |
|   while (<$inh>) {
 | |
|     $inc.=$_;
 | |
|   }
 | |
|   close($inh);
 | |
|   my $master;
 | |
|   #my $sitetab = xCAT::Table->new('site');
 | |
|   my $noderestab = xCAT::Table->new('noderes');
 | |
|   #(my $et) = $sitetab->getAttribs({key=>"master"},'value');
 | |
|   my @masters = xCAT::TableUtils->get_site_attribute("master");
 | |
|   my $tmp = $masters[0];
 | |
|   if ( defined($tmp) ) {
 | |
|       $master = $tmp;
 | |
|   }
 | |
|   my $ipfn = xCAT::NetworkUtils->my_ip_facing($node);
 | |
|   if ($ipfn) {
 | |
|       $master = $ipfn;
 | |
|   }
 | |
|   my $et = $noderestab->getNodeAttribs($node,['xcatmaster']);
 | |
|   if ($et and $et->{'xcatmaster'}) { 
 | |
|     $master = $et->{'xcatmaster'};
 | |
|   }
 | |
|   unless ($master) {
 | |
|       die "Unable to identify master for $node";
 | |
|   }
 | |
|   $ENV{XCATMASTER}=$master;
 | |
| 
 | |
|   my @nodestatus = xCAT::TableUtils->get_site_attribute("nodestatus");
 | |
|   my $tmp=$nodestatus[0];
 | |
|   if( defined($tmp)  ){
 | |
| 	$ENV{NODESTATUS}=$tmp;
 | |
|   }
 | |
| 
 | |
|   #replace the env with the right value so that correct include files can be found
 | |
|   $inc =~ s/#ENV:([^#]+)#/envvar($1)/eg;
 | |
| 
 | |
|   if ($pkglistfile) {
 | |
|       #substitute the tag #INCLUDE_DEFAULT_PKGLIST# with package file name (for full install of  rh, centos,SL, esx fedora)
 | |
|       $inc =~ s/#INCLUDE_DEFAULT_PKGLIST#/#INCLUDE:$pkglistfile#/g;
 | |
|             
 | |
|       #substitute the tag #INCLUDE_DEFAULT_PKGLIST_S# with package file name (for full install of sles)
 | |
|       #substitute the tag #INCLUDE_DEFAULT_PERNLIST_S# with package file name (for full install sles
 | |
|       #substitute the tag #INCLUDE_DEFAULT_RMPKGLIST_S# with package file name (for full install sles)
 | |
|       $inc =~ s/#INCLUDE_DEFAULT_PKGLIST_S#/#INCLUDE_PKGLIST:$pkglistfile#/g;
 | |
|       $inc =~ s/#INCLUDE_DEFAULT_PTRNLIST_S#/#INCLUDE_PTRNLIST:$pkglistfile#/g;
 | |
|       $inc =~ s/#INCLUDE_DEFAULT_RMPKGLIST_S#/#INCLUDE_RMPKGLIST:$pkglistfile#/g;
 | |
|   }
 | |
| 
 | |
|   if (("ubuntu" eq $platform) || ("debian" eq $platform)) {
 | |
|     # since debian/ubuntu uses a preseed file instead of a kickstart file, pkglist
 | |
|     # must be included via simple string replacement instead of using includefile()
 | |
| 
 | |
|     # the first line of $pkglistfile is the space-delimited package list
 | |
|     # the additional lines are considered preseed directives and included as is
 | |
| 
 | |
|     if ($pkglistfile) {
 | |
|       # handle empty and non-empty $pkglistfile's
 | |
| 
 | |
|       if (open PKGLISTFILE, "<$pkglistfile") {
 | |
|         my $pkglist = '';
 | |
|         # append preseed directive lines
 | |
|         while (<PKGLISTFILE>) {
 | |
|           chomp $_;
 | |
|           $pkglist .= " " . $_;
 | |
|         }
 | |
| 
 | |
|         $inc =~ s/#INCLUDE_DEFAULT_PKGLIST_PRESEED#/$pkglist/g;
 | |
|         close PKGLISTFILE;
 | |
|       }
 | |
|     } else {
 | |
|       # handle no $pkglistfile
 | |
|       $inc =~ s/#INCLUDE_DEFAULT_PKGLIST_PRESEED#//g;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   #do *all* includes, recursive and all
 | |
|   my $doneincludes=0;
 | |
|   while (not $doneincludes) {
 | |
|     $doneincludes=1;
 | |
|     if ($inc =~ /#INCLUDE_PKGLIST:[^#^\n]+#/) {
 | |
|       $doneincludes=0;
 | |
|       $inc =~ s/#INCLUDE_PKGLIST:([^#^\n]+)#/includefile($1, 0, 1)/eg;
 | |
|     }
 | |
|     if ($inc =~ /#INCLUDE_PTRNLIST:[^#^\n]+#/) {
 | |
|       $doneincludes=0;
 | |
|       $inc =~ s/#INCLUDE_PTRNLIST:([^#^\n]+)#/includefile($1, 0, 2)/eg;
 | |
|     }
 | |
|     if ($inc =~ /#INCLUDE_RMPKGLIST:[^#^\n]+#/) {
 | |
|       $doneincludes=0;
 | |
|       $inc =~ s/#INCLUDE_RMPKGLIST:([^#^\n]+)#/includefile($1, 0, 3)/eg;
 | |
|     }
 | |
|     if ($inc =~ /#INCLUDE:[^#^\n]+#/) {
 | |
|       $doneincludes=0;
 | |
|       $inc =~ s/#INCLUDE:([^#^\n]+)#/includefile($1, 0, 0)/eg;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   #Support hierarchical include
 | |
|   $inc =~ s/#ENV:([^#]+)#/envvar($1)/eg;
 | |
|   if ($inc =~ /#INCLUDE:[^#^\n]+#/) {
 | |
|      $inc =~ s/#INCLUDE:([^#^\n]+)#/includefile($1, 0, 0)/eg;
 | |
|   }
 | |
| 
 | |
|   #ok, now do everything else..
 | |
|   $inc =~ s/#XCATVAR:([^#]+)#/envvar($1)/eg;
 | |
|   $inc =~ s/#ENV:([^#]+)#/envvar($1)/eg;
 | |
|   $inc =~ s/#MACHINEPASSWORD#/machinepassword()/eg;
 | |
|   $inc =~ s/#TABLE:([^:]+):([^:]+):([^#]+)#/tabdb($1,$2,$3)/eg;
 | |
|   $inc =~ s/#TABLEBLANKOKAY:([^:]+):([^:]+):([^#]+)#/tabdb($1,$2,$3,'1')/eg;
 | |
|   $inc =~ s/#CRYPT:([^:]+):([^:]+):([^#]+)#/crydb($1,$2,$3)/eg;
 | |
|   $inc =~ s/#COMMAND:([^#]+)#/command($1)/eg;
 | |
|   $inc =~ s/#KICKSTARTNET#/kickstartnetwork()/eg;
 | |
|   $inc =~ s/#ESXIPV6SETUP#/esxipv6setup()/eg;
 | |
|   $inc =~ s/#INCLUDE_NOP:([^#^\n]+)#/includefile($1,1,0)/eg;
 | |
|   $inc =~ s/#INCLUDE_PKGLIST:([^#^\n]+)#/includefile($1,0,1)/eg;
 | |
|   $inc =~ s/#INCLUDE_PTRNLIST:([^#^\n]+)#/includefile($1,0,2)/eg;
 | |
|   $inc =~ s/#INCLUDE_RMPKGLIST:([^#^\n]+)#/includefile($1,0,3)/eg;
 | |
|   $inc =~ s/#INCLUDE:([^#^\n]+)#/includefile($1, 0, 0)/eg;
 | |
|   $inc =~ s/#HOSTNAME#/$node/eg;
 | |
| 
 | |
|   my $nrtab = xCAT::Table->new("noderes");
 | |
|   my $tftpserver = $nrtab->getNodeAttribs($node, ['tftpserver']);
 | |
|   my $sles_sdk_media = "http://" . $tftpserver->{tftpserver} . $media_dir . "/sdk1";
 | |
|   
 | |
|   $inc =~ s/#SLES_SDK_MEDIA#/$sles_sdk_media/eg;
 | |
| 
 | |
|   #if user specify the partion file, replace the default partition strategy
 | |
|   if ($partitionfile){
 | |
|     #if the content of the partition file is definition replace the default is ok
 | |
|     my $partcontent = '';
 | |
|     my $scriptflag = 0;
 | |
| 
 | |
|     if ($partitionfile =~ /^s:(.*)/){
 | |
|         $scriptflag = 1;
 | |
|         $partitionfile = $1;
 | |
|     }
 | |
| 
 | |
|     if (-r $partitionfile){
 | |
|         open ($inh, "<", $partitionfile);
 | |
|         while (<$inh>){
 | |
|             $partcontent .= $_;
 | |
|         }
 | |
|         close ($inh);
 | |
| 
 | |
|         #the content of the specified file is a script which can write partition definition into /tmp/partitionfile
 | |
|         if ($scriptflag){
 | |
|             #for redhat/sl/centos/kvm/fedora
 | |
|             if ($inc =~ /#XCAT_PARTITION_START#/) {
 | |
|                 my $tempstr = "%inlcude /tmp/partitionfile\n";
 | |
|                 $inc =~ s/#XCAT_PARTITION_START#[\s\S]*#XCAT_PARTITION_END#/$tempstr/;
 | |
|                 #modify the content in the file, and write into %pre part
 | |
|                 $partcontent = "cat > /tmp/partscript << EOFEOF\n" . $partcontent . "\nEOFEOF\n";
 | |
|                 $partcontent .= "chmod 755 /tmp/partscript\n";
 | |
|                 $partcontent .= "/tmp/partscript\n";
 | |
|                 #replace the #XCA_PARTITION_SCRIPT#
 | |
|                 $inc =~ s/#XCA_PARTITION_SCRIPT#/$partcontent/;
 | |
|             }
 | |
|             #for sles/suse
 | |
|             elsif ($inc =~ /<!-- XCAT-PARTITION-START -->/){
 | |
|                 my $tempstr = "<drive><device>XCATPARTITIONTEMP</device></drive>";
 | |
|                 $inc =~ s/<!-- XCAT-PARTITION-START -->[\s\S]*<!-- XCAT-PARTITION-END -->/$tempstr/;
 | |
|                 $partcontent = "cat > /tmp/partscript << EOFEOF\n" . $partcontent . "\nEOFEOF\n";
 | |
|                 $partcontent .= "chmod 755 /tmp/partscript\n";
 | |
|                 $partcontent .= "/tmp/partscript\n";
 | |
|                 $inc =~ s/#XCA_PARTITION_SCRIPT#/$partcontent/;
 | |
|             }
 | |
|         }
 | |
|         else{
 | |
|             $partcontent =~ s/\s$//;
 | |
|             if ($inc =~ /#XCAT_PARTITION_START#/){
 | |
|                 $inc =~ s/#XCAT_PARTITION_START#[\s\S]*#XCAT_PARTITION_END#/$partcontent/;
 | |
|             }
 | |
|             elsif ($inc =~ /<!-- XCAT-PARTITION-START -->/){
 | |
|                 $inc =~ s/<!-- XCAT-PARTITION-START -->[\s\S]*<!-- XCAT-PARTITION-END -->/$partcontent/;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ($tmplerr) {
 | |
|      close ($outh);
 | |
|      return $tmplerr;
 | |
|    }
 | |
|   print $outh $inc;
 | |
|   close($outh);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| sub esxipv6setup {
 | |
|  if ($::XCATSITEVALS{managedaddressmode} ne "autoula") { return ""; } # blank unless autoula
 | |
| 	my $hoststab;
 | |
|       my $mactab = xCAT::Table->new('mac',-create=>0);
 | |
|       my $ent = $mactab->getNodeAttribs($node,['mac']);
 | |
|       my $suffix = $ent->{mac};
 | |
|       $suffix = lc($suffix);
 | |
|       unless ($mactab) { die "mac table should always exist prior to template processing when doing autoula"; }
 | |
|  #in autoula, because ESXi weasel doesn't seemingly grok IPv6 at all, we'll have to do it in %pre
 | |
| 		unless ($hoststab) { $hoststab = xCAT::Table->new('hosts',-create=>1); }
 | |
| 		my $ulaaddr = autoulaaddress($suffix);
 | |
| 		$hoststab->setNodeAttribs($node,{ip=>$ulaaddr});
 | |
|  return 'esxcfg-vmknic -i '.$ulaaddr.'/64 "Management Network"'."\n";
 | |
| }
 | |
| 
 | |
| sub kickstartnetwork {
 | |
| 	my $line = "network --onboot=yes --bootproto=";
 | |
| 	my $hoststab;
 | |
|       my $mactab = xCAT::Table->new('mac',-create=>0);
 | |
|       unless ($mactab) { die "mac table should always exist prior to template processing when doing autoula"; }
 | |
|       my $ent = $mactab->getNodeAttribs($node,['mac']);
 | |
|       unless ($ent and $ent->{mac}) { die "missing mac data for $node"; }
 | |
|       my $suffix = $ent->{mac};
 | |
|       $suffix = lc($suffix);
 | |
| 	if ($::XCATSITEVALS{managedaddressmode} eq "autoula") {
 | |
| 		unless ($hoststab) { $hoststab = xCAT::Table->new('hosts',-create=>1); }
 | |
| 		$line .= "static --device=$suffix --noipv4 --ipv6=";
 | |
| 		my $ulaaddr = autoulaaddress($suffix);
 | |
| 		$hoststab->setNodeAttribs($node,{ip=>$ulaaddr});
 | |
| 		$line .= $ulaaddr;
 | |
| 	} else {
 | |
| 		$line .= "dhcp --device=$suffix";
 | |
| 	}
 | |
| 	return $line;
 | |
| }
 | |
| sub autoulaaddress {
 | |
|       my $suffix = shift;
 | |
|       my $prefix = $::XCATSITEVALS{autoulaprefix};
 | |
|       $suffix =~ /(..):(..:..):(..:..):(..)/;
 | |
|       my $leadbyte = $1;
 | |
|       my $mask = ((hex($leadbyte) & 2) ^ 2);
 | |
|       if ($mask) {
 | |
|         $leadbyte = hex($leadbyte) | $mask;
 | |
|       } else {
 | |
|         $leadbyte = hex($leadbyte) & 0xfd; #mask out the one bit
 | |
|       }
 | |
|       $suffix = sprintf("%02x$2ff:fe$3$4",$leadbyte);
 | |
| 
 | |
|       return $prefix.$suffix;
 | |
| }
 | |
| 
 | |
| sub machinepassword {
 | |
|     if ($lastmachinepass) { #note, this should only happen after another call
 | |
| 			    #to subvars that does *not* request reuse
 | |
| 			    #the issue being avoiding reuse in the installmonitor case
 | |
| 			    #subvars function clears this if appropriate
 | |
| 	return $lastmachinepass;
 | |
|     }
 | |
|     my $domaintab = xCAT::Table->new('domain');
 | |
|     $ENV{HOME}='/etc/xcat';
 | |
|     $ENV{LDAPRC}='ad.ldaprc';
 | |
|     my $ou;
 | |
|     if ($domaintab) {
 | |
|         my $ouent = $domaintab->getNodeAttribs('node','ou');
 | |
|         if ($ouent and $ouent->{ou}) {
 | |
|             $ou = $ouent->{ou};
 | |
|         }
 | |
|     }
 | |
|     #my $sitetab = xCAT::Table->new('site');
 | |
|     #unless ($sitetab) {
 | |
|     #    return "ERROR: unable to open site table"; 
 | |
|     #}
 | |
|     my $domain;
 | |
|     #(my $et) = $sitetab->getAttribs({key=>"domain"},'value');
 | |
|     my @domains =  xCAT::TableUtils->get_site_attribute("domain");
 | |
|     my $tmp = $domains[0];
 | |
|     if (defined($tmp)) {
 | |
|         $domain = $tmp;
 | |
|     } else {
 | |
|         return "ERROR: no domain set in site table";
 | |
|     }
 | |
|     my $realm = uc($domain);
 | |
|     $realm =~ s/\.$//;
 | |
|     $realm =~ s/^\.//;
 | |
|     $ENV{KRB5CCNAME}="/tmp/xcat/krbcache.$realm.$$";
 | |
|     unless ($loggedrealms{$realm}) {
 | |
|         my $passtab = xCAT::Table->new('passwd',-create=>0);
 | |
|         unless ($passtab) { sendmsg([1,"Error authenticating to Active Directory"],$node); return; }
 | |
|         (my $adpent) = $passtab->getAttribs({key=>'activedirectory'},['username','password']);
 | |
|         unless ($adpent and $adpent->{username} and $adpent->{password}) {
 | |
|             return "ERROR: activedirectory entry missing from passwd table";
 | |
|         }
 | |
|         my $err = xCAT::ADUtils::krb_login(username=>$adpent->{username},password=>$adpent->{password},realm=>$realm);
 | |
|         if ($err) {
 | |
|             return "ERROR: authenticating to Active Directory";
 | |
|         }
 | |
|         $loggedrealms{$realm}=1;
 | |
|     }
 | |
|     #my $server = $sitetab->getAttribs({key=>'directoryserver'},['value']);
 | |
|     my $server;
 | |
|     my @servers = xCAT::TableUtils->get_site_attribute("directoryserver");
 | |
|     $tmp = $servers[0];
 | |
|     if (defined($tmp)) {
 | |
|         $server = $tmp;
 | |
|     } else {
 | |
|         $server = '';
 | |
|         if ($netdnssupport) {
 | |
|            my $res = Net::DNS::Resolver->new;
 | |
|            my $query = $res->query("_ldap._tcp.$domain","SRV");
 | |
|            if ($query) {
 | |
|                foreach my $srec ($query->answer) {
 | |
|                    $server = $srec->{target};
 | |
|                }
 | |
|            }
 | |
|         }
 | |
|         unless ($server) {
 | |
|             sendmsg([1,"Unable to determine a directory server to communicate with, try site.directoryserver"]);
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
|     my %args = (
 | |
|         node => $node,
 | |
|         dnsdomain => $domain,
 | |
|         directoryserver => $server,
 | |
|         changepassondupe => 1,
 | |
|     );
 | |
|     if ($ou) { $args{ou} = $ou };
 | |
|     my $data = xCAT::ADUtils::add_host_account(%args);
 | |
|     if ($data->{error}) { 
 | |
|         return "ERROR: ".$data->{error};
 | |
|     } else {
 | |
| 	$lastmachinepass=$data->{password};
 | |
|         return $data->{password};
 | |
|     }
 | |
| }
 | |
| sub includefile
 | |
| {
 | |
|     my $file = shift;
 | |
|     my $special=shift;
 | |
|     my $pkglist=shift; #1 means package list, 
 | |
|                        #2 means pattern list, pattern list starts with @, 
 | |
|                        #3 means remove package list, packages to be removed start with -.
 | |
|     my $text = "";
 | |
|     unless ($file =~ /^\//) {
 | |
|       $file = $idir."/".$file;
 | |
|     }
 | |
| 
 | |
|     open(INCLUDE,$file) || return "#INCLUDEBAD:cannot open $file#";
 | |
|     
 | |
|     my $pkgb = "";
 | |
|     my $pkge = "";
 | |
|     if ($pkglist) {
 | |
| 	if ($pkglist == 2) {
 | |
| 	    $pkgb = "<pattern>";
 | |
| 	    $pkge = "</pattern>";
 | |
| 	} else {
 | |
| 	    $pkgb = "<package>";
 | |
| 	    $pkge = "</package>";
 | |
| 	}
 | |
|     } 
 | |
|     while(<INCLUDE>) {
 | |
|         if ($pkglist == 1) {
 | |
|             s/#INCLUDE:/#INCLUDE_PKGLIST:/;
 | |
|         }  elsif ($pkglist == 2) {
 | |
|             s/#INCLUDE:/#INCLUDE_PTRNLIST:/;
 | |
|         }  elsif ($pkglist == 3) {
 | |
|             s/#INCLUDE:/#INCLUDE_RMPKGLIST:/;
 | |
|         }
 | |
| 
 | |
|         if (( $_ =~ /^\s*#/ ) || ( $_ =~ /^\s*$/ )) { 
 | |
| 	    $text .= "$_";
 | |
|         } else {
 | |
| 	    my $tmp=$_;
 | |
|             chomp($tmp);  #remove return char
 | |
|             $tmp =~ s/\s*$//;  #removes trailing spaces
 | |
| 	    next if (($pkglist == 1) && (($tmp=~/^\s*@/) || ($tmp=~/^\s*-/)));  #for packge list, do not include the lines start with @
 | |
| 	    if ($pkglist == 2) { #for pattern list, only include the lines start with @
 | |
| 		if ($tmp =~/^\s*@(.*)/) {
 | |
| 		    $tmp=$1;
 | |
| 		    $tmp =~s/^\s*//;  #removes leading spaces
 | |
| 		} else { next; }
 | |
| 	    } elsif ($pkglist == 3) { #for rmpkg list, only include the lines start with -
 | |
| 		if ($tmp =~/^\s*-(.*)/) {
 | |
| 		    $tmp=$1;
 | |
| 		    $tmp =~s/^\s*//;  #removes leading spaces
 | |
| 		} else { next; }
 | |
| 	    }
 | |
| 	    $text .= "$pkgb$tmp$pkge\n";
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     close(INCLUDE);
 | |
|     
 | |
|     if ($special) {
 | |
| 	$text =~ s/\$/\\\$/g;
 | |
| 	$text =~ s/`/\\`/g;
 | |
|     }
 | |
| 
 | |
|     chomp($text);
 | |
|     return($text);
 | |
| }
 | |
| 
 | |
| sub command
 | |
| {
 | |
| 	my $command = shift;
 | |
| 	my $r;
 | |
| 
 | |
| #	if(($r = `$command`) == 0) {
 | |
| #		chomp($r);
 | |
| #		return($r);
 | |
| #	}
 | |
| #	else {
 | |
| #		return("#$command: failed $r#");
 | |
| #	}
 | |
| 
 | |
| 	$r = `$command`;
 | |
| 	chomp($r);
 | |
| 	return($r);
 | |
| }
 | |
| 
 | |
| sub envvar
 | |
| {
 | |
| 	my $envvar = shift;
 | |
| 
 | |
| 	if($envvar =~ /^\$/) {
 | |
| 		$envvar =~ s/^\$//;
 | |
| 	}
 | |
| 
 | |
| 	return($ENV{$envvar});
 | |
| }
 | |
| 
 | |
| sub genpassword {
 | |
| #Generate a pseudo-random password of specified length
 | |
|     my $length = shift;
 | |
|     my $password='';
 | |
|     my $characters= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890';
 | |
|     srand; #have to reseed, rand is not rand otherwise
 | |
|     while (length($password) < $length) {
 | |
|         $password .= substr($characters,int(rand 63),1);
 | |
|     }
 | |
|     return $password;
 | |
| }
 | |
| 
 | |
| sub crydb
 | |
| {
 | |
|     my $result = tabdb(@_);
 | |
|     unless ($result =~ /^\$1\$/) {
 | |
|         $result = crypt($result,'$1$'.genpassword(8));
 | |
|     }
 | |
|     return $result;
 | |
| }
 | |
| sub tabdb
 | |
| {
 | |
| 	my $table = shift;
 | |
| 	my $key = shift;
 | |
| 	my $field = shift;
 | |
|    my $blankok = shift;
 | |
|     my $tabh = xCAT::Table->new($table);
 | |
|     unless ($tabh) {
 | |
|        $tmplerr="Unable to open table named $table";
 | |
|        if ($table =~ /\.tab/) {
 | |
|           $tmplerr .= " (.tab should not be specified as part of the table name in xCAT 2, as seems to be the case here)";
 | |
|        }
 | |
|       return "";
 | |
|     }
 | |
|     my $ent;
 | |
|     my $bynode=0;
 | |
|     if ($key eq "THISNODE" or $key eq '$NODE') {
 | |
|       $ent = $tabh->getNodeAttribs($node,[$field]);
 | |
|       $key="node=$node";
 | |
|     } else {
 | |
|       my %kp;
 | |
|       foreach (split /,/,$key) {
 | |
|         my $key;
 | |
|         my $val;
 | |
|         if ($_ eq 'THISNODE' or $_ eq '$NODE') {
 | |
|             $bynode=1;
 | |
|         } else {
 | |
|             ($key,$val) = split /=/,$_;
 | |
|             $kp{$key}=$val;
 | |
|         }
 | |
|       }
 | |
|       if ($bynode) {
 | |
|           my @ents = $tabh->getNodeAttribs($node,[keys %kp,$field]);
 | |
|           my $tent; #Temporary ent
 | |
|           TENT: foreach $tent (@ents) {
 | |
|               foreach (keys %kp) {
 | |
|                   unless ($kp{$_} eq $tent->{$_}) {
 | |
|                       next TENT;
 | |
|                   }
 | |
|               } #If still here, we found it
 | |
|              $ent = $tent;
 | |
|               
 | |
|           }
 | |
|       } else {
 | |
|           ($ent) = $tabh->getAttribs(\%kp,$field);
 | |
|       }
 | |
|     }
 | |
|     $tabh->close;
 | |
|     unless($ent and  defined($ent->{$field})) {
 | |
|       unless ($blankok) {
 | |
|          if ($field eq "xcatmaster") {
 | |
|            my $ipfn = xCAT::NetworkUtils->my_ip_facing($node);
 | |
|            if ($ipfn) {
 | |
|              return $ipfn;
 | |
|            }
 | |
|          }
 | |
|          #$tmplerr="Unable to find requested $field from $table, with $key";
 | |
|          my $rep=get_replacement($table,$key,$field);
 | |
|          if ($rep) {
 | |
|             return tabdb($rep->[0], $rep->[1], $rep->[2]);
 | |
|          } else {
 | |
|             $tmplerr="Unable to find requested $field from $table, with $key"
 | |
|          }
 | |
|       }
 | |
|       return "";
 | |
|       #return "#TABLEBAD:$table:field $field not found#";
 | |
|     }
 | |
|     return $ent->{$field};
 | |
| 
 | |
| 
 | |
| 	#if($key =~ /^\$/) {
 | |
| 	#	$key =~ s/^\$//;
 | |
| 	#	$key = $ENV{$key};
 | |
| 	#}
 | |
| 	#if($field =~ /^\$/) {
 | |
| 	#	$field =~ s/^\$//;
 | |
| 	#	$field = $ENV{$field};
 | |
| 	#}
 | |
| 	#if($field == '*') {
 | |
| 	#	$field = 1;
 | |
| 	#	$all = 1;
 | |
| 	#}
 | |
| 
 | |
| 	#--$field;
 | |
| 
 | |
| 	#if($field < 0) {
 | |
| 	#	return "#TABLE:field not found#"
 | |
| 	#}
 | |
| 
 | |
| 	#open(TAB,$table) || \
 | |
| 	#	return "#TABLE:cannot open $table#";
 | |
| 
 | |
| 	#while(<TAB>) {
 | |
| 	#	if(/^$key(\t|,| )/) {
 | |
| 	#		m/^$key(\t|,| )+(.*)/;
 | |
| 	#		if($all == 1) {
 | |
| 	#			return "$2";
 | |
| 	#		}
 | |
| 	#		@fields = split(',',$2);
 | |
| 	#		if(defined $fields[$field]) {
 | |
| 	#			return "$fields[$field]";
 | |
| 	#		}
 | |
| 	#		else {
 | |
| 	#			return "#TABLE:field not found#"
 | |
| 	#		}
 | |
| 	#	}
 | |
| 	#}
 | |
| 
 | |
| 	#close(TAB);
 | |
| 	#return "#TABLE:key not found#"
 | |
| }
 | |
| 
 | |
| sub get_replacement {
 | |
|     my $table=shift;
 | |
|     my $key=shift;
 | |
|     my $field=shift;
 | |
|     my $rep;
 | |
|     if (exists($tab_replacement{"$table:$field"})) {
 | |
| 	my $repstr=$tab_replacement{"$table:$field"};
 | |
| 	if ($repstr) {
 | |
| 	    my @a=split(':', $repstr);
 | |
| 	    if (@a > 2) {
 | |
| 		$rep=\@a;
 | |
| 	    } else {
 | |
| 		$rep->[0]=$a[0];
 | |
|                 $rep->[1]=$key;
 | |
|                 $rep->[2]=$a[1];
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     return $rep;
 | |
| }
 | |
| 
 | |
| 
 | |
| my $os;
 | |
| my $profile;
 | |
| my $arch;
 | |
| my $provmethod;
 | |
| my $nodesetstate;
 | |
| sub subvars_for_mypostscript { 
 | |
|   my $self         = shift;
 | |
|   my $nodes        = shift;
 | |
|   $nodesetstate    = shift;
 | |
|   my $callback     = shift;
 | |
|   #my $tmpl          = shift;  #tmplfile  default: "/opt/xcat/share/xcat/templates/mypostscript/mypostscript.tmpl" customized: /install/postscripts/mypostscript.tmpl 
 | |
|   $tmplerr=undef; #clear tmplerr since we are starting fresh
 | |
|   my %namedargs = @_; #further expansion of this function will be named arguments, should have happened sooner.
 | |
| 
 | |
|   my $installroot =
 | |
|   my @entries =  xCAT::TableUtils->get_site_attribute("installdir"); 
 | |
|   if($entries[0]) {
 | |
|        $installroot = $entries[0];
 | |
|   }
 | |
|   my $tmpl="$installroot/postscripts/mypostscript.tmpl";
 | |
|     
 | |
|   unless ( -r $tmpl) {
 | |
|        $tmpl="$::XCATROOT/share/xcat/templates/mypostscript/mypostscript.tmpl";
 | |
|   }
 | |
|     
 | |
|   unless ( -r "$tmpl") {
 | |
|        $callback->(
 | |
|        {
 | |
|              error => [
 | |
|                            "site.precreatemypostscripts is set to 1 or yes. But No mypostscript template exists"
 | |
|                             . " in directory $installroot/install/postscripts or $::XCATROOT/share/xcat/templates/mypostscript/mypostscript.tmpl"
 | |
|                        ],
 | |
|               errorcode => [1]
 | |
|            }
 | |
|          );
 | |
|        return;
 | |
|   }
 | |
| 
 | |
|   my $outh;
 | |
|   my $inh;
 | |
|   $idir = dirname($tmpl);
 | |
|   open($inh,"<",$tmpl);
 | |
|   unless ($inh) {
 | |
|      my $rsp;
 | |
|      $rsp->{errorcode}->[0]=1;
 | |
|      $rsp->{error}->[0]="Unable to open $tmpl, aborting\n";
 | |
|      $callback->($rsp);
 | |
|      return;
 | |
|   }
 | |
| 
 | |
|   my $inc;
 | |
|   my $t_inc;
 | |
|   #First load input into memory..
 | |
|   while (<$inh>) {
 | |
|       $t_inc.=$_;
 | |
|   }
 | |
| 
 | |
|   close($inh);
 | |
| 
 | |
| 
 | |
|   my %script_fp;    
 | |
|   my $allattribsfromsitetable;
 | |
| 
 | |
|   # read all attributes for the site table and write an export   
 | |
|   # only run this function once for one command with noderange
 | |
|   $allattribsfromsitetable = getAllAttribsFromSiteTab();
 | |
| 
 | |
|   my $masterhash = getMasters($nodes);
 | |
|   
 | |
|   ## os, arch, profile, provemethod
 | |
|   my $typehash = getTypeVars($nodes, $callback);
 | |
|   if( !defined($typehash)) { 
 | |
|      return;
 | |
|   }
 | |
| 
 | |
|   ## nfsserver,installnic,primarynic
 | |
|   my $attribsfromnoderes = getNoderes($nodes);
 | |
| 
 | |
|   foreach my $n (@$nodes ) {
 | |
|       $node = $n; 
 | |
|       $inc = $t_inc;
 | |
|       my $tftpdir = xCAT::TableUtils::getTftpDir();
 | |
|       my $script;
 | |
|       my $scriptfile; 
 | |
|       $scriptfile = "$tftpdir/mypostscripts/mypostscript.$node";
 | |
|       mkpath(dirname($scriptfile));
 | |
|       open($script, ">$scriptfile");
 | |
| 
 | |
|       unless ($script)
 | |
|       {
 | |
|          my $rsp;
 | |
|          push @{$rsp->{data}}, "Could not open $scriptfile for writing.\n";
 | |
|          xCAT::MsgUtils->message("E", $rsp, $callback);
 | |
|          return 1;
 | |
|       }
 | |
|       $script_fp{$node}=$script;
 | |
|       `/bin/chmod ugo+x $scriptfile`;  
 | |
|       
 | |
|       ##attributes from site tab
 | |
|       #
 | |
|       my $master = $masterhash->{$node};
 | |
| 
 | |
|       if( defined($master) ) {
 | |
|           $allattribsfromsitetable =~ s/MASTER=([^\n]+)\n/MASTER=$master\n/; 
 | |
|       } 
 | |
| 
 | |
|        
 | |
|       #get the node type, service node or compute node
 | |
|       my $nodetype = getNodeType($node);
 | |
| 
 | |
|       ## nfsserver,installnic,primarynic
 | |
|       my ($nfsserver, $installnic, $primarynic, $route_vars);
 | |
| 
 | |
|       my $noderesent;
 | |
|       
 | |
|       if(exists($attribsfromnoderes->{$node})) {
 | |
|           $noderesent = $attribsfromnoderes->{$node};
 | |
|       }
 | |
|  
 | |
|       if ($noderesent ){
 | |
|               if($noderesent->{nfsserver}) {
 | |
|                   $nfsserver = $noderesent->{nfsserver};
 | |
|               }
 | |
|               if($noderesent->{installnic}) {
 | |
|                   $installnic = $noderesent->{installnic};
 | |
|               }
 | |
|               if($noderesent->{primarynic}) {
 | |
|                   $primarynic = $noderesent->{primarynic};
 | |
|               }
 | |
|         
 | |
|       }
 | |
|       #print Dumper($noderesent);
 | |
|       #routes 
 | |
|       if ($noderesent and defined($noderesent->{'routenames'}))
 | |
|       {
 | |
|   	my $rn=$noderesent->{'routenames'};
 | |
|   	my @rn_a=split(',', $rn);
 | |
| 	my $routestab = xCAT::Table->new('routes');
 | |
| 	if ((@rn_a > 0) && ($routestab)) {
 | |
| 	    $route_vars .= "NODEROUTENAMES=$rn\n";
 | |
| 	    $route_vars .= "export NODEROUTENAMES\n";
 | |
| 	    foreach my $route_name (@rn_a) {
 | |
| 		my $routesent = $routestab->getAttribs({routename => $route_name}, 'net', 'mask', 'gateway', 'ifname');
 | |
| 		if ($routesent and defined($routesent->{net}) and defined($routesent->{mask})) {
 | |
| 		    my $val="ROUTE_$route_name=" . $routesent->{net} . "," . $routesent->{mask};
 | |
| 		    $val .= ",";
 | |
| 		    if (defined($routesent->{gateway})) {
 | |
| 			$val .= $routesent->{gateway};
 | |
| 		    }
 | |
| 		    $val .= ",";
 | |
| 		    if (defined($routesent->{ifname})) {
 | |
| 			$val .= $routesent->{ifname};
 | |
| 		    }
 | |
| 		    $route_vars .=  "$val\n";
 | |
| 		    $route_vars .= "export ROUTE_$route_name\n";
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     #NODESETSTATE
 | |
| 
 | |
|     ### vlan related item
 | |
|     #  for #VLAN_VARS_EXPORT#
 | |
|     my $vlan_vars;
 | |
|     $vlan_vars = getVlanItems($node);
 | |
| 
 | |
|     ## get monitoring server and other configuration data for monitoring setup on nodes
 | |
|     # for #MONITORING_VARS_EXPORT#
 | |
|     my $mon_vars;
 | |
|     $mon_vars = getMonItems($node);    
 | |
| 
 | |
|     ## OSPKGDIR export
 | |
|     #  for #OSIMAGE_VARS_EXPORT# 
 | |
|     if (!$nodesetstate) { $nodesetstate = xCAT::Postage::getnodesetstate($node); }
 | |
| 
 | |
|     my $et = $typehash->{$node};
 | |
|     $provmethod = $et->{'provmethod'};
 | |
|     $os = $et->{'os'};
 | |
|     $arch = $et->{'arch'};
 | |
|     $profile = $et->{'profile'};
 | |
| 
 | |
|     my $osimage_vars;
 | |
|     $osimage_vars = getOsimageItems($node);
 | |
|      
 | |
|     ## network
 | |
|     # for #NETWORK_FOR_DISKLESS_EXPORT#
 | |
|     #
 | |
|     my $diskless_net_vars;
 | |
|     $diskless_net_vars = getDisklessNet(); 
 | |
|     
 | |
|     ## postscripts
 | |
|     # for #INCLUDE_POSTSCRIPTS_LIST# 
 | |
|     #
 | |
|     my $postscripts;
 | |
|     $postscripts = getPostScripts();
 | |
| 
 | |
|     ## postbootscripts
 | |
|     # for #INCLUDE_POSTBOOTSCRIPTS_LIST#
 | |
|     my $postbootscripts;
 | |
|     $postbootscripts = getPostbootScripts();
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|   #ok, now do everything else..
 | |
|   #$inc =~ s/#XCATVAR:([^#]+)#/envvar($1)/eg;
 | |
|   #$inc =~ s/#ENV:([^#]+)#/envvar($1)/eg;
 | |
|   $inc =~ s/#SITE_TABLE_ALL_ATTRIBS_EXPORT#/$allattribsfromsitetable/eg; 
 | |
|   $inc =~ s/#TABLE:([^:]+):([^:]+):([^#]+)#/tabdb($1,$2,$3)/eg; 
 | |
|   $inc =~ s/#ROUTES_VARS_EXPORT#/$route_vars/eg; 
 | |
|   $inc =~ s/#VLAN_VARS_EXPORT#/$vlan_vars/eg; 
 | |
|   $inc =~ s/#MONITORING_VARS_EXPORT#/$mon_vars/eg; 
 | |
|   $inc =~ s/#OSIMAGE_VARS_EXPORT#/$osimage_vars/eg; 
 | |
|   $inc =~ s/#NETWORK_FOR_DISKLESS_EXPORT#/$diskless_net_vars/eg; 
 | |
|   $inc =~ s/#INCLUDE_POSTSCRIPTS_LIST#/$postscripts/eg; 
 | |
|   $inc =~ s/#INCLUDE_POSTBOOTSCRIPTS_LIST#/$postbootscripts/eg; 
 | |
|   
 | |
|   #$inc =~ s/#COMMAND:([^#]+)#/command($1)/eg;
 | |
|   $inc =~ s/#NODE#/$node/eg;
 | |
|   $inc =~ s/\$NODE/$node/eg;
 | |
|   $inc =~ s/#OSVER#/$os/eg;
 | |
|   $inc =~ s/#ARCH#/$arch/eg;
 | |
|   $inc =~ s/#PROFILE#/$profile/eg;
 | |
|   $inc =~ s/#NTYPE#/$nodetype/eg;
 | |
|   $inc =~ s/#NFSSERVER#/$nfsserver/eg;
 | |
|   $inc =~ s/#INSTALLNIC#/$installnic/eg;
 | |
|   $inc =~ s/#PRIMARYNIC#/$primarynic/eg;
 | |
|   $inc =~ s/#Subroutine:([^:]+)::([^:]+)::([^:]+):([^#]+)#/subroutine($1,$2,$3,$4)/eg;
 | |
| 
 | |
|   #my $nrtab = xCAT::Table->new("noderes");
 | |
|   #my $tftpserver = $nrtab->getNodeAttribs($node, ['tftpserver']);
 | |
|   #my $sles_sdk_media = "http://" . $tftpserver->{tftpserver} . $media_dir . "/sdk1";
 | |
|   
 | |
|   #$inc =~ s/#SLES_SDK_MEDIA#/$sles_sdk_media/eg;
 | |
| 
 | |
|   #if ($tmplerr) {
 | |
|   #   close ($outh);
 | |
|   #   return $tmplerr;
 | |
|   # }
 | |
|   #print $outh $inc;
 | |
|   #close($outh);
 | |
|       print $script $inc;    
 | |
|       close($script_fp{$node});
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| sub getMasterFromNoderes
 | |
| {
 | |
|      my $node = shift;
 | |
|      my $value;
 | |
|  
 | |
|      my $noderestab = xCAT::Table->new('noderes');
 | |
|      # if node has service node as master then override site master
 | |
|      my $et = $noderestab->getNodeAttribs($node, ['xcatmaster'],prefetchcache=>1);
 | |
|      if ($et and defined($et->{'xcatmaster'}))
 | |
|      {
 | |
|            $value = $et->{'xcatmaster'};
 | |
|      }
 | |
|      else
 | |
|      {
 | |
|            my $sitemaster_value = $value;
 | |
|            $value = xCAT::NetworkUtils->my_ip_facing($node);
 | |
|            if ($value eq "0")
 | |
|            {
 | |
|                 $value = $sitemaster_value;
 | |
|            }
 | |
|       }
 | |
|       
 | |
|       return $value;
 | |
| 
 | |
| }
 | |
| 
 | |
| sub getMasters
 | |
| {
 | |
|      my $nodes = shift;
 | |
|      my %masterhash;
 | |
| 
 | |
|      my $noderestab = xCAT::Table->new('noderes');
 | |
|      # if node has service node as master then override site master
 | |
|      my $ethash = $noderestab->getNodesAttribs($nodes, ['xcatmaster'],prefetchcache=>1);
 | |
| 
 | |
|      
 | |
|      if ($ethash) {
 | |
|          foreach my $node ($nodes) {
 | |
|              if( $ethash->{$node}->[0] ) {
 | |
|                   $masterhash{$node} = $ethash->{$node}->[0]->{xcatmaster};    
 | |
|              }
 | |
| 
 | |
|              if ( ! exists($masterhash{$node}))
 | |
|              {
 | |
|                   my $value;
 | |
|                   $value = xCAT::NetworkUtils->my_ip_facing($node);
 | |
|                   if ($value eq "0")
 | |
|                   {
 | |
|                       undef($value);
 | |
|                   }
 | |
|                   $masterhash{$node} = $value;
 | |
|              }
 | |
|          }
 | |
|  
 | |
|      } 
 | |
|      
 | |
|      return \%masterhash; 
 | |
| }
 | |
| 
 | |
| sub getNoderes
 | |
| {
 | |
|      my $nodes = shift;
 | |
|      my %nodereshash;
 | |
| 
 | |
|      my $noderestab = xCAT::Table->new('noderes');
 | |
|        
 | |
|      my $ethash =
 | |
|         $noderestab->getNodesAttribs($nodes,
 | |
|                                   ['nfsserver', 'installnic', 'primarynic','routenames'],prefetchcache=>1);
 | |
|      if ($ethash ){
 | |
|           foreach my $node (@$nodes) {
 | |
|               if( defined( $ethash->{$node}->[0]) ) {
 | |
|                   $nodereshash{$node}{nfsserver} = $ethash->{$node}->[0]->{nfsserver};
 | |
|                   $nodereshash{$node}{installnic} = $ethash->{$node}->[0]->{installnic};
 | |
|                   $nodereshash{$node}{primarynic} = $ethash->{$node}->[0]->{primarynic};
 | |
|                   $nodereshash{$node}{routenames} = $ethash->{$node}->[0]->{routenames};
 | |
|               }
 | |
|           }  
 | |
|       }
 | |
|      
 | |
|      return \%nodereshash; 
 | |
| }
 | |
| 
 | |
| 
 | |
| sub getTypeVars
 | |
| {
 | |
|      my $nodes    = shift;
 | |
|      my $callback = shift;
 | |
|      my %typehash;
 | |
| 
 | |
|      my $typetab = xCAT::Table->new('nodetype');
 | |
|        
 | |
|      my $ethash =
 | |
|       $typetab->getNodesAttribs($nodes, ['os', 'arch', 'profile', 'provmethod'],prefetchcache=>1);
 | |
| 
 | |
|      if ($ethash ){
 | |
|           foreach my $node (@$nodes) {
 | |
|               if( defined( $ethash->{$node}->[0]) ) {
 | |
|                   $typehash{$node}{os} = $ethash->{$node}->[0]->{os};
 | |
|                   $typehash{$node}{arch} = $ethash->{$node}->[0]->{arch};
 | |
| 
 | |
|                  if ($^O =~ /^linux/i)
 | |
|                  {
 | |
|                       unless ($typehash{$node}{'os'} and $typehash{$node}{'arch'})
 | |
|                       {
 | |
|                           my $rsp;
 | |
|                           push @{$rsp->{data}},
 | |
|                                "No os or arch setting in nodetype table for $node.\n";
 | |
|                                xCAT::MsgUtils->message("E", $rsp, $callback);
 | |
|                                return undef;
 | |
|                        }
 | |
|                   }
 | |
| 
 | |
| 
 | |
|                   $typehash{$node}{profile} = $ethash->{$node}->[0]->{profile};
 | |
|               }
 | |
|           }  
 | |
|       }
 | |
|      
 | |
|      return \%typehash; 
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| sub getAllAttribsFromSiteTab {
 | |
|     
 | |
|     my $sitetab    = xCAT::Table->new('site');
 | |
|     my $master;
 | |
|     my $result;
 | |
|     
 | |
|     # read all attributes for the site table and write an export
 | |
|     # for them in the post install file
 | |
|     my $recs = $sitetab->getAllEntries();
 | |
|     my $noderestab = xCAT::Table->new('noderes');
 | |
|     my $attribute;
 | |
|     my $value;
 | |
|     my $masterset = 0;
 | |
|     foreach (@$recs)    # export the attribute
 | |
|     {
 | |
|         $attribute = $_->{key};
 | |
|         $attribute =~ tr/a-z/A-Z/;
 | |
|         $value = $_->{value};
 | |
|         if ($attribute eq "MASTER")
 | |
|         {
 | |
|             $masterset = 1;
 | |
|             $result .= "SITEMASTER=" . $value . "\n";
 | |
|             $result .= "export SITEMASTER\n";
 | |
| 
 | |
|             # if node has service node as master then override site master
 | |
|             #my $et = $noderestab->getNodeAttribs($node, ['xcatmaster'],prefetchcache=>1);
 | |
|             #if ($et and defined($et->{'xcatmaster'}))
 | |
|             #{
 | |
|             #    $value = $et->{'xcatmaster'};
 | |
|             #}
 | |
|             #else
 | |
|             #{
 | |
|             #    my $sitemaster_value = $value;
 | |
|             #    $value = xCAT::Utils->my_ip_facing($node);
 | |
|             #    if ($value eq "0")
 | |
|             #    {
 | |
|             #        $value = $sitemaster_value;
 | |
|             #    }
 | |
|             #}
 | |
|             $result .= "$attribute=" . $value . "\n";
 | |
|             $result .= "export $attribute\n";
 | |
| 
 | |
|         }
 | |
|         else
 | |
|         {    # not Master attribute
 | |
|             $result .= "$attribute='" . $value . "'\n";
 | |
|             $result .= "export $attribute\n";
 | |
|         }
 | |
|     }    # end site table attributes
 | |
| 
 | |
|     return $result;
 | |
| }
 | |
| 
 | |
| sub enablesshbetweennodes
 | |
| {
 | |
|    my $node = shift;  
 | |
|    my $result;   
 | |
| 
 | |
|    my $enablessh=xCAT::TableUtils->enablessh($node); 
 | |
|    if ($enablessh == 1) {
 | |
|        $result = "YES";
 | |
|    } else {
 | |
|        $result = "NO";
 | |
|    }      
 | |
|    
 | |
|    return $result;
 | |
| }
 | |
| 
 | |
| sub subroutine
 | |
| {
 | |
|    my $prefix          = shift;
 | |
|    my $module          = shift;
 | |
|    my $subroutine_name = shift;
 | |
|    my $key = shift;  
 | |
|    my $result;   
 | |
|    
 | |
|    if ($key eq "THISNODE" or $key eq '$NODE') {
 | |
|       $key=$node;  
 | |
|    }
 | |
|    my $function = join("::",$prefix,$module,$subroutine_name);
 | |
|    
 | |
|    {
 | |
|        no strict 'refs';
 | |
|        $result=$function->($key); 
 | |
|        use strict;
 | |
|    }
 | |
| 
 | |
|    return $result;
 | |
| }
 | |
| 
 | |
| 
 | |
| sub getNodeType
 | |
| {
 | |
| 
 | |
|     my $node = shift;
 | |
|     my $result;
 | |
| 
 | |
|     # see if this is a service or compute node?
 | |
|     if (xCAT::Utils->isSN($node))
 | |
|     {
 | |
|         $result="service";
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         $result="compute";
 | |
|     }
 | |
| 
 | |
|     return $result;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| sub getVlanItems
 | |
| {
 | |
| 
 | |
|     my $node = shift;
 | |
|     my $result;
 | |
| 
 | |
|     #get vlan related items
 | |
|     my $vlan;
 | |
|     my $swtab = xCAT::Table->new("switch", -create => 0);
 | |
|     if ($swtab) {
 | |
| 	my $tmp = $swtab->getNodeAttribs($node, ['vlan'],prefetchcache=>1);
 | |
| 	if (defined($tmp) && ($tmp) && $tmp->{vlan})
 | |
| 	{
 | |
| 	    $vlan = $tmp->{vlan};
 | |
| 	    $result .= "VLANID='" . $vlan . "'\n";
 | |
| 	    $result .= "export VLANID\n";
 | |
| 	} else {
 | |
| 	    my $vmtab = xCAT::Table->new("vm", -create => 0);
 | |
| 	    if ($vmtab) {
 | |
| 		my $tmp1 = $vmtab->getNodeAttribs($node, ['nics'],prefetchcache=>1);
 | |
| 		if (defined($tmp1) && ($tmp1) && $tmp1->{nics})
 | |
| 		{
 | |
| 		    $result .= "VMNODE='YES'\n";
 | |
| 		    $result .= "export VMNODE\n";
 | |
| 		    
 | |
| 		    my @nics=split(',', $tmp1->{nics});
 | |
| 		    foreach my $nic (@nics) {
 | |
| 			if ($nic =~ /^vl([\d]+)$/) {
 | |
| 			    $vlan = $1;
 | |
| 			    $result .= "VLANID='" . $vlan . "'\n";
 | |
| 			    $result .= "export VLANID\n";
 | |
| 			    last;
 | |
| 			}
 | |
| 		    }
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
| 	
 | |
| 	if ($vlan) {
 | |
| 	    my $nwtab=xCAT::Table->new("networks", -create =>0);
 | |
| 	    if ($nwtab) {
 | |
| 		my $sent = $nwtab->getAttribs({vlanid=>"$vlan"},'net','mask');
 | |
| 		my $subnet;
 | |
| 		my $netmask;
 | |
| 		if ($sent and ($sent->{net})) {
 | |
| 		    $subnet=$sent->{net};
 | |
| 		    $netmask=$sent->{mask};
 | |
| 		} 
 | |
| 		if (($subnet) && ($netmask)) {
 | |
| 		    my $hoststab = xCAT::Table->new("hosts", -create => 0);
 | |
| 		    if ($hoststab) {
 | |
| 			my $tmp = $hoststab->getNodeAttribs($node, ['otherinterfaces'],prefetchcache=>1);
 | |
| 			if (defined($tmp) && ($tmp) && $tmp->{otherinterfaces})
 | |
| 			{
 | |
| 			    my $otherinterfaces = $tmp->{otherinterfaces};
 | |
| 			    my @itf_pairs=split(/,/, $otherinterfaces);
 | |
| 			    foreach (@itf_pairs) {
 | |
| 				my ($name,$ip)=split(/:/, $_);
 | |
| 				if(xCAT::NetworkUtils->ishostinsubnet($ip, $netmask, $subnet)) {
 | |
| 				    if ($name =~ /^-/ ) {
 | |
| 					$name = $node.$name;
 | |
| 				    }
 | |
| 				    $result .= "VLANHOSTNAME='" . $name . "'\n";
 | |
| 				    $result .= "export VLANHOSTNAME\n";
 | |
| 				    $result .= "VLANIP='" . $ip . "'\n";
 | |
| 				    $result .= "export VLANIP\n";
 | |
| 				    $result .= "VLANSUBNET='" . $subnet . "'\n";
 | |
| 				    $result .= "export VLANSUBNET\n";
 | |
| 				    $result .= "VLANNETMASK='" . $netmask . "'\n";
 | |
| 				    $result .= "export VLANNETMASK\n";
 | |
| 				    last;
 | |
| 				}
 | |
| 			    }	    
 | |
| 			}
 | |
| 		    }
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
| 
 | |
| 
 | |
|    return $result;
 | |
| }
 | |
| 
 | |
| 
 | |
| sub getMonItems
 | |
| {
 | |
| 
 | |
|     my $node = shift;
 | |
|     my $result;
 | |
| 
 | |
|     #get monitoring server and other configuration data for monitoring setup on nodes
 | |
|     my %mon_conf = xCAT_monitoring::monitorctrl->getNodeConfData($node);
 | |
|     foreach (keys(%mon_conf))
 | |
|     {
 | |
|         $result .= "$_=" . $mon_conf{$_} . "\n";
 | |
|         $result .= "export $_\n";
 | |
|     }
 | |
| 
 | |
| 
 | |
| 
 | |
|     return $result;
 | |
| }
 | |
| 
 | |
| 
 | |
| sub getOsimageItems
 | |
| {
 | |
| 
 | |
|     my $result;
 | |
| 
 | |
|     #get packge names for extra rpms
 | |
|     my $pkglist;
 | |
|     my $ospkglist;
 | |
|     if (   ($^O =~ /^linux/i)
 | |
|         && ($provmethod)
 | |
|         && ($provmethod ne "install")
 | |
|         && ($provmethod ne "netboot")
 | |
|         && ($provmethod ne "statelite"))
 | |
|     {
 | |
| 
 | |
|         #this is the case where image from the osimage table is used
 | |
|         my $linuximagetab = xCAT::Table->new('linuximage', -create => 1);
 | |
|         (my $ref1) =
 | |
|           $linuximagetab->getAttribs({imagename => $provmethod},
 | |
|                                      'pkglist', 'pkgdir', 'otherpkglist',
 | |
|                                      'otherpkgdir');
 | |
|         if ($ref1)
 | |
|         {
 | |
|             if ($ref1->{'pkglist'})
 | |
|             {
 | |
|                 $ospkglist = $ref1->{'pkglist'};
 | |
|                 if ($ref1->{'pkgdir'})
 | |
|                 {
 | |
|                     $result .= "OSPKGDIR=" . $ref1->{'pkgdir'} . "\n";
 | |
|                     $result .= "export OSPKGDIR\n";
 | |
|                 }
 | |
|             }
 | |
|             if ($ref1->{'otherpkglist'})
 | |
|             {
 | |
|                 $pkglist = $ref1->{'otherpkglist'};
 | |
|                 if ($ref1->{'otherpkgdir'})
 | |
|                 {
 | |
|                     $result .= 
 | |
|                       "OTHERPKGDIR=" . $ref1->{'otherpkgdir'} . "\n";
 | |
|                     $result .=  "export OTHERPKGDIR\n";
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         my $stat        = "install";
 | |
|         my $installroot = xCAT::TableUtils->getInstallDir();
 | |
|         if ($profile)
 | |
|         {
 | |
|             my $platform = "rh";
 | |
|             if ($os)
 | |
|             {
 | |
|                 if    ($os =~ /rh.*/)     { $platform = "rh"; }
 | |
|                 elsif ($os =~ /centos.*/) { $platform = "centos"; }
 | |
|                 elsif ($os =~ /fedora.*/) { $platform = "fedora"; }
 | |
|                 elsif ($os =~ /SL.*/)     { $platform = "SL"; }
 | |
|                 elsif ($os =~ /sles.*/)   { $platform = "sles"; }
 | |
|                 elsif ($os =~ /ubuntu.*/) { $platform = "ubuntu"; }
 | |
|                 elsif ($os =~ /debian.*/) { $platform = "debian"; }
 | |
|                 elsif ($os =~ /aix.*/)    { $platform = "aix"; }
 | |
|                 elsif ($os =~ /AIX.*/)    { $platform = "AIX"; }
 | |
|             }
 | |
|             if (($nodesetstate) && ($nodesetstate eq "netboot" || $nodesetstate eq "statelite"))
 | |
|             {
 | |
|                 $stat = "netboot";
 | |
|             }
 | |
| 
 | |
|             $ospkglist =
 | |
|               xCAT::SvrUtils->get_pkglist_file_name(
 | |
|                                           "$installroot/custom/$stat/$platform",
 | |
|                                           $profile, $os, $arch);
 | |
|             if (!$ospkglist)
 | |
|             {
 | |
|                 $ospkglist =
 | |
|                   xCAT::SvrUtils->get_pkglist_file_name(
 | |
|                                        "$::XCATROOT/share/xcat/$stat/$platform",
 | |
|                                        $profile, $os, $arch);
 | |
|             }
 | |
| 
 | |
|             $pkglist =
 | |
|               xCAT::SvrUtils->get_otherpkgs_pkglist_file_name(
 | |
|                                           "$installroot/custom/$stat/$platform",
 | |
|                                           $profile, $os, $arch);
 | |
|             if (!$pkglist)
 | |
|             {
 | |
|                 $pkglist =
 | |
|                   xCAT::SvrUtils->get_otherpkgs_pkglist_file_name(
 | |
|                                        "$::XCATROOT/share/xcat/$stat/$platform",
 | |
|                                        $profile, $os, $arch);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     #print "pkglist=$pkglist\n";
 | |
|     #print "ospkglist=$ospkglist\n";
 | |
|     require xCAT::Postage;
 | |
|     if ($ospkglist)
 | |
|     {
 | |
|         my $pkgtext = xCAT::Postage::get_pkglist_tex($ospkglist);
 | |
|         my ($envlist,$pkgtext) = xCAT::Postage::get_envlist($pkgtext);
 | |
|         if ($envlist) {
 | |
|            $result .= "ENVLIST='".$envlist."'\n";
 | |
|            $result .= "export ENVLIST\n";
 | |
|         }
 | |
|         if ($pkgtext)
 | |
|         {
 | |
|             $result .= "OSPKGS='".$pkgtext."'\n";
 | |
|             $result .= "export OSPKGS\n";
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ($pkglist)
 | |
|     {
 | |
|         my $pkgtext = xCAT::Postage::get_pkglist_tex($pkglist);
 | |
|         if ($pkgtext)
 | |
|         {
 | |
|             my @sublists = split('#NEW_INSTALL_LIST#', $pkgtext);
 | |
|             my $sl_index = 0;
 | |
|             foreach (@sublists)
 | |
|             {
 | |
|                 $sl_index++;
 | |
|                 my $tmp = $_;
 | |
|                 my ($envlist, $tmp) = xCAT::Postage::get_envlist($tmp);
 | |
|                 if ($envlist) {
 | |
|                     $result .= "ENVLIST$sl_index='".$envlist."'\n";
 | |
|                     $result .= "export ENVLIST$sl_index\n";
 | |
|                 }
 | |
|                 $result .= "OTHERPKGS$sl_index='".$tmp."'\n";
 | |
|                 $result .= "export OTHERPKGS$sl_index\n";
 | |
|             }
 | |
|             if ($sl_index > 0)
 | |
|             {
 | |
|                 $result .= "OTHERPKGS_INDEX=$sl_index\n";
 | |
|                 $result .= "export OTHERPKGS_INDEX\n";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     # SLES sdk
 | |
|     if ($os =~ /sles.*/)
 | |
|     {
 | |
|         my $installdir = $::XCATSITEVALS{'installdir'} ? $::XCATSITEVALS{'installdir'} : "/install";
 | |
|         my $sdkdir = "$installdir/$os/$arch/sdk1";
 | |
|         if (-e "$sdkdir")
 | |
|         {
 | |
|             $result .= "SDKDIR='" . $sdkdir . "'\n";
 | |
|             $result .= "export SDKDIR\n";
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # check if there are sync files to be handled
 | |
|     my $syncfile;
 | |
|     if (   ($provmethod)
 | |
|         && ($provmethod ne "install")
 | |
|         && ($provmethod ne "netboot")
 | |
|         && ($provmethod ne "statelite"))
 | |
|     {
 | |
|         my $osimagetab = xCAT::Table->new('osimage', -create => 1);
 | |
|         if ($osimagetab)
 | |
|         {
 | |
|             (my $ref) =
 | |
|               $osimagetab->getAttribs(
 | |
|                                       {imagename => $provmethod}, 'osvers',
 | |
|                                       'osarch',     'profile',
 | |
|                                       'provmethod', 'synclists'
 | |
|                                       );
 | |
|             if ($ref)
 | |
|             {
 | |
|                 $syncfile = $ref->{'synclists'};
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     if (!$syncfile)
 | |
|     {
 | |
|         my $stat = "install";
 | |
|         if (($nodesetstate) && ($nodesetstate eq "netboot" || $nodesetstate eq "statelite")) {
 | |
|             $stat = "netboot";
 | |
|         }
 | |
|         $syncfile =
 | |
|           xCAT::SvrUtils->getsynclistfile(undef, $os, $arch, $profile, $stat);
 | |
|     }
 | |
|     if (!$syncfile)
 | |
|     {
 | |
|         $result .= "NOSYNCFILES=1\n";
 | |
|         $result .= "export NOSYNCFILES\n";
 | |
|     }
 | |
| 
 | |
| 
 | |
|     return $result;
 | |
| }
 | |
| 
 | |
| my $setbootfromnet = 0;
 | |
| sub getDisklessNet()
 | |
| {
 | |
|     my $result;
 | |
|     my $isdiskless     = 0;
 | |
|     my $bootfromnet = 0;
 | |
|     if (($arch eq "ppc64") || ($os =~ /aix.*/i))
 | |
|     {
 | |
| 
 | |
|         # on Linux, the provmethod can be install,netboot or statelite,
 | |
|         # on AIX, the provmethod can be null or image name
 | |
|         #this is for Linux
 | |
|         if (   ($provmethod)
 | |
|             && (($provmethod eq "netboot") || ($provmethod eq "statelite")))
 | |
|         {
 | |
|             $isdiskless = 1;
 | |
|         }
 | |
|     
 | |
|         if ($isdiskless)
 | |
|         {
 | |
|             (my $ip, my $mask, my $gw) = net_parms($node);
 | |
|             if (!$ip || !$mask || !$gw)
 | |
|             {
 | |
|                 xCAT::MsgUtils->message(
 | |
|                     'S',
 | |
|                     "Unable to determine IP, netmask or gateway for $node, can not set the node to boot from network"
 | |
|                     );
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 $bootfromnet = 1;
 | |
|                 $result .= "NETMASK=$mask\n";
 | |
|                 $result .= "export NETMASK\n";
 | |
|                 $result .= "GATEWAY=$gw\n";
 | |
|                 $result .= "export GATEWAY\n";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     $setbootfromnet = $bootfromnet;    
 | |
| 
 | |
|     return $result;
 | |
| 
 | |
| }
 | |
| 
 | |
| my $et;
 | |
| my $et1;
 | |
| my $et2;
 | |
| 
 | |
| sub getPostScripts
 | |
| {
 | |
| 
 | |
|     my $node = shift;
 | |
|     my $result;
 | |
|     my $ps;
 | |
|     my %post_hash = ();    #used to reduce duplicates
 | |
|  
 | |
|    
 | |
|     my $posttab    = xCAT::Table->new('postscripts');
 | |
|     my $ostab    = xCAT::Table->new('osimage');
 | |
|     # get the xcatdefaults entry in the postscripts table
 | |
|     my $et        =
 | |
|       $posttab->getAttribs({node => "xcatdefaults"},
 | |
|                            'postscripts', 'postbootscripts');
 | |
|     my $defscripts = $et->{'postscripts'};
 | |
|     if ($defscripts)
 | |
|     {
 | |
| 
 | |
|         foreach my $n (split(/,/, $defscripts))
 | |
|         {
 | |
|             if (!exists($post_hash{$n}))
 | |
|             {
 | |
|                 $post_hash{$n} = 1;
 | |
|                 $result .= $n . "\n";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     # get postscripts for images
 | |
|     my $osimgname = $provmethod;
 | |
| 
 | |
|     if($osimgname =~ /install|netboot|statelite/){
 | |
|         $osimgname = "$os-$arch-$provmethod-$profile";
 | |
|     }
 | |
|     my $et2 =
 | |
|       $ostab->getAttribs({'imagename' => "$osimgname"}, ['postscripts', 'postbootscripts']);
 | |
|     $ps = $et2->{'postscripts'};
 | |
|     if ($ps)
 | |
|     {
 | |
|         foreach my $n (split(/,/, $ps))
 | |
|         {
 | |
|             if (!exists($post_hash{$n}))
 | |
|             {
 | |
|                 $post_hash{$n} = 1;
 | |
|                 $result .= $n . "\n";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # get postscripts for node specific
 | |
|     my $et1 =
 | |
|       $posttab->getNodeAttribs($node, ['postscripts', 'postbootscripts'],prefetchcache=>1);
 | |
|     $ps = $et1->{'postscripts'};
 | |
|     if ($ps)
 | |
|     {
 | |
|         foreach my $n (split(/,/, $ps))
 | |
|         {
 | |
|             if (!exists($post_hash{$n}))
 | |
|             {
 | |
|                 $post_hash{$n} = 1;
 | |
|                 $result .=  $n . "\n";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if ($setbootfromnet)
 | |
|     {
 | |
|         $result .=  "setbootfromnet\n";
 | |
|     }
 | |
| 
 | |
|     # add setbootfromdisk if the nodesetstate is install and arch is ppc64
 | |
|     if (($nodesetstate) && ($nodesetstate eq "install") && ($arch eq "ppc64"))
 | |
|     {
 | |
|         $result .=  "setbootfromdisk\n";
 | |
|     }
 | |
| 
 | |
| 
 | |
|     return $result;
 | |
| }
 | |
| 
 | |
| 
 | |
| sub getPostbootScripts
 | |
| {
 | |
| 
 | |
|     my $node = shift;
 | |
|     my $result;
 | |
|     my $ps;
 | |
|  
 | |
|    
 | |
|     my %postboot_hash = ();                         #used to reduce duplicates
 | |
|     my $defscripts    = $et->{'postbootscripts'};
 | |
|     if ($defscripts)
 | |
|     {
 | |
|         foreach my $n (split(/,/, $defscripts))
 | |
|         {
 | |
|             if (!exists($postboot_hash{$n}))
 | |
|             {
 | |
|                 $postboot_hash{$n} = 1;
 | |
|                 $result .=   $n . "\n";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     # get postbootscripts for image
 | |
|     my $ips = $et2->{'postbootscripts'};
 | |
|     if ($ips)
 | |
|     {
 | |
|         foreach my $n (split(/,/, $ips))
 | |
|         {
 | |
|             if (!exists($postboot_hash{$n}))
 | |
|             {
 | |
|                 $postboot_hash{$n} = 1;
 | |
|                 $result .=  $n . "\n";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     # get postscripts
 | |
|     $ps = $et1->{'postbootscripts'};
 | |
|     if ($ps)
 | |
|     {
 | |
|         foreach my $n (split(/,/, $ps))
 | |
|         {
 | |
|             if (!exists($postboot_hash{$n}))
 | |
|             {
 | |
|                 $postboot_hash{$n} = 1;
 | |
|                 $result .=  $n . "\n";
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return $result;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 1;
 |