Author: nhosoi
Update of /cvs/dirsec/adminserver/admserv/newinst/src
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv17988/admserv/newinst/src
Added Files:
register_param.map.in register_server.pl.in
Log Message:
Resolves: #237356
Summary: Move DS Admin Code into Admin Server (Comment #58)
Description: adding the server registeration script and its data files
--- NEW FILE register_param.map.in ---
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
#
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
#
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception.
#
#
# Copyright (C) 2007 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#
# register_param.map:
# This file is used by the register_server.pl script to register the server
# info to the Configuration Directory Server. The server info is stored in
# the (template) ldif files located in @ldifdir@. In case a server entry has
# %...% format parameters, this map table is used to resolve it and replace
# the parameter with the value defined in this file.
#
# [Parameter resolution rules]
# * If the right-hand value is in ` (backquote), the value is eval'ed by perl.
# The output should be stored in $returnvalue to pass to the internal hash.
# * If the right-hand value is in " (doublequote), the value is passed as is.
# * If the right-hand value is not in any quote, the value should be found
# in either of the setup inf file (static) or the install inf file (dynamic).
# * Variables surrounded by @ (e.g., @configdir@) are replaced with the
# system path at the compile time.
# * The right-hand value can contain variables surrounded by % (e.g., %asid%)
# which refers the right-hand value (key) of this map file.
#
fqdn = `use Net::Domain qw(hostfqdn); $returnvalue = hostfqdn();`
domain = `use Net::Domain qw(hostdomain); $returnvalue = hostdomain();`
brand = Brand
normbrand = NormBrand
hostname = `use Net::Domain qw(hostname); $returnvalue = hostname();`
vendor = Vendor
uname_a = `open(UNAMEA, "uname -a |"); $returnvalue = <UNAMEA>; chomp
$returnvalue; close(UNAMEA);`
uname_m = `open(UNAMEM, "uname -m |"); $returnvalue = <UNAMEM>; chomp
$returnvalue; close(UNAMEM);`
configroot = "CONFIG ROOT -- replace me"
as_uid = ServerAdminID
as_passwd = ServerAdminPwd
asid = `use Net::Domain qw(hostname); $returnvalue = hostname();`
as_port = Port
admpw = "@configdir@/admpw"
as_error = "@logdir@/errors"
as_access = "@logdir@/access"
as_pid = "@pidfile@"
as_console_jar = "%normbrand%-admserv-%as_version%.jar"
as_help_path = "@helpdir@"
as_user = SysUser
as_version = Version
as_buildnum = BuildNumber
as_installedlocation = "AS INSTALLED LOCATION -- replace me"
as_serverroot = "AS SERVER ROOT-- replace me"
as_sie = "cn=admin-serv-%asid%, cn=%brand% Administration Server, cn=Server Group,
cn=%fqdn%, ou=%domain%, o=NetscapeRoot"
ds_version = Version
dsid = ServerIdentifier
ds_user = SuiteSpotUserID
ds_port = ServerPort
ds_secure_port ="636"
rootdn = RootDN
ds_suffix = Suffix
ds_buildnum = BuildNumber
ds_passwd = RootDNPwd
ds_console_jar ="%normbrand%-ds-%ds_version%.jar"
ds_installedlocation = "DS INSTALLED LOCATION -- replace me"
ds_serverroot = "DS SERVER ROOT-- replace me"
ds_sie = "cn=slapd-%dsid%, cn=%brand% Directory Server, cn=Server Group, cn=%fqdn%,
ou=%domain%, o=NetscapeRoot"
--- NEW FILE register_server.pl.in ---
# BEGIN COPYRIGHT BLOCK
# This Program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 2 of the License.
#
# This Program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
#
# In addition, as a special exception, Red Hat, Inc. gives You the additional
# right to link the code of this Program with code not covered under the GNU
# General Public License ("Non-GPL Code") and to distribute linked combinations
# including the two, subject to the limitations in this paragraph. Non-GPL Code
# permitted under this exception must only link to the code of this Program
# through those well defined interfaces identified in the file named EXCEPTION
# found in the source code files (the "Approved Interfaces"). The files of
# Non-GPL Code may instantiate templates or use macros or inline functions from
# the Approved Interfaces without causing the resulting work to be covered by
# the GNU General Public License. Only Red Hat, Inc. may make changes or
# additions to the list of Approved Interfaces. You must obey the GNU General
# Public License in all respects for all of the Program code and other code used
# in conjunction with the Program except the Non-GPL Code covered by this
# exception. If you modify this file, you may extend this exception to your
# version of the file, but you are not obligated to do so. If you do not wish to
# provide this exception without modification, you must delete this exception
# statement from your version and license this file solely under the GPL without
# exception.
#
#
# Copyright (C) 2007 Red Hat, Inc.
# All rights reserved.
# END COPYRIGHT BLOCK
#
# Usage: register_server.pl [ -h <host> ] [ -p <port> ] [ -D <rootdn> ]
\
# -w <rootdnpw> [ -d <default_infdir> ] \
# -i <inffile(s)> -m <mapfile> <ldiffile> ...
#
# Description: Store server info stored in the ldiffiles to the Configuration
# Directory Server replacing the macros with the defined values
# in the map file.
#
# -h <host>: configuration server host (localhost, by default)
# -p <port>: configuration server port (389)
# -D <rootdn>: configuration server's rootdn ("cn=Directory Manager")
# -w <rootdnpw>: configuration server's rootdn password
# -d <default_infdir>: the directory where static .inf files are located
# ("/usr/share/fedora-ds/inf")
# -i <inffile(s)>: dynamic .inf file(s)
# -m <mapfile>: map file name
# <ldiffile> ...: ldif file(s) or template ldif file(s) to be stored in
# the Configuration Directory Server
use Getopt::Std;
use Net::Domain qw(hostname);
# PERLDAP modules
use Mozilla::LDAP::Conn;
use Mozilla::LDAP::Entry;
# Setup Inf module
use Inf;
# process map table
# [map table sample]
# fqdn = FullMachineName
# hostname = `use Sys::Hostname; $returnvalue = hostname();`
# ds_console_jar ="%normbrand%-ds-%ds_version%.jar"
#
# * If the right-hand value is in ` (backquote), the value is eval'ed by perl.
# The output should be stored in $returnvalue to pass to the internal hash.
# * If the right-hand value is in " (doublequote), the value is passed as is.
# * If the right-hand value is not in any quote, the value should be found
# in either of the setup inf file (static) or the install inf file (dynamic).
# * Variables surrounded by @ (e.g., @admin_confdir@) are replaced with the
# system path at the compile time.
# * The right-hand value can contain variables surrounded by % (e.g., %asid%)
# which refers the right-hand value (key) of this map file.
sub process_maptbl
{
($mapper, @infdata) = @_;
foreach $section (keys %{$mapper})
{
my $thissection = \%{%{$mapper}->{$section}};
foreach $key (keys %{$thissection})
{
my $value = $thissection->{$key};
if ($value =~ /^\"/)
{
$value =~ tr/\"//d;
$thissection->{$key} = $value;
}
elsif ($value =~ /^\`/)
{
$value =~ tr/\`//d;
eval $value;
$thissection->{$key} = $returnvalue;
}
else
{
my $infsection;
foreach my $thisinf (@infdata)
{
foreach my $section0 (keys %{$thisinf})
{
$infsection = \%{%{$thisinf}->{$section0}};
if ("" ne $infsection->{$value})
{
$thissection->{$key} = $infsection->{$value};
goto nextkey;
}
}
}
if ("" eq $infsection->{$value})
{
print "ERROR: $value not found in the .inf files\n";
return NULL;
}
}
nextkey:
}
}
return $mapper;
}
# delete the subtree starting from the passed entry
sub delete_all
{
my ($conn, $bentry) = @_;
my $sentry = $conn->search($bentry->{dn},
"subtree", "(objectclass=*)", 0, ("dn"));
while ($sentry) {
push @mystack, ($sentry);
$sentry = $conn->nextEntry();
}
# reverse order
my $myentry = pop @mystack;
while ($myentry) {
$conn->delete($myentry->{dn});
$rc = $conn->getErrorCode();
if ( $rc ne 0 ) {
$conn->printError();
print "ERROR: unable to delete entry, error code: $rc\n";
return 1;
}
$myentry = pop @mystack;
}
return 0;
}
@ignorelist = (
"modifyTimestamp",
"createTimestamp",
"installationTimestamp",
"creatorsName",
"modifiersName",
"numSubordinates"
);
@speciallist = (
"uniqueMember"
);
sub is_in_array
{
my ($val, $array) = @_;
foreach my $elem ($array)
{
if ( lc($val) eq lc($elem) )
{
return 1;
}
}
return 0;
}
# compare 2 entries
# return 0 if they match 100% (exception: @ignorelist).
# return 1 if they match except @speciallist.
# return -1 if they do not match.
sub comp_entries
{
my ($e0, $e1) = @_;
$rc = 0;
foreach $akey ( keys %{$e0} )
{
next if ( 1 == is_in_array($akey, @ignorelist) );
$aval0 = $e0->{$akey};
$aval1 = $e1->{$akey};
my $amin;
my $amax;
if ( $#aval0 != $#aval1 )
{
if ( 1 == is_in_array($akey, @speciallist) )
{
$rc = 1;
if ( $#aval0 < $#aval1 )
{
$amin = $#aval0;
$amax = $#aval1;
}
else
{
$amin = $#aval1;
$amax = $#aval0;
}
}
else
{
$rc = -1;
return $rc;
}
}
@sval0 = sort { $a cmp $b } @{$aval0};
@sval1 = sort { $a cmp $b } @{$aval1};
for ( my $i = 0; $i <= $amin; $i++ )
{
my $isspecial = -1;
if ( $sval0[$i] ne $sval1[$i] )
{
if ( 0 > $isspecial )
{
$isspecial = is_in_array($akey, @speciallist);
}
if ( $isspecial )
{
$rc = 1;
}
else
{
$rc = -1;
return $rc;
}
}
}
}
return $rc;
}
# if the entry does not exist on the server, add the entry.
# otherwise, do nothing
sub check_and_add_entry
{
my ($conn, $aentry) = @_;
my $sentry = $conn->search($aentry->{dn}, "base",
"(objectclass=*)");
do
{
my $needtoadd = 1;
my $needtomod = 0;
my $rval = -1;
if ( NULL != $sentry && !$confds_fresh )
{
$rval = comp_entries( $sentry, $aentry );
}
if ( 0 == $rval && !$confds_fresh )
{
# the identical entry exists on the configuration DS.
# no need to add the entry.
$needtoadd = 0;
goto out;
}
elsif ( 1 == $rval && !$confds_fresh )
{
$needtoadd = 0;
$needtomod = 1;
}
elsif ( NULL != $sentry && "" ne $sentry->{dn} )
{
# $confds_fresh || $rval == -1
# an entry having the same DN exists, but the attributes do not
# match. remove the entry and the subtree underneath.
if ( $confds_verbose )
{
print "Deleting an entry dn: $sentry->{dn} ...\n";
}
$rval = delete_all($conn, $sentry);
if ( 0 != $rval )
{
return 1;
}
}
if ( 1 == $needtoadd )
{
$conn->add($aentry);
my $rc = $conn->getErrorCode();
if ( $rc != 0 )
{
print "ERROR: adding an entry $aentry->{dn} failed, error code: $rc\n";
print "[entry]\n";
$aentry->printLDIF();
$conn->close();
return 1;
}
# if ( $confds_verbose )
# {
# print "Entry $aentry->{dn} is added\n";
# }
}
elsif ( 1 == $needtomod ) # $sentry exists
{
foreach $attr ( @speciallist )
{
foreach $nval ( @{$aentry->{$attr}} )
{
$sentry->addValue( $attr, $nval );
}
}
$conn->update($sentry);
my $rc = $conn->getErrorCode();
if ( $rc != 0 )
{
print "ERROR: updating an entry $sentry->{dn} failed, error code:
$rc\n";
print "[entry]\n";
$aentry->printLDIF();
$conn->close();
return 1;
}
}
if ( NULL != $sentry )
{
$sentry = $conn->nextEntry(); # supposed to have no more entries
}
} until ( NULL == $sentry );
out:
return 0;
}
# register server info from the template ldif files
sub register_serverinfo
{
my ($conn, $mapper, @ldiffiles) = @_;
my $thissection = \%{%{$mapper}->{""}};
foreach my $ldiffile (@ldiffiles)
{
open(MYLDIF, "< $ldiffile") or die "Can't open $ldiffile :
$!";
if ( $confds_verbose )
{
print "Processing $ldiffile ...\n";
}
my $entry = NULL;
while ( my $l = <MYLDIF> )
{
chop $l;
if ( "$l" eq "" )
{
next if ( NULL == $entry );
check_and_add_entry($conn, $entry);
$entry->DESTROY();
$entry = NULL;
}
elsif ( "$l" =~ /^dn:/ )
{
$entry = new Mozilla::LDAP::Entry();
my ($h, $dn) = split(/: /, $l, 2);
# Need to repeat to handle nested subst
my $origdn = $dn;
while ( $dn =~ /%([A-Za-z_]+)%/ )
{
$dn =~ s{%([A-Za-z_]+)%}{$thissection->{$1} ||
"SERVER_INFO_NOTFOUND"}ge;
}
if ( $dn =~ /SERVER_INFO_NOTFOUND/ )
{
print "ERROR: \"$origdn\" mapped to \"$dn\".\n";
print "Make sure that %value% replaced by SERVER_INFO_NOTFOUND exists in
$mapfile.\n";
return 1;
}
$entry->setDN($dn);
}
else
{
my ($key, $value) = split(/: /, $l, 2);
# Need to repeat to handle nested subst
my $origvalue = $value;
while ( $value =~ /%([A-Za-z_]+)%/ )
{
$value =~ s{%([A-Za-z_]+)%}{$thissection->{$1} ||
"SERVER_INFO_NOTFOUND"}ge;
}
if ( $value =~ /SERVER_INFO_NOTFOUND/ )
{
print "ERROR: \"$origvalue\" mapped to \"$value\"\n";
print "Make sure that %value% replaced by SERVER_INFO_NOTFOUND exists in
$mapfile.\n";
return 1;
}
$entry->addValue( $key, "$value" )
}
}
close(MYLDIF);
if ( NULL != $entry )
{
check_and_add_entry($conn, $entry);
$entry->DESTROY();
$entry = NULL;
}
}
return 0;
}
$USAGE =
"$0 [ -Fv ] [ -h <host> ] [ -p <port> ] [ -D <rootdn> ] \
-w <rootdnpw> [ -d <default_infdir> ] \
-i <inffile(s)> ... -m <mapfile> <ldiffile>
...
Description: Store server info stored in the ldiffiles to the Configuration
Directory Server replacing the macros with the defined values
in the map file.
-H: help (print this message)
-v: verbose
-F: Fresh registration; i.e., removing the existing server info.
-h <host>: configuration server host (localhost, by default)
-p <port>: configuration server port (389)
-D <rootdn>: configuration server's rootdn (\"cn=Directory
Manager\")
-w <rootdnpw>: configuration server's rootdn password
-d <default_infdir>: the directory where static .inf files are located
(\"/usr/share/@PACKAGE_BASE_NAME@/inf\")
-i <inffile(s)>: dynamic .inf file(s)
-m <mapfile>: map file name
<ldiffile> ...: ldif files or template ldif files to be stored in the
Configuration Directory Server";
if ($#ARGV < 0 || !getopts('HFvh:p:D:w:d:m:i:') || $opt_H)
{
print "Usage: $USAGE\n";
exit 1;
}
$confds_verbose = $opt_v;
$confds_fresh = $opt_F;
$confds_host = $opt_h;
if ( "" eq $confds_host )
{
$confds_host = hostname();
}
$confds_port = $opt_p;
if ( "" eq $confds_port )
{
$confds_port = 389;
}
$confds_rootdn = $opt_D;
if ( "" eq $confds_rootdn )
{
$confds_rootdn = "cn=Directory Manager";
}
$confds_rootdnpw = $opt_w;
if ( "" eq $confds_rootdnpw )
{
print "ERROR: No root dn password\n";
print "usage: $USAGE\n";
exit 1;
}
my $infdir = $opt_d;
if ( "" eq $infdir )
{
$infdir = "/usr/share/@PACKAGE_BASE_NAME@/inf";
}
my @inffiles = ();
if ( "" eq $opt_i )
{
print "ERROR: No dynamic .inf files\n";
print "usage: $USAGE\n";
exit 1;
}
else
{
@inffiles = split(/[ ]/, $opt_i);
}
my @ldiffiles = @ARGV;
if ( 0 > $#ldiffiles )
{
print "ERROR: No root ldif files\n";
print "usage: $USAGE\n";
exit 1;
}
$mapfile = $opt_m;
if ( "" eq $mapfile )
{
print "ERROR: No mapfile\n";
print "usage: $USAGE\n";
exit 1;
}
if ( ! -r $mapfile )
{
print "ERROR: Cannot read $mapfile\n";
print "usage: $USAGE\n";
exit 1;
}
# reading info files
@infdata = ();
opendir(DIR, $infdir) or die "Cannot open install inf dir $infdir: $!";
while (defined($file = readdir(DIR)))
{
next if ( !("$file" =~ /\.inf$/) );
my $inffile = $infdir."/".$file;
my $infdatum = new Inf($inffile);
push(@infdata, ($infdatum));
}
closedir(DIR);
# open the ldap connection
$conn = new Mozilla::LDAP::Conn( $confds_host, $confds_port,
$confds_rootdn, $confds_rootdnpw );
if ( NULL == $conn )
{
print "ERROR: Cannot connect to the server\n";
exit 1;
}
# eval map table for each dynamic .inf file
foreach my $thisinf (@inffiles)
{
my $mapper = new Inf($mapfile);
my $infdatum = new Inf($thisinf);
push(@infdata, ($infdatum));
$mapper = process_maptbl($mapper, @infdata);
if ( NULL eq $mapper )
{
print "ERROR: failed to generate mapper\n";
exit 1;
}
# register server info
my $rc = register_serverinfo($conn, $mapper, @ldiffiles);
if ( 0 != $rc )
{
print "ERROR: failed to register server info\n";
return 1;
}
pop @infdata;
# in case handling multiple server instances,
# need to turn it off from the second loop.
$confds_fresh = 0;
}
$conn->close();
exit 0;