2007-10-26 22:44:33 +00:00
|
|
|
#!/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;
|
2010-03-09 22:00:00 +00:00
|
|
|
use xCAT::ADUtils; #to allow setting of one-time machine passwords
|
|
|
|
my $netdnssupport = eval {
|
|
|
|
require Net::DNS;
|
|
|
|
1;
|
|
|
|
};
|
2007-10-26 22:44:33 +00:00
|
|
|
|
2008-03-10 14:20:47 +00:00
|
|
|
my $tmplerr;
|
2007-10-26 22:44:33 +00:00
|
|
|
my $table;
|
|
|
|
my $key;
|
|
|
|
my $field;
|
|
|
|
my $idir;
|
|
|
|
my $node;
|
2010-03-09 22:00:00 +00:00
|
|
|
my %loggedrealms;
|
2007-10-26 22:44:33 +00:00
|
|
|
|
|
|
|
sub subvars {
|
|
|
|
my $self = shift;
|
|
|
|
my $inf = shift;
|
|
|
|
my $outf = shift;
|
|
|
|
$node = shift;
|
|
|
|
my $outh;
|
|
|
|
my $inh;
|
|
|
|
$idir = dirname($inf);
|
|
|
|
open($inh,"<",$inf);
|
|
|
|
unless ($inh) {
|
2008-03-10 14:20:47 +00:00
|
|
|
return "Unable to open $inf, aborting";
|
2007-10-26 22:44:33 +00:00
|
|
|
}
|
|
|
|
mkpath(dirname($outf));
|
|
|
|
open($outh,">",$outf);
|
|
|
|
unless($outh) {
|
2008-03-10 14:20:47 +00:00
|
|
|
return "Unable to open $outf for writing/creation, aborting";
|
2007-10-26 22:44:33 +00:00
|
|
|
}
|
|
|
|
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');
|
|
|
|
if ($et and $et->{value}) {
|
|
|
|
$master = $et->{value};
|
|
|
|
}
|
|
|
|
$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;
|
2009-05-11 20:46:03 +00:00
|
|
|
|
|
|
|
#replace the env with the right value so that correct include files can be found
|
|
|
|
$inc =~ s/#ENV:([^#]+)#/envvar($1)/eg;
|
|
|
|
|
2007-10-26 22:44:33 +00:00
|
|
|
#FIRST, do *all* includes, recursive and all
|
|
|
|
my $doneincludes=0;
|
|
|
|
while (not $doneincludes) {
|
|
|
|
$doneincludes=1;
|
2010-04-15 18:31:46 +00:00
|
|
|
if ($inc =~ /#INCLUDE_PKGLIST:[^#^\n]+#/) {
|
2010-04-13 17:30:54 +00:00
|
|
|
$doneincludes=0;
|
2010-04-15 18:31:46 +00:00
|
|
|
$inc =~ s/#INCLUDE_PKGLIST:([^#^\n]+)#/includefile($1, 0, 1)/eg;
|
2010-04-13 17:30:54 +00:00
|
|
|
}
|
2010-04-15 18:31:46 +00:00
|
|
|
if ($inc =~ /#INCLUDE:[^#^\n]+#/) {
|
2007-10-26 22:44:33 +00:00
|
|
|
$doneincludes=0;
|
2010-04-15 18:31:46 +00:00
|
|
|
$inc =~ s/#INCLUDE:([^#^\n]+)#/includefile($1, 0, 0)/eg;
|
2007-10-26 22:44:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#ok, now do everything else..
|
2009-09-02 15:16:05 +00:00
|
|
|
$inc =~ s/#XCATVAR:([^#]+)#/envvar($1)/eg;
|
|
|
|
$inc =~ s/#ENV:([^#]+)#/envvar($1)/eg;
|
2010-03-09 22:00:00 +00:00
|
|
|
$inc =~ s/#MACHINEPASSWORD#/machinepassword()/eg;
|
2007-10-26 22:44:33 +00:00
|
|
|
$inc =~ s/#TABLE:([^:]+):([^:]+):([^#]+)#/tabdb($1,$2,$3)/eg;
|
2008-03-20 17:38:25 +00:00
|
|
|
$inc =~ s/#TABLEBLANKOKAY:([^:]+):([^:]+):([^#]+)#/tabdb($1,$2,$3,'1')/eg;
|
2007-10-26 22:44:33 +00:00
|
|
|
$inc =~ s/#CRYPT:([^:]+):([^:]+):([^#]+)#/crydb($1,$2,$3)/eg;
|
2009-09-02 15:16:05 +00:00
|
|
|
$inc =~ s/#COMMAND:([^#]+)#/command($1)/eg;
|
2010-04-15 18:31:46 +00:00
|
|
|
$inc =~ s/#INCLUDE_NOP:([^#^\n]+)#/includefile($1,1,0)/eg;
|
|
|
|
$inc =~ s/#INCLUDE_PKGLIST:([^#^\n]+)#/includefile($1,0,1)/eg;
|
|
|
|
$inc =~ s/#INCLUDE:([^#^\n]+)#/includefile($1, 0, 0)/eg;
|
2009-09-30 17:27:42 +00:00
|
|
|
|
2009-07-10 18:34:09 +00:00
|
|
|
|
2008-03-10 14:20:47 +00:00
|
|
|
if ($tmplerr) {
|
|
|
|
close ($outh);
|
|
|
|
return $tmplerr;
|
|
|
|
}
|
2007-10-26 22:44:33 +00:00
|
|
|
print $outh $inc;
|
|
|
|
close($outh);
|
2008-03-10 14:20:47 +00:00
|
|
|
return 0;
|
2007-10-26 22:44:33 +00:00
|
|
|
}
|
2010-03-09 22:00:00 +00:00
|
|
|
sub machinepassword {
|
|
|
|
my $domaintab = xCAT::Table->new('domain');
|
|
|
|
$ENV{LDAPCONF}='/etc/xcat/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');
|
|
|
|
if ($et and $et->{value}) {
|
|
|
|
$domain = $et->{value};
|
|
|
|
}
|
|
|
|
unless ($domain) {
|
|
|
|
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']);
|
|
|
|
if ($server and $server->{value}) {
|
|
|
|
$server = $server->{value};
|
|
|
|
} 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 {
|
|
|
|
return $data->{password};
|
|
|
|
}
|
|
|
|
}
|
2007-10-26 22:44:33 +00:00
|
|
|
sub includefile
|
|
|
|
{
|
2009-07-10 18:34:09 +00:00
|
|
|
my $file = shift;
|
|
|
|
my $special=shift;
|
2010-04-13 17:30:54 +00:00
|
|
|
my $pkglist=shift;
|
2009-07-10 18:34:09 +00:00
|
|
|
my $text = "";
|
2007-10-26 22:44:33 +00:00
|
|
|
unless ($file =~ /^\//) {
|
|
|
|
$file = $idir."/".$file;
|
|
|
|
}
|
|
|
|
|
2010-03-09 22:00:00 +00:00
|
|
|
open(INCLUDE,$file) || return "#INCLUDEBAD:cannot open $file#";
|
2009-07-10 18:34:09 +00:00
|
|
|
|
2010-04-13 17:30:54 +00:00
|
|
|
my $pkgb = "";
|
|
|
|
my $pkge = "";
|
|
|
|
if ($pkglist) {
|
|
|
|
$pkgb = "<package>";
|
|
|
|
$pkge = "</package>";
|
|
|
|
}
|
2009-07-10 18:34:09 +00:00
|
|
|
while(<INCLUDE>) {
|
2010-04-13 17:30:54 +00:00
|
|
|
if ($pkglist) {
|
|
|
|
s/#INCLUDE:/#INCLUDE_PKGLIST:/;
|
|
|
|
}
|
|
|
|
if (( $_ =~ /^\s*#/ ) || ( $_ =~ /^\s*$/ )) {
|
|
|
|
$text .= "$_";
|
|
|
|
} else {
|
|
|
|
chomp;
|
|
|
|
s/\s*$//;
|
|
|
|
$text .= "$pkgb$_$pkge\n";
|
|
|
|
}
|
2009-07-10 18:34:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
close(INCLUDE);
|
|
|
|
|
|
|
|
if ($special) {
|
|
|
|
$text =~ s/\$/\\\$/g;
|
|
|
|
$text =~ s/`/\\`/g;
|
|
|
|
}
|
2007-10-26 22:44:33 +00:00
|
|
|
|
2009-07-10 18:34:09 +00:00
|
|
|
chomp($text);
|
|
|
|
return($text);
|
2007-10-26 22:44:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2008-03-20 17:38:25 +00:00
|
|
|
my $blankok = shift;
|
2007-10-26 22:44:33 +00:00
|
|
|
my $tabh = xCAT::Table->new($table);
|
2008-03-10 14:20:47 +00:00
|
|
|
unless ($tabh) {
|
|
|
|
$tmplerr="Unable to open table named $table";
|
|
|
|
if ($table =~ /\.tab/) {
|
2008-03-10 14:45:35 +00:00
|
|
|
$tmplerr .= " (.tab should not be specified as part of the table name in xCAT 2, as seems to be the case here)";
|
2008-03-10 14:20:47 +00:00
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
2007-10-26 22:44:33 +00:00
|
|
|
my $ent;
|
2009-06-17 21:03:08 +00:00
|
|
|
my $bynode=0;
|
2007-10-26 22:44:33 +00:00
|
|
|
if ($key eq "THISNODE" or $key eq '$NODE') {
|
|
|
|
$ent = $tabh->getNodeAttribs($node,[$field]);
|
2008-05-16 19:03:18 +00:00
|
|
|
$key="node=$node";
|
2007-10-26 22:44:33 +00:00
|
|
|
} else {
|
|
|
|
my %kp;
|
|
|
|
foreach (split /,/,$key) {
|
|
|
|
my $key;
|
|
|
|
my $val;
|
2009-06-17 21:03:08 +00:00
|
|
|
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);
|
2007-10-26 22:44:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
$tabh->close;
|
2007-11-19 19:45:11 +00:00
|
|
|
unless($ent and defined($ent->{$field})) {
|
2008-03-20 17:38:25 +00:00
|
|
|
unless ($blankok) {
|
2008-05-16 19:03:18 +00:00
|
|
|
$tmplerr="Unable to find requested $field from $table, with $key";
|
2008-03-20 17:38:25 +00:00
|
|
|
}
|
2007-11-19 19:45:11 +00:00
|
|
|
return "";
|
|
|
|
#return "#TABLEBAD:$table:field $field not found#";
|
2007-10-26 22:44:33 +00:00
|
|
|
}
|
|
|
|
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#"
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|