summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRich Megginson <rmeggins@redhat.com>2007-07-04 01:28:17 +0000
committerRich Megginson <rmeggins@redhat.com>2007-07-04 01:28:17 +0000
commitaf10ba6ae36a6f50ff55be43da77fac0c38542a5 (patch)
tree9f490a8d72ebcac9e84e2bfd394fedd59c3f996c
parent24b026971adfd97c4ff542aa56211250b54abc97 (diff)
downloadds-af10ba6ae36a6f50ff55be43da77fac0c38542a5.tar.gz
ds-af10ba6ae36a6f50ff55be43da77fac0c38542a5.tar.xz
ds-af10ba6ae36a6f50ff55be43da77fac0c38542a5.zip
Resolves: bug 246683
Bug Description: Reimplement ds_create without setuputil code Reviewed by: nhosoi (Thanks!) Fix Description: ds_create was a CGI program that would create a new instance, set it up to be managed by console, and register it with the config ds. The new ds_create CGI perl script does just that. One tricky part was that, rather than enabling the pass through auth plugin and having to restart the server, the new server is created without being started, then the modification is done to the new server dse.ldif file directly, using the new FileConn.pm module, which simulates a Mozilla::LDAP::Conn on an LDIF file. This also allows us to create a new instance with a pre-hashed rootdn password, rather than having to send the cleartext password. I had to move around some code in AdminServer and AdminUtil so that I could use it from ds_create. I also implemented support for the admin server PASSWORD_PIPE in perl so we could use it in other CGI perl scripts. Finally, the error handling was not consistent in our code, so I made explicit the passing of error messages up and down the stack. Oh how I wish we could just do this in python and use exception handling . . . I added a test for ds_create. Platforms tested: RHEL4 Flag Day: Yes - autotool changes Doc impact: No. Should work the same way as the old ds_create.
-rw-r--r--Makefile.am3
-rw-r--r--Makefile.in3
-rw-r--r--ldap/admin/src/scripts/DSMigration.pm.in10
-rw-r--r--ldap/admin/src/scripts/FileConn.pm389
-rw-r--r--ldap/admin/src/scripts/Resource.pm4
-rw-r--r--ldap/admin/src/scripts/Util.pm.in64
-rw-r--r--ldap/admin/src/scripts/setup-ds.pl.in4
-rw-r--r--ldap/admin/src/scripts/setup-ds.res.in6
8 files changed, 451 insertions, 32 deletions
diff --git a/Makefile.am b/Makefile.am
index ea116701..236041a3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -200,7 +200,8 @@ perl_SCRIPTS = ldap/admin/src/scripts/SetupLog.pm \
ldap/admin/src/scripts/DSDialogs.pm \
ldap/admin/src/scripts/Setup.pm \
ldap/admin/src/scripts/Migration.pm \
- ldap/admin/src/scripts/DSMigration.pm
+ ldap/admin/src/scripts/DSMigration.pm \
+ ldap/admin/src/scripts/FileConn.pm
property_DATA = ldap/admin/src/scripts/setup-ds.res \
ldap/admin/src/scripts/migrate-ds.res
diff --git a/Makefile.in b/Makefile.in
index 6235d97b..abb30db3 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1137,7 +1137,8 @@ perl_SCRIPTS = ldap/admin/src/scripts/SetupLog.pm \
ldap/admin/src/scripts/DSDialogs.pm \
ldap/admin/src/scripts/Setup.pm \
ldap/admin/src/scripts/Migration.pm \
- ldap/admin/src/scripts/DSMigration.pm
+ ldap/admin/src/scripts/DSMigration.pm \
+ ldap/admin/src/scripts/FileConn.pm
property_DATA = ldap/admin/src/scripts/setup-ds.res \
ldap/admin/src/scripts/migrate-ds.res
diff --git a/ldap/admin/src/scripts/DSMigration.pm.in b/ldap/admin/src/scripts/DSMigration.pm.in
index 86f0cb4d..0e037044 100644
--- a/ldap/admin/src/scripts/DSMigration.pm.in
+++ b/ldap/admin/src/scripts/DSMigration.pm.in
@@ -374,6 +374,7 @@ sub migrateDS {
my $mig = shift;
$pkgname = $mig->{pkgname}; # set globals
$oldsroot = $mig->{oldsroot}; # set globals
+ my @errs;
# for each instance
foreach my $inst (@{$mig->{instances}}) {
@@ -388,13 +389,18 @@ sub migrateDS {
# extract the information needed for ds_newinst.pl
my $configdir = "$oldsroot/$inst/config";
- my $inf = createInfFromConfig($configdir, $inst);
+ my $inf = createInfFromConfig($configdir, $inst, \@errs);
debug(2, "Using inffile $inf->{filename} created from $configdir\n");
+ if (@errs) {
+ $mig->msg(@errs);
+ return 0;
+ }
# create the new instance
- my ($rc, $output) = createDSInstance($inf);
+ my ($rc, $output) = createDSInstance($inf, \@errs);
unlink($inf->{filename});
if ($rc) {
+ $mig->msg(@errs);
$mig->msg($FATAL, 'error_creating_dsinstance', $rc, $output);
return 0;
} else {
diff --git a/ldap/admin/src/scripts/FileConn.pm b/ldap/admin/src/scripts/FileConn.pm
new file mode 100644
index 00000000..c777b156
--- /dev/null
+++ b/ldap/admin/src/scripts/FileConn.pm
@@ -0,0 +1,389 @@
+# 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
+#
+# FileConn is a subclass of Mozilla::LDAP::Conn. This class does
+# not use LDAP. Instead, it operates on a given LDAP file, allowing
+# you to search, add, modify, and delete entries in the file.
+#
+package FileConn;
+
+use Mozilla::LDAP::Conn;
+use Mozilla::LDAP::API qw(:constant ldap_explode_dn ldap_err2string); # Direct access to C API
+use Mozilla::LDAP::Utils qw(normalizeDN);
+use Mozilla::LDAP::LDIF;
+
+require Exporter;
+@ISA = qw(Exporter Mozilla::LDAP::Conn);
+@EXPORT = qw();
+@EXPORT_OK = qw();
+
+sub new {
+ my $class = shift;
+ my $filename = shift;
+ my $self = {};
+
+ $self = bless $self, $class;
+
+ $self->read($filename);
+
+ return $self;
+}
+
+sub getParentDN {
+ my $dn = shift;
+ my @rdns = ldap_explode_dn($dn, 0);
+ shift @rdns;
+ return join(',', @rdns);
+}
+
+sub read {
+ my $self = shift;
+ my $filename = shift;
+
+ if ($filename) {
+ $self->{filename} = $filename;
+ } else {
+ $filename = $self->{filename};
+ }
+
+ if (!$self->{filename}) {
+ return;
+ }
+
+ open( MYLDIF, "$filename" ) || die "Can't open $filename: $!";
+ my $in = new Mozilla::LDAP::LDIF(*MYLDIF);
+ while ($ent = readOneEntry $in) {
+ if (!$self->add($ent)) {
+ die "Error: could not add entry ", $ent->getDN(), ":", $self->getErrorString();
+ }
+ }
+ close( MYLDIF );
+}
+
+# return all nodes below the given node
+sub iterate {
+ my $self = shift;
+ my $dn = shift;
+ my $scope = shift;
+ my $callback = shift;
+ my $context = shift;
+ my $suppress = shift;
+ my $ndn = normalizeDN($dn);
+ my $children = $self->{$ndn}->{children};
+ if (($scope != LDAP_SCOPE_ONELEVEL) && $self->{$ndn}->{data} && !$suppress) {
+ &{$callback}($self->{$ndn}->{data}, $context);
+ }
+
+ if ($scope == LDAP_SCOPE_BASE) {
+ return;
+ }
+
+ for my $node (@{$children}) {
+ &{$callback}($node->{data}, $context);
+ }
+ if ($scope == LDAP_SCOPE_SUBTREE) {
+ for my $node (@{$children}) {
+ $self->iterate($node->{data}->getDN(), $scope, $callback, $context, 1);
+ }
+ }
+}
+
+sub writecb {
+ my $entry = shift;
+ my $fh = shift;
+ if (! $entry->getDN()) { # rootDSE requires special hack around perldap bug
+ my $ary = $entry->getLDIFrecords();
+ shift @$ary; # remove "dn"
+ shift @$ary; # remove the empty dn value
+ print $fh "dn:\n";
+ print $fh (Mozilla::LDAP::LDIF::pack_LDIF (78, $ary), "\n");
+ } else {
+ Mozilla::LDAP::LDIF::put_LDIF($fh, 78, $entry);
+ }
+}
+
+sub write {
+ my $self = shift;
+ my $filename = shift;
+
+ if ($filename) {
+ $self->{filename} = $filename;
+ } else {
+ $filename = $self->{filename};
+ }
+
+ if (!$self->{filename}) {
+ return;
+ }
+
+ open( MYLDIF, ">$filename" ) || die "Can't write $filename: $!";
+ $self->iterate("", LDAP_SCOPE_SUBTREE, \&writecb, \*MYLDIF);
+ close( MYLDIF );
+}
+
+sub setErrorCode {
+ my $self = shift;
+ $self->{lastErrorCode} = shift;
+}
+
+sub getErrorCode {
+ my $self = shift;
+ return $self->{lastErrorCode};
+}
+
+sub getErrorString {
+ my $self = shift;
+ return ($self->{lastErrorCode} ? ldap_err2string($self->{lastErrorCode}) : LDAP_SUCCESS);
+}
+
+#############################################################################
+# Print the last error code...
+#
+sub printError
+{
+ my ($self, $str) = @_;
+
+ $str = "LDAP error:" unless defined($str);
+ print "$str ", $self->getErrorString(), "\n";
+}
+
+sub close {
+ my $self = shift;
+ $self->write();
+}
+
+sub printcb {
+ my $entry = shift;
+
+ print $entry->getDN(), "\n";
+}
+
+sub print {
+ my $self = shift;
+ my $dn = shift;
+ my $scope = shift;
+ $self->iterate($dn, $scope, \&printcb);
+}
+
+# for each entry, call the user provided filter callback
+# with the entry and the user provided filter context
+# if the filtercb returns true, add the entry to the
+# list of entries to return
+sub searchcb {
+ my $entry = shift;
+ my $context = shift;
+ my $self = $context->[0];
+ my $filtercb = $context->[1];
+ my $filtercontext = $context->[2];
+ if (&{$filtercb}($entry, $filtercontext)) {
+ push @{$self->{entries}}, $entry;
+ }
+}
+
+sub matchall {
+ return 1;
+}
+
+sub matchAttrVal {
+ my $entry = shift;
+ my $context = shift;
+ my $attr = $context->[0];
+ my $val = $context->[1];
+
+ if ($val eq "*") {
+ return $entry->exists($attr);
+ }
+ return $entry->hasValue($attr, $val, 1);
+}
+
+my $attrpat = '[-;.:\w]*[-;\w]';
+
+# given a string filter, figure out which subroutine to
+# use to match
+sub filterToMatchSub {
+ my $self = shift;
+ my ($basedn, $scope, $filter, $attrsonly, @rest) = @_;
+ my ($matchsub, $context);
+# do some filter processing
+ if (!$filter or ($filter eq "(objectclass=*)") or
+ ($filter eq "objectclass=*")) {
+ $matchsub = \&matchall;
+ } elsif ($filter =~ /^\(($attrpat)=(.+)\)$/o) {
+ push @{$context}, $1, $2;
+ $matchsub = \&matchAttrVal;
+# } elsif ($filter =~ /^\(\|\(($attrpat)=(.+)\)\(($attrpat)=(.+)\)\)$/o) {
+# $attr = $1;
+# $val = $2;
+# $attr1 = $1;
+# $val1 = $2;
+# $isand = 0;
+# } elsif ($filter =~ /^\(\&\(($attrpat)=(.+)\)\(($attrpat)=(.+)\)\)$/o) {
+# $attr = $1;
+# $val = $2;
+# $attr1 = $1;
+# $val1 = $2;
+# $isand = 1;
+# } elsif ($filter =~ /^\(\|\(($attrpat)=(.+)\)\(($attrpat)=(.+)\)\)$/o) {) {
+# # "(&(objectclass=nsBackendInstance)(|(nsslapd-suffix=$suffix)(nsslapd-suffix=$nsuffix)))");
+ }
+
+ $self->iterate($basedn, $scope, \&searchcb, [$self, $matchsub, $context]);
+}
+
+# simple searches only
+sub search {
+ my $self = shift;
+ my ($basedn, $scope, $filter, $attrsonly, @rest) = @_;
+ my $attrs;
+ if (ref($rest[0]) eq "ARRAY") {
+ $attrs = $rest[0];
+ } elsif (scalar(@rest) > 0) {
+ $attrs = \@rest;
+ }
+
+ $scope = Mozilla::LDAP::Utils::str2Scope($scope);
+
+ $self->{entries} = [];
+
+ my $ndn = normalizeDN($basedn);
+ if (!exists($self->{$ndn})) {
+ $self->setErrorCode(LDAP_NO_SUCH_OBJECT);
+ return undef;
+ }
+
+ $self->setErrorCode(0);
+ if (ref($filter) eq 'CODE') {
+ $self->iterate($basedn, $scope, \&searchcb, [$self, $filter, $attrsonly]);
+ } else {
+ $self->filterToMatchSub($basedn, $scope, $filter, $attrsonly);
+ }
+
+ return $self->nextEntry();
+}
+
+sub nextEntry {
+ my $self = shift;
+ return shift @{$self->{entries}};
+}
+
+sub add {
+ my $self = shift;
+ my $entry = shift;
+ my $dn = $entry->getDN();
+ my $ndn = normalizeDN($dn);
+ my $parentdn = getParentDN($dn);
+ my $nparentdn = normalizeDN($parentdn);
+
+ $self->setErrorCode(0);
+ if (exists($self->{$ndn})) {
+ $self->setErrorCode(LDAP_ALREADY_EXISTS);
+ return 0;
+ }
+ if ($nparentdn && !exists($self->{$nparentdn})) {
+ $self->setErrorCode(LDAP_NO_SUCH_OBJECT);
+ return 0;
+ }
+ # each hash entry has two keys
+ # data is the actual Entry
+ # children is the array ref of the one level children of this dn
+ $self->{$ndn}->{data} = $entry;
+ push @{$self->{$nparentdn}->{children}}, $self->{$ndn};
+
+ return 1;
+}
+
+sub update {
+ my $self = shift;
+ my $entry = shift;
+ my $dn = $entry->getDN();
+ my $ndn = normalizeDN($dn);
+
+ $self->setErrorCode(0);
+ if (!exists($self->{$ndn})) {
+ $self->setErrorCode(LDAP_NO_SUCH_OBJECT);
+ return 0;
+ }
+
+ $self->{$ndn}->{data} = $entry;
+
+ return 1;
+}
+
+sub delete {
+ my $self = shift;
+ my $dn = shift;
+
+ if (ref($dn)) {
+ $dn = $dn->getDN(); # an Entry
+ }
+ my $ndn = normalizeDN($dn);
+
+ $self->setErrorCode(0);
+ if (!exists($self->{$ndn})) {
+ $self->setErrorCode(LDAP_NO_SUCH_OBJECT);
+ return 0;
+ }
+
+ if (@{$self->{$ndn}->{children}}) {
+ $self->setErrorCode(LDAP_NOT_ALLOWED_ON_NONLEAF);
+ return 0;
+ }
+
+ # delete the data associated with this node
+ delete $self->{$ndn}->{data};
+ delete $self->{$ndn}->{children};
+
+ my $parentdn = getParentDN($dn);
+ my $nparentdn = normalizeDN($parentdn);
+ # delete this node from its parent
+ for (my $ii = 0; $ii < @{$self->{$nparentdn}->{children}}; ++$ii) {
+ # find matching hash ref in parent's child list
+ if ($self->{$nparentdn}->{children}->[$ii] eq $self->{$ndn}) {
+ # remove that element from the array
+ splice @{$self->{$nparentdn}->{children}}, $ii, 1;
+ # done - should only ever be one matching child
+ last;
+ }
+ }
+
+ # delete this node
+ delete $self->{$ndn};
+
+ return 0;
+}
+
+1;
diff --git a/ldap/admin/src/scripts/Resource.pm b/ldap/admin/src/scripts/Resource.pm
index 4bc52a74..1fcd44ca 100644
--- a/ldap/admin/src/scripts/Resource.pm
+++ b/ldap/admin/src/scripts/Resource.pm
@@ -112,7 +112,9 @@ sub read {
}
}
# replace \n with real newline
- $self->{res}->{$curkey} =~ s/\\n/\n/g;
+ if (defined($curkey)) {
+ $self->{res}->{$curkey} =~ s/\\n/\n/g;
+ }
close RES;
}
}
diff --git a/ldap/admin/src/scripts/Util.pm.in b/ldap/admin/src/scripts/Util.pm.in
index 008b4210..355aed73 100644
--- a/ldap/admin/src/scripts/Util.pm.in
+++ b/ldap/admin/src/scripts/Util.pm.in
@@ -119,8 +119,7 @@ sub delete_all
$conn->delete($dn);
my $rc = $conn->getErrorCode();
if ( $rc != 0 ) {
- $conn->printError();
- print "ERROR: unable to delete entry $dn, error code: $rc\n";
+ debug(1, "ERROR: unable to delete entry $dn, error code: $rc:" . $conn->getErrorString() . "\n");
return 1;
}
$dn = pop @mystack;
@@ -220,7 +219,7 @@ sub comp_entries
# $verbose prints out more info
sub check_and_add_entry
{
- my ($context, $aentry) = @_;
+ my ($context, $aentry, $errs) = @_;
my $conn = $context->[0];
my $fresh = $context->[1];
my $verbose = $context->[2];
@@ -277,6 +276,7 @@ sub check_and_add_entry
$rc = delete_all($conn, $sentry);
if ( 0 != $rc )
{
+ push @{$errs}, 'error_deleteall_entries', $sentry->{dn}, $conn->getErrorString();
debug(1, "Error deleting $sentry->{dn}\n");
return 0;
}
@@ -305,8 +305,8 @@ sub check_and_add_entry
if ( $rc != 0 )
{
my $string = $conn->getErrorString();
- print "ERROR: adding an entry $aentry->{dn} failed, error: $string\n";
- print "[entry]\n";
+ push @{$errs}, 'error_adding_entry', $aentry->{dn}, $string;
+ debug(1, "ERROR: adding an entry $aentry->{dn} failed, error: $string\n");
$aentry->printLDIF();
$conn->close();
return 0;
@@ -359,8 +359,8 @@ sub check_and_add_entry
if ( $rc != 0 )
{
my $string = $conn->getErrorString();
- print "ERROR: updating an entry $sentry->{dn} failed, error: $string\n";
- print "[entry]\n";
+ push @{$errs}, 'error_updating_entry', $sentry->{dn}, $string;
+ debug(1, "ERROR: updating an entry $sentry->{dn} failed, error: $string\n");
$aentry->printLDIF();
$conn->close();
return 0;
@@ -396,12 +396,14 @@ sub cbaddent {
# and the values are the replacements
# ldiffiles - an array ref - the list of LDIF files to
# operate on
+# errs - an array ref - this is filled in with the
+# errors encountered in processing - this is
+# suitable for passing to setup->msg or
+# Resource->getText
# callback (optional) - a code ref - a ref to a subroutine
# that will be called with each entry - see below
# context (optional) - this will be passed as the first
# argument to your given callback - see below
-# errs (optional) - an array ref - This is how errors
-# are returned to the caller - see below
# Callback:
# The callback sub will be called for each entry after
# the entry has been converted. The callback will be
@@ -413,18 +415,20 @@ sub cbaddent {
# abort processing of any further.
# Errors:
# This function should return an array of errors in the
-# format described below, for use with Resource::getText().
-# If the callback returns any errors
+# format described below, for use with Resource::getText()
+# or Setup::msg()
# Return:
# The return value is a list of entries.
# Example usage:
# sub handle_entries {
# my $context = shift;
# my $entry = shift;
+# my $errs = shift;
# .... do something with entry ....
# .... if $context is Mozilla::LDAP::Conn, $conn->add($entry); ...
# .... report errors ....
# if ($fatalerror) {
+# push @{$errs}, 'error_token', arg1, arg2, ...;
# return 0;
# } else {
# return 1;
@@ -433,14 +437,16 @@ sub cbaddent {
# $mapper = {foo => 'bar', baz => 'biff'};
# @ldiffiles = ('foo.ldif', 'bar.ldif', ..., 'biff.ldif');
# $conn = new Mozilla::LDAP::Conn(...);
-# @entries = getMappedEntries($mapper, \@ldiffiles, \&handle_entries, $conn);
+# my @errs;
+# @entries = getMappedEntries($mapper, \@ldiffiles, \@errs, \&handle_entries, $conn);
# Note that this will return 0 entries since a callback was used.
# The simpler example is this:
-# @entries = getMappedEntries($mapper, \@ldiffiles);
+# @entries = getMappedEntries($mapper, \@ldiffiles, \@errs);
#
sub getMappedEntries {
my $mapper = shift;
my $ldiffiles = shift;
+ my $errs = shift;
my $callback = shift || \&cbaddent; # default - just add entry to @entries
my @entries = ();
my $context = shift || \@entries;
@@ -451,7 +457,10 @@ sub getMappedEntries {
}
foreach my $ldiffile (@{$ldiffiles}) {
- open(MYLDIF, "< $ldiffile") or die "Can't open $ldiffile : $!";
+ if (!open(MYLDIF, "< $ldiffile")) {
+ push @{$errs}, "error_opening_ldiftmpl", $ldiffile, $!;
+ return 0;
+ }
my $in = new Mozilla::LDAP::LDIF(*MYLDIF);
debug(1, "Processing $ldiffile ...\n");
ENTRY: while (my $entry = Mozilla::LDAP::LDIF::readOneEntry($in)) {
@@ -462,9 +471,7 @@ sub getMappedEntries {
if (exists($mapper->{$1})) {
$dn =~ s{%([\w_-]+)%}{$mapper->{$1}}ge;
} else {
- print "ERROR: \"$origdn\" mapped to \"$dn\".\n";
- print "The LDIF file $ldiffile contains a token $1 for which there is no mapper.\n";
- print "Please check $ldiffile and your mapper to make sure all tokens are handled correctly.\n";
+ push @{$errs}, 'error_mapping_token_ldiftmpl', $dn, $ldiffile, $1;
$error = 1;
last ENTRY;
}
@@ -480,9 +487,8 @@ sub getMappedEntries {
if (exists($mapper->{$1})) {
$value =~ s{%([\w_-]+)%}{$mapper->{$1}}ge;
} else {
- print "ERROR: \"$origvalue\" mapped to \"$value\".\n";
- print "The LDIF file $ldiffile contains a token $1 for which there is no mapper.\n";
- print "Please check $ldiffile and your mapper to make sure all tokens are handled correctly.\n";
+ push @{$errs}, 'error_mapping_token_ldiftmpl', $dn, $ldiffile, $1;
+ debug(1, "ERROR: \"$origvalue\" mapped to \"$value\".\n");
$error = 1;
last ENTRY;
}
@@ -492,9 +498,9 @@ sub getMappedEntries {
$entry->setValues( $attr, @newvalues );
}
- if (!&{$callback}($context, $entry)) {
- print "There was an error processing entry ", $entry->getDN(), "\n";
- print "Cannot continue processing entries.\n";
+ if (!&{$callback}($context, $entry, $errs)) {
+ debug(1, "ERROR: There was an error processing entry ". $entry->getDN(). "\n");
+ debug(1, "Cannot continue processing entries.\n");
$error = 1;
last ENTRY;
}
@@ -640,7 +646,7 @@ sub addSuffix {
# The %token% tokens are replaced in getMappedEntries
sub process_maptbl
{
- my ($mapper, @infdata) = @_;
+ my ($mapper, $errs, @infdata) = @_;
if (defined($mapper->{""})) {
$mapper = $mapper->{""}; # side effect of Inf with no sections
@@ -680,7 +686,7 @@ sub process_maptbl
}
if (!defined($infsection->{$value}))
{
- print "ERROR: $value not found in the .inf files\n";
+ push @{$errs}, 'no_mapvalue_for_key', $value, $key;
return {};
}
}
@@ -709,6 +715,7 @@ sub getHashedPassword {
sub createDSInstance {
my $inf = shift;
+ my $errs = shift; # unused for now
# find ds_newinst.pl - in same directory as this script or in PATH
my $ds_newinst;
($ds_newinst = $0) =~ s|/[^/]+$|/ds_newinst.pl|;
@@ -724,13 +731,18 @@ sub createDSInstance {
}
# this creates an Inf suitable for passing to createDSInstance
+# except that it has a bogus suffix
sub createInfFromConfig {
my $configdir = shift;
my $inst = shift;
+ my $errs = shift;
my $fname = "$configdir/dse.ldif";
my $id;
($id = $inst) =~ s/^slapd-//;
- open( DSELDIF, "$fname" ) || die "Can't open $fname: $!";
+ if (!open( DSELDIF, "$fname" )) {
+ push @{$errs}, "error_opening_dseldif", $fname, $!;
+ return 0;
+ }
my ($outfh, $inffile) = tempfile(SUFFIX => '.inf');
my $in = new Mozilla::LDAP::LDIF(*DSELDIF) ;
while (my $ent = readOneEntry $in) {
diff --git a/ldap/admin/src/scripts/setup-ds.pl.in b/ldap/admin/src/scripts/setup-ds.pl.in
index 0117bdef..f52cd169 100644
--- a/ldap/admin/src/scripts/setup-ds.pl.in
+++ b/ldap/admin/src/scripts/setup-ds.pl.in
@@ -69,8 +69,10 @@ if (!$setup->{silent}) {
$setup->{inf}->write();
}
-my ($rc, $output) = createDSInstance($setup->{inf});
+my @errs;
+my ($rc, $output) = createDSInstance($setup->{inf}, \@errs);
if ($rc) {
+ $setup->msg(@errs);
$setup->msg($FATAL, 'error_creating_dsinstance', $rc, $output);
} else {
$setup->msg('created_dsinstance', $output);
diff --git a/ldap/admin/src/scripts/setup-ds.res.in b/ldap/admin/src/scripts/setup-ds.res.in
index 3c6b6fa8..4b8982e1 100644
--- a/ldap/admin/src/scripts/setup-ds.res.in
+++ b/ldap/admin/src/scripts/setup-ds.res.in
@@ -89,3 +89,9 @@ error_creating_suffix = Could not create the suffix '%s'. Error: %s\n\n
setup_exiting = Exiting . . .\nLog file is '%s'\n\n
error_creating_dsinstance = Error: Could not create directory server instance. Error code %s. Output:\n%s\n
created_dsinstance = Your new DS instance was successfully created. Output:\n%s\n
+no_mapvalue_for_key = The map value '%s' for key '%s' did not map to a value in any of the given information files.\n
+error_opening_ldiftmpl = Could not open the LDIF template file '%s'. Error: %s\n
+error_mapping_token_ldiftmpl = The entry '%s' in LDIF file '%s' contains a token '%s' for which there is no mapper.\nPlease check the file and your mapper to make sure all tokens are handled correctly.\n
+error_deleteall_entries = Error deleting entry '%s' and all children. Error: %s\n
+error_adding_entry = Error adding entry '%s'. Error: %s\n
+error_updating_entry = Error updating entry '%s'. Error: %s\n