148482344e
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@14141 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
1714 lines
50 KiB
Perl
1714 lines
50 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;
|
|
|
|
|
|
if( defined(%::GLOBAL_TAB_HASH) && defined( $::GLOBAL_TAB_HASH{$table}) && defined( $::GLOBAL_TAB_HASH{$table}{$key}) ) {
|
|
return $::GLOBAL_TAB_HASH{$table}{$key}{$field};
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
=head3 subvars_for_mypostscript
|
|
|
|
create the mypostscript file for each node in the noderange, according to
|
|
the template file mypostscript.tmpl. The template file is
|
|
/opt/xcat/share/xcat/templates/mypostscript/mypostscript.tmpl by default. and
|
|
uses also can copy it to /install/postscripts/, and customize it there.
|
|
The mypostscript.tmpl is for all the images.
|
|
|
|
If success, there is a mypostscript.$nodename for each node in the $tftpdir/mypostscripts/
|
|
|
|
|
|
Arguments:
|
|
hostname
|
|
Returns:
|
|
Globals:
|
|
%::GLOBAL_TAB_HASH: in subvars_for_mypostscript(), it will read mypostscript.tmpl and
|
|
see what db attrs will be needed. The %::GLOBAL_TAB_HASH will store all
|
|
the db attrs needed. And the format of value setting looks like:
|
|
$::GLOBAL_TAB_HASH{$tabname}{$key}{$attrib} = $value;
|
|
|
|
Error:
|
|
none
|
|
Example:
|
|
|
|
Comments:
|
|
none
|
|
|
|
=cut
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
my $os;
|
|
my $profile;
|
|
my $arch;
|
|
my $provmethod;
|
|
%::GLOBAL_TAB_HASH = ();
|
|
|
|
sub subvars_for_mypostscript {
|
|
my $self = shift;
|
|
my $nodes = shift;
|
|
my $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;
|
|
my %table;
|
|
#First load input into memory..
|
|
while (<$inh>) {
|
|
$t_inc.=$_;
|
|
if( $_ =~ /#TABLE:([^:]+):([^:]+):([^#]+)#/ ) {
|
|
my $tabname=$1;
|
|
my $key=$2;
|
|
my $attrib = $3;
|
|
$table{$tabname}{$key}{$attrib} = 1;
|
|
}
|
|
}
|
|
|
|
close($inh);
|
|
|
|
##
|
|
# $Tabname_hash{$key}{$attrib}=value
|
|
# for example: $MAC_hash{cn001}{mac}=9a:ca:be:a9:ad:02
|
|
#
|
|
#
|
|
#%::GLOBAL_TAB_HASH = ();
|
|
my $rc = collect_all_attribs_for_tables_in_template(\%table, $nodes, $callback);
|
|
if($rc == -1) {
|
|
return;
|
|
}
|
|
|
|
#print Dumper(\%::GLOBAL_TAB_HASH);
|
|
|
|
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();
|
|
|
|
# get the net', 'mask', 'gateway' from networks table
|
|
my $nets = getNetworks();
|
|
|
|
#%image_hash is used to store the attributes in linuximage and osimage tabs
|
|
my %image_hash;
|
|
getLinuximage(\%image_hash);
|
|
|
|
# get postscript and postscript
|
|
my $script_hash = xCAT::Postage::getScripts($nodes, \%image_hash);
|
|
|
|
my $tftpdir = xCAT::TableUtils::getTftpDir();
|
|
|
|
my $snhash = getservicenode();
|
|
|
|
foreach my $n (@$nodes ) {
|
|
$node = $n;
|
|
$inc = $t_inc;
|
|
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 = $attribsfromnoderes->{$node}->{xcatmaster};
|
|
my $master = $::GLOBAL_TAB_HASH{noderes}{$node}{xcatmaster};
|
|
|
|
if( !defined($master) ) {
|
|
$::GLOBAL_TAB_HASH{noderes}{$node}{xcatmaster} = $::XCATSITEVALS{MASTER};
|
|
}
|
|
|
|
#get the node type, service node or compute node
|
|
my $nodetype = getNodeType($node, $snhash);
|
|
|
|
|
|
my $noderesent;
|
|
|
|
if(exists($::GLOBAL_TAB_HASH{noderes}{$node})) {
|
|
$noderesent = $::GLOBAL_TAB_HASH{noderes}{$node};
|
|
}
|
|
|
|
#print Dumper($noderesent);
|
|
#routes
|
|
my $route_vars;
|
|
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);
|
|
|
|
|
|
#print "nodesetstate:$nodesetstate\n";
|
|
## OSPKGDIR export
|
|
# for #OSIMAGE_VARS_EXPORT#
|
|
if (!$nodesetstate) { $nodesetstate = xCAT::Postage::getnodesetstate($node); }
|
|
#print "nodesetstate:$nodesetstate\n";
|
|
|
|
#my $et = $typehash->{$node};
|
|
my $et = $::GLOBAL_TAB_HASH{nodetype}{$node};
|
|
$provmethod = $et->{'provmethod'};
|
|
$os = $et->{'os'};
|
|
$arch = $et->{'arch'};
|
|
$profile = $et->{'profile'};
|
|
|
|
|
|
my $osimgname = $provmethod;
|
|
if($osimgname =~ /install|netboot|statelite/){
|
|
$osimgname = "$os-$arch-$provmethod-$profile";
|
|
}
|
|
|
|
my $osimage_vars;
|
|
$osimage_vars = getImageitems_for_node($node, \%image_hash, $nodesetstate);
|
|
|
|
## network
|
|
# for #NETWORK_FOR_DISKLESS_EXPORT#
|
|
#
|
|
my $diskless_net_vars;
|
|
my $setbootfromnet = 0;
|
|
$diskless_net_vars = getDisklessNet($nets, \$setbootfromnet, $image_hash{$osimgname}{provmethod});
|
|
|
|
## postscripts
|
|
# for #INCLUDE_POSTSCRIPTS_LIST#
|
|
#
|
|
#
|
|
|
|
my $postscripts;
|
|
$postscripts = xCAT::Postage::getPostScripts($node, $osimgname, $script_hash, $setbootfromnet, $nodesetstate, $arch);
|
|
|
|
## postbootscripts
|
|
# for #INCLUDE_POSTBOOTSCRIPTS_LIST#
|
|
my $postbootscripts;
|
|
$postbootscripts = xCAT::Postage::getPostbootScripts($node, $osimgname, $script_hash);
|
|
|
|
|
|
|
|
|
|
#ok, now do everything else..
|
|
#$inc =~ s/#XCATVAR:([^#]+)#/envvar($1)/eg;
|
|
#$inc =~ s/#ENV:([^#]+)#/envvar($1)/eg;
|
|
$inc =~ s/#NODE#/$node/eg;
|
|
$inc =~ s/\$NODE/$node/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/#NTYPE#/$nodetype/eg;
|
|
$inc =~ s/#Subroutine:([^:]+)::([^:]+)::([^:]+):([^#]+)#/subroutine($1,$2,$3,$4)/eg;
|
|
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
}
|
|
#print Dumper(\%masterhash);
|
|
return \%masterhash;
|
|
}
|
|
|
|
sub getservicenode
|
|
{
|
|
my %snhash;
|
|
# reads all nodes from the service node table
|
|
my $servicenodetab = xCAT::Table->new('servicenode');
|
|
unless ($servicenodetab) # no servicenode table
|
|
{
|
|
xCAT::MsgUtils->message('I', "Unable to open servicenode table.\n");
|
|
return undef;
|
|
|
|
}
|
|
my @nodes = $servicenodetab->getAllNodeAttribs(['tftpserver'],undef,prefetchcache=>1);
|
|
$servicenodetab->close;
|
|
foreach my $n (@nodes)
|
|
{
|
|
my $node = $n->{node};
|
|
$snhash{$node}=1
|
|
}
|
|
|
|
return \%snhash;
|
|
}
|
|
|
|
|
|
sub getNoderes
|
|
{
|
|
my $nodes = shift;
|
|
my %nodereshash;
|
|
|
|
my $noderestab = xCAT::Table->new('noderes');
|
|
|
|
my $ethash =
|
|
$noderestab->getNodesAttribs($nodes,
|
|
['nfsserver', 'installnic', 'primarynic','routenames', 'xcatmaster'],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};
|
|
$nodereshash{$node}{xcatmaster} = $ethash->{$node}->[0]->{xcatmaster};
|
|
|
|
if ( ! exists($nodereshash{$node}{xcatmaster}))
|
|
{
|
|
my $value;
|
|
$value = xCAT::NetworkUtils->my_ip_facing($node);
|
|
if ($value eq "0")
|
|
{
|
|
undef($value);
|
|
}
|
|
$nodereshash{$node}{xcatmaster} = $value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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};
|
|
$typehash{$node}{provmethod} = $ethash->{$node}->[0]->{provmethod};
|
|
}
|
|
}
|
|
}
|
|
|
|
return \%typehash;
|
|
}
|
|
|
|
|
|
sub getAllAttribsFromSiteTab {
|
|
|
|
my $result;
|
|
|
|
# all attributes for the site table are in %::XCATSITEVALS, so write an export
|
|
# for them in the mypostscript file
|
|
my $attribute;
|
|
my $value;
|
|
my $masterset = 0;
|
|
foreach (keys(%::XCATSITEVALS)) # export the attribute
|
|
{
|
|
$attribute = $_;
|
|
$attribute =~ tr/a-z/A-Z/;
|
|
$value = $::XCATSITEVALS{$_};
|
|
if ($attribute eq "MASTER")
|
|
{
|
|
$masterset = 1;
|
|
$result .= "SITEMASTER=" . $value . "\n";
|
|
$result .= "export SITEMASTER\n";
|
|
|
|
#if noderes.master for each node exists, the following value will be replaced.
|
|
#$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 $snhash = shift;
|
|
my $result;
|
|
|
|
# see if this is a service or compute node?
|
|
if ($snhash->{$node} == 1)
|
|
{
|
|
$result="service";
|
|
}
|
|
else
|
|
{
|
|
$result="compute";
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
|
|
sub getVlanItems_t
|
|
{
|
|
|
|
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 getVlanItems
|
|
{
|
|
|
|
my $node = shift;
|
|
my $result;
|
|
|
|
#get vlan related items
|
|
my $module_name="xCAT_plugin::vlan";
|
|
eval("use $module_name;");
|
|
if (!$@) {
|
|
no strict "refs";
|
|
if (defined(${$module_name."::"}{getNodeVlanConfData})) {
|
|
my @tmp_scriptd=${$module_name."::"}{getNodeVlanConfData}->($node);
|
|
#print Dumper(@tmp_scriptd);
|
|
if (@tmp_scriptd > 0) {
|
|
$result = join(" ", @tmp_scriptd);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
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 getLinuximage
|
|
{
|
|
|
|
my $image_hash = shift;
|
|
my $linuximagetab = xCAT::Table->new('linuximage', -create => 1);
|
|
|
|
my @et2 = $linuximagetab->getAllAttribs('imagename', 'pkglist', 'pkgdir', 'otherpkglist', 'otherpkgdir' );
|
|
if( @et2 ) {
|
|
foreach my $tmp_et2 (@et2) {
|
|
my $imagename= $tmp_et2->{imagename};
|
|
$image_hash->{$imagename}->{pkglist}= $tmp_et2->{pkglist};
|
|
$image_hash->{$imagename}->{pkgdir} = $tmp_et2->{pkgdir};
|
|
$image_hash->{$imagename}->{otherpkglist} = $tmp_et2->{otherpkglist};
|
|
$image_hash->{$imagename}->{otherpkgdir} = $tmp_et2->{otherpkgdir};
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
sub getImageitems_for_node
|
|
{
|
|
|
|
my $node = shift;
|
|
my $image_hash = shift;
|
|
my $nodesetstate = shift;
|
|
|
|
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');
|
|
my $ref1 = $image_hash->{$provmethod};
|
|
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'
|
|
# );
|
|
my $ref = $image_hash->{$provmethod};
|
|
if ($ref)
|
|
{
|
|
$syncfile = $ref->{'synclists'};
|
|
# if($ref->{'provmethod'}) {
|
|
# $provmethod = $ref->{'provmethod'};
|
|
# }
|
|
}
|
|
#}
|
|
}
|
|
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;
|
|
}
|
|
|
|
sub getNetworks
|
|
{
|
|
my $nettab = xCAT::Table->new('networks');
|
|
unless ($nettab) {
|
|
xCAT::MsgUtils->message("E", "Unable to open networks table");
|
|
return undef
|
|
}
|
|
my @nets = $nettab->getAllAttribs('net', 'mask', 'gateway');
|
|
|
|
return \@nets;
|
|
}
|
|
|
|
sub getDisklessNet()
|
|
{
|
|
my $nets = shift;
|
|
my $setbootfromnet = shift;
|
|
my $provmethod = shift;
|
|
|
|
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 ( ($os =~ /aix.*/i)
|
|
&& ($provmethod)
|
|
&& ($provmethod ne "install")
|
|
&& ($provmethod ne "netboot")
|
|
&& ($provmethod ne "statelite"))
|
|
{
|
|
my $nimtype;
|
|
my $nimimagetab = xCAT::Table->new('nimimage', -create => 1);
|
|
if ($nimimagetab)
|
|
{
|
|
(my $ref) =
|
|
$nimimagetab->getAttribs({imagename => $provmethod},
|
|
'nimtype');
|
|
if ($ref)
|
|
{
|
|
$nimtype = $ref->{'nimtype'};
|
|
}
|
|
}
|
|
if ($nimtype eq 'diskless')
|
|
{
|
|
$isdiskless = 1;
|
|
}
|
|
}
|
|
|
|
if ($isdiskless)
|
|
{
|
|
(my $ip, my $mask, my $gw) = xCAT::Postage::net_parms($node, $nets);
|
|
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;
|
|
|
|
}
|
|
|
|
sub collect_all_attribs_for_tables_in_template
|
|
{
|
|
my $table = shift;
|
|
my $nodes = shift;
|
|
my $callback = shift;
|
|
my $blankok;
|
|
if(defined($table) ) {
|
|
foreach my $tabname (keys %$table) {
|
|
my $key_hash = $table->{$tabname};
|
|
my @keys = keys %$key_hash;
|
|
my $key = $keys[0];
|
|
my $attrib_hash = $table->{$tabname}->{$key};
|
|
my @attribs = keys %$attrib_hash;
|
|
my $tabh = xCAT::Table->new($tabname);
|
|
unless ($tabh) {
|
|
xCAT::MsgUtils->message(
|
|
'E',
|
|
"Unable to open the table: $table."
|
|
);
|
|
return;
|
|
}
|
|
|
|
my $ent;
|
|
my $bynode=0;
|
|
if ($key eq "THISNODE" or $key eq '$NODE') {
|
|
$ent = $tabh->getNodesAttribs($nodes,@attribs);
|
|
if ($ent) {
|
|
foreach my $node (@$nodes) {
|
|
if( $ent->{$node}->[0] ) {
|
|
foreach my $attrib (@attribs) {
|
|
$::GLOBAL_TAB_HASH{$tabname}{$node}{$attrib} = $ent->{$node}->[0]->{$attrib};
|
|
|
|
#for noderes.xcatmaster
|
|
if ($tabname =~ /^noderes$/ && $attrib =~ /^xcatmaster$/ && ! exists($::GLOBAL_TAB_HASH{noderes}{$node}{xcatmaster}))
|
|
{
|
|
my $value;
|
|
$value = xCAT::NetworkUtils->my_ip_facing($node);
|
|
if ($value eq "0")
|
|
{
|
|
undef($value);
|
|
}
|
|
$::GLOBAL_TAB_HASH{$tabname}{$node}{$attrib} = $value;
|
|
}
|
|
|
|
# for nodetype.os and nodetype.arch
|
|
if ($^O =~ /^linux/i && $tabname =~ /^nodetype$/ && ($attrib =~ /^(os|arch)$/))
|
|
{
|
|
unless ( $::GLOBAL_TAB_HASH{nodetype}{$node}{'os'} or $::GLOBAL_TAB_HASH{nodetype}{$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 -1;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
# for noderes.nfsserver and noderes.tftpserver
|
|
if( defined($::GLOBAL_TAB_HASH{noderes}) && defined ($::GLOBAL_TAB_HASH{noderes}{$node} )
|
|
&& defined ($::GLOBAL_TAB_HASH{noderes}{$node}{xcatmaster} ) ) {
|
|
if(!defined ($::GLOBAL_TAB_HASH{noderes}{$node}{nfsserver}) ) {
|
|
$::GLOBAL_TAB_HASH{noderes}{$node}{nfsserver} = $::GLOBAL_TAB_HASH{noderes}{$node}{xcatmaster};
|
|
}
|
|
if(!defined ($::GLOBAL_TAB_HASH{noderes}{$node}{tftpserver}) ) {
|
|
$::GLOBAL_TAB_HASH{noderes}{$node}{tftpserver} = $::GLOBAL_TAB_HASH{noderes}{$node}{xcatmaster};
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
$tabh->close;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
1;
|