summaryrefslogtreecommitdiffstats
path: root/ldap/admin/src/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/admin/src/scripts')
-rw-r--r--ldap/admin/src/scripts/DSCreate.pm.in799
-rw-r--r--ldap/admin/src/scripts/DSMigration.pm.in64
-rw-r--r--ldap/admin/src/scripts/FileConn.pm66
-rw-r--r--ldap/admin/src/scripts/Migration.pm.in2
-rw-r--r--ldap/admin/src/scripts/Util.pm.in134
-rw-r--r--ldap/admin/src/scripts/dscreate.map.in67
-rw-r--r--ldap/admin/src/scripts/dsorgentries.map.in50
-rw-r--r--ldap/admin/src/scripts/migrate-ds.pl.in14
-rw-r--r--ldap/admin/src/scripts/migrate-ds.res3
-rw-r--r--ldap/admin/src/scripts/setup-ds.pl.in12
-rw-r--r--ldap/admin/src/scripts/setup-ds.res.in21
-rw-r--r--ldap/admin/src/scripts/template-restart-slapd.in25
12 files changed, 1180 insertions, 77 deletions
diff --git a/ldap/admin/src/scripts/DSCreate.pm.in b/ldap/admin/src/scripts/DSCreate.pm.in
new file mode 100644
index 00000000..62cbf8ea
--- /dev/null
+++ b/ldap/admin/src/scripts/DSCreate.pm.in
@@ -0,0 +1,799 @@
+# 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
+#
+
+###########################
+#
+# This perl module provides a way to create a new instance of
+# directory server.
+#
+##########################
+
+package DSCreate;
+use Util;
+use Inf;
+use FileConn;
+
+use Net::Domain qw(hostfqdn);
+# tempfiles
+use File::Temp qw(tempfile tempdir);
+use File::Path;
+use File::Copy;
+use File::Basename qw(basename);
+
+# load perldap
+use Mozilla::LDAP::Conn;
+use Mozilla::LDAP::Utils qw(normalizeDN);
+use Mozilla::LDAP::API qw(ldap_explode_dn);
+use Mozilla::LDAP::LDIF;
+
+use Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(createDSInstance);
+@EXPORT_OK = qw(createDSInstance);
+
+use strict;
+
+use SetupLog;
+
+sub checkPort {
+ my $inf = shift;
+
+ # allow port 0 if ldapi is used
+ if ("@enable_ldapi@") {
+ if ($inf->{slapd}->{ldapifilepath} &&
+ ($inf->{slapd}->{ServerPort} == 0)) {
+ return ();
+ }
+ }
+
+ if (!portAvailable($inf->{slapd}->{ServerPort})) {
+ return ('error_port_available', $inf->{slapd}->{ServerPort}, $!);
+ }
+
+ return ();
+}
+
+# checks the parameters in $inf to make sure the supplied values
+# are valid
+# returns null if successful, or an error string for use with getText()
+sub sanityCheckParams {
+ my $inf = shift;
+ my @errs = ();
+
+ # if we don't need to start the server right away, we can skip the
+ # port number checks
+ if (!defined($inf->{slapd}->{start_server}) or
+ ($inf->{slapd}->{start_server} == 1)) {
+
+ if (@errs = checkPort($inf)) {
+ return @errs;
+ }
+ }
+
+ if (!isValidServerID($inf->{slapd}->{ServerIdentifier})) {
+ return ('error_invalid_serverid', $inf->{slapd}->{ServerIdentifier});
+ } elsif (-d $inf->{slapd}->{config_dir}) {
+ return ('error_server_already_exists', $inf->{slapd}->{config_dir});
+ }
+
+ if (@errs = isValidUser($inf->{General}->{SuiteSpotUserID})) {
+ return @errs;
+ }
+
+ if (!isValidDN($inf->{slapd}->{Suffix})) {
+ return ('dialog_dssuffix_error', $inf->{slapd}->{Suffix});
+ }
+
+ if (!isValidDN($inf->{slapd}->{RootDN})) {
+ return ('dialog_dsrootdn_error', $inf->{slapd}->{RootDN});
+ }
+
+ if ($inf->{slapd}->{RootDNPwd} =~ /\{\w+\}.+/) {
+ debug(1, "The root password is already hashed - no checking will be performed\n");
+ } elsif (length($inf->{slapd}->{RootDNPwd}) < 8) {
+ debug(0, "WARNING: The root password is less than 8 characters long. You should choose a longer one.\n");
+ }
+
+ return ();
+}
+
+sub getMode {
+ my $inf = shift;
+ my $mode = shift;
+ if (defined($inf->{General}->{SuiteSpotGroup})) {
+ $mode = "0" . $mode . $mode . "0";
+ } else {
+ $mode = "0" . $mode . "00";
+ }
+
+ return oct($mode);
+}
+
+# This is used to change the ownership and permissions of files and directories
+# The mode is just a single digit octal number (e.g. 4 6 7)
+# If there is a group, the ownership and permissions will allow group access
+# otherwise, only the owner will be allowed access
+sub changeOwnerMode {
+ my $inf = shift;
+ my $mode = shift;
+ my $it = shift;
+
+ my $uid = getpwnam $inf->{General}->{SuiteSpotUserID};
+ my $gid = -1; # default to leave it alone
+
+ if (defined($inf->{General}->{SuiteSpotGroup})) {
+ $gid = getgrnam $inf->{General}->{SuiteSpotGroup};
+ }
+
+ $mode = getMode($inf, $mode);
+ $! = 0; # clear errno
+ chmod $mode, $it;
+ if ($!) {
+ return ('error_chmoding_file', $it, $!);
+ }
+ $! = 0; # clear errno
+ chown $uid, $gid, $it;
+ if ($!) {
+ return ('error_chowning_file', $it, $inf->{General}->{SuiteSpotUserID}, $!);
+ }
+
+ return ();
+}
+
+sub makeDSDirs {
+ my $inf = shift;
+ my $verbose = ($Util::debuglevel > 0);
+ my $mode = getMode($inf, 7);
+ my @errs;
+
+ # These paths are owned by the SuiteSpotGroup
+ # This allows the admin server to run as a different,
+ # more privileged user than the directory server, but
+ # still allows the admin server to manage directory
+ # server files/dirs without being root
+ for (qw(inst_dir config_dir schema_dir log_dir lock_dir run_dir tmp_dir
+ cert_dir db_dir ldif_dir bak_dir)) {
+ my $dir = $inf->{slapd}->{$_};
+ @errs = makePaths($dir, $mode, $inf->{General}->{SuiteSpotUserID},
+ $inf->{General}->{SuiteSpotGroup});
+ if (@errs) {
+ return @errs;
+ }
+ }
+
+ return @errs;
+}
+
+sub createInstanceScripts {
+ my $inf = shift;
+ my $myperl = "!/usr/bin/env perl";
+ my $mydevnull = (-f "/dev/null" ? " /dev/null " : " NUL ");
+ my %maptable = (
+ "DS-ROOT" => $inf->{General}->{prefix},
+ "SEP" => "/", # works on all platforms
+ "SERVER-NAME" => $inf->{General}->{FullMachineName},
+ "SERVER-PORT" => $inf->{slapd}->{ServerPort},
+ "PERL-EXEC" => $myperl,
+ "DEV-NULL" => $mydevnull,
+ "ROOT-DN" => $inf->{slapd}->{RootDN},
+ "LDIF-DIR" => $inf->{slapd}->{ldif_dir},
+ "SERV-ID" => $inf->{slapd}->{ServerIdentifier},
+ "BAK-DIR" => $inf->{slapd}->{bak_dir},
+ "SERVER-DIR" => $inf->{General}->{ServerRoot},
+ "CONFIG-DIR" => $inf->{slapd}->{config_dir},
+ "RUN-DIR" => $inf->{slapd}->{run_dir},
+ "PRODUCT-NAME" => "slapd",
+ "SERVERBIN-DIR" => $inf->{slapd}->{sbindir},
+ "DB-DIR" => $inf->{slapd}->{db_dir}
+ );
+
+ my $dir = "$inf->{General}->{prefix}@taskdir@";
+ for (glob("$dir/template-*")) {
+ my $basename = $_;
+ $basename =~ s/^.*template-//;
+ my $destfile = "$inf->{slapd}->{inst_dir}/$basename";
+ if (!open(SRC, "< $_")) {
+ return ("error_opening_scripttmpl", $_, $!);
+ }
+ if (!open(DEST, "> $destfile")) {
+ return ("error_opening_scripttmpl", $destfile, $!);
+ }
+ my $contents; # slurp entire file into memory
+ read SRC, $contents, int(-s $_);
+ close(SRC);
+ while (my ($key, $val) = each %maptable) {
+ $contents =~ s/\{\{$key\}\}/$val/g;
+ }
+ print DEST $contents;
+ close(DEST);
+ my @errs = changeOwnerMode($inf, 5, $destfile);
+ if (@errs) {
+ return @errs;
+ }
+ }
+
+ return ();
+}
+
+sub createConfigFile {
+ my $inf = shift;
+ my $conffile = "$inf->{slapd}->{config_dir}/dse.ldif";
+ my $conn = new FileConn;
+ my @errs;
+
+ # first, create the basic config
+ my $mapper = new Inf("$inf->{General}->{prefix}@infdir@/dscreate.map");
+ my $dsinf = new Inf("$inf->{General}->{prefix}@infdir@/slapd.inf");
+ if (!$inf->{slapd}->{ds_bename}) {
+ $inf->{slapd}->{ds_bename} = "userRoot"; # for suffix-db
+ }
+ $mapper = process_maptbl($mapper, \@errs, $inf, $dsinf);
+ if (!$mapper or @errs) {
+ $conn->close();
+ if (!@errs) {
+ @errs = ('error_creating_file', $conffile, $!);
+ }
+ return @errs;
+ }
+
+ my @ldiffiles = ("$inf->{General}->{prefix}@templatedir@/template-dse.ldif",
+ "$inf->{General}->{prefix}@templatedir@/template-suffix-db.ldif");
+ if ("@enable_pam_passthru@") {
+ push @ldiffiles, "$inf->{General}->{prefix}@templatedir@/template-pampta.ldif";
+ }
+ if ("@enable_bitwise@") {
+ push @ldiffiles, "$inf->{General}->{prefix}@templatedir@/template-bitwise.ldif";
+ }
+ if ("@enable_dna@") {
+ push @ldiffiles, "$inf->{General}->{prefix}@templatedir@/template-dnaplugin.ldif";
+ }
+
+ getMappedEntries($mapper, \@ldiffiles, \@errs, \&check_and_add_entry,
+ [$conn]);
+
+ if (@errs) {
+ $conn->close();
+ return @errs;
+ }
+
+ if ("@enable_ldapi@") {
+ my $ent = $conn->search("cn=config", "base", "(objectclass=*)");
+ if (defined($inf->{slapd}->{ldapifilepath})) {
+ $ent->setValues("nsslapd-ldapifilepath", $inf->{slapd}->{ldapifilepath});
+ $ent->setValues("nsslapd-ldapilisten", "on");
+ } else {
+ $ent->setValues("nsslapd-ldapifilepath",
+ "$inf->{slapd}->{run_dir}/slapd-$inf->{slapd}->{ServerIdentifier}.socket");
+ $ent->setValues("nsslapd-ldapilisten", "off");
+ }
+ if ("@enable_autobind@") {
+ $ent->setValues("nsslapd-ldapiautobind", "on");
+ }
+ $ent->setValues("nsslapd-ldapimaprootdn", $inf->{slapd}->{RootDN});
+ $ent->setValues("nsslapd-ldapimaptoentries", "off");
+ $ent->setValues("nsslapd-ldapiuidnumbertype", "uidNumber");
+ $ent->setValues("nsslapd-ldapigidnumbertype", "gidNumber");
+ $ent->setValues("nsslapd-ldapientrysearchbase", "dc=example, dc=com");
+ $ent->setValues("nsslapd-ldapiautodnsuffix", "cn=peercred,cn=external,cn=auth");
+ if (!$conn->update($ent)) {
+ $conn->close();
+ return ("error_enabling_feature", "ldapi", $conn->getErrorString());
+ }
+ }
+
+ if ($inf->{slapd}->{sasl_path}) {
+ my $ent = $conn->search("cn=config", "base", "(objectclass=*)");
+ $ent->setValues("nsslapd-saslpath", $inf->{slapd}->{sasl_path});
+ if (!$conn->update($ent)) {
+ $conn->close();
+ return ("error_enabling_feature", "sasl_path", $conn->getErrorString());
+ }
+ }
+
+ $conn->write($conffile);
+ $conn->close();
+
+ if (@errs = changeOwnerMode($inf, 6, $conffile)) {
+ return @errs;
+ }
+ # make a copy
+ my $origconf = "$inf->{slapd}->{config_dir}/dse_original.ldif";
+ $! = 0; # clear errno
+ copy($conffile, $origconf);
+ if ($!) {
+ return ('error_copying_file', $conffile, $origconf, $!);
+ }
+ if (@errs = changeOwnerMode($inf, 4, $origconf)) {
+ return @errs;
+ }
+
+ return @errs;
+}
+
+sub makeOtherConfigFiles {
+ my $inf = shift;
+ my @errs;
+ # install certmap.conf at <configdir>
+ my $src = "$inf->{General}->{prefix}@configdir@/certmap.conf";
+ my $dest = "$inf->{slapd}->{config_dir}/certmap.conf";
+ $! = 0; # clear errno
+ copy($src, $dest);
+ if ($!) {
+ return ('error_copying_file', $src, $dest, $!);
+ }
+ if (@errs = changeOwnerMode($inf, 4, $dest)) {
+ return @errs;
+ }
+
+ $src = "$inf->{General}->{prefix}@configdir@/slapd-collations.conf";
+ $dest = "$inf->{slapd}->{config_dir}/slapd-collations.conf";
+ $! = 0; # clear errno
+ copy($src, $dest);
+ if ($!) {
+ return ('error_copying_file', $src, $dest, $!);
+ }
+ if (@errs = changeOwnerMode($inf, 4, $dest)) {
+ return @errs;
+ }
+
+ return ();
+}
+
+sub installSchema {
+ my $inf = shift;
+ my @errs;
+ my @schemafiles = ();
+ if (!defined($inf->{slapd}->{install_full_schema}) or
+ $inf->{slapd}->{install_full_schema}) {
+ push @schemafiles, glob("$inf->{General}->{prefix}@schemadir@/*");
+ } else {
+ push @schemafiles, "$inf->{General}->{prefix}@schemadir@/00core.ldif";
+ }
+ for (@schemafiles) {
+ my $src = $_;
+ my $basename = basename($src);
+ my $dest = "$inf->{slapd}->{schema_dir}/$basename";
+ $! = 0; # clear errno
+ copy($src, $dest);
+ if ($!) {
+ return ('error_copying_file', $src, $dest, $!);
+ }
+ my $mode = 4; # default read only
+ if ($basename eq "99user.ldif") {
+ $mode = 6; # read write
+ }
+ if (@errs = changeOwnerMode($inf, $mode, $dest)) {
+ return @errs;
+ }
+ }
+
+ return ();
+}
+
+# maps the suffix attr to the filename to use
+my %suffixTable = (
+ 'o' => "@templatedir@/template-org.ldif",
+ 'dc' => "@templatedir@/template-domain.ldif",
+ 'ou' => "@templatedir@/template-orgunit.ldif",
+ 'st' => "@templatedir@/template-state.ldif",
+ 'l' => "@templatedir@/template-locality.ldif",
+ 'c' => "@templatedir@/template-country.ldif"
+);
+
+sub initDatabase {
+ my $inf = shift;
+ # If the user has specified an LDIF file to use to initialize the database,
+ # load it now
+ my $ldiffile = $inf->{slapd}->{InstallLdifFile};
+ if ($ldiffile && -f $ldiffile) {
+ debug(1, "Loading initial ldif file $ldiffile\n");
+ } elsif (($inf->{slapd}->{Suffix} =~ /^(.*?)=/) && $suffixTable{$1}) {
+ my @errs;
+ my $template = $inf->{General}->{prefix} . $suffixTable{$1};
+ my $mapper = new Inf("$inf->{General}->{prefix}@infdir@/dsorgentries.map");
+ my $dsinf = new Inf("$inf->{General}->{prefix}@infdir@/slapd.inf");
+ my @rdns = ldap_explode_dn($inf->{slapd}->{Suffix}, 1);
+ $inf->{slapd}->{naming_value} = $rdns[0];
+ $mapper = process_maptbl($mapper, \@errs, $inf, $dsinf);
+ if (!$mapper or @errs) {
+ return @errs;
+ }
+
+ my @ldiffiles = ($template, "$inf->{General}->{prefix}@templatedir@/template-baseacis.ldif");
+ if (exists($inf->{slapd}->{InstallLdifFile}) and
+ ($inf->{slapd}->{InstallLdifFile} =~ /suggest/i)) {
+ push @ldiffiles, "$inf->{General}->{prefix}@templatedir@/template.ldif";
+ }
+
+ my ($fh, $templdif) = tempfile("ldifXXXXXX", SUFFIX => ".ldif", OPEN => 0,
+ DIR => File::Spec->tmpdir);
+ my $conn = new FileConn;
+ $conn->setNamingContext($inf->{slapd}->{Suffix});
+ getMappedEntries($mapper, \@ldiffiles, \@errs, \&check_and_add_entry,
+ [$conn]);
+ $conn->write($templdif);
+ $conn->close();
+ if (@errs) {
+ return @errs;
+ }
+ # $templdif now contains the ldif to import
+ $ldiffile = $templdif;
+ }
+ if (!$ldiffile) {
+ return ();
+ }
+
+ my $cmd = "$inf->{slapd}->{inst_dir}/ldif2db -n userRoot -i \'$ldiffile\'";
+ $? = 0; # clear error condition
+ my $output = `$cmd 2>&1`;
+ if ($?) {
+ return ('error_importing_ldif', $ldiffile, $?, $output);
+ }
+
+ debug(1, $output);
+
+ return ();
+}
+
+sub startServer {
+ my $inf = shift;
+ return () if (defined($inf->{slapd}->{start_server}) && !$inf->{slapd}->{start_server});
+
+ my @errs;
+ # get error log
+ my $errLog = "$inf->{slapd}->{log_dir}/errors";
+ my $startcmd = "$inf->{slapd}->{inst_dir}/start-slapd";
+
+ # emulate tail -f
+ # if the last line we see does not contain "slapd started", try again
+ my $done = 0;
+ my $started = 0;
+ my $code = 0;
+ my $lastLine = "";
+ my $cmdPat = 'slapd started\.';
+ my $timeout = $inf->{slapd}->{startup_timeout};
+
+ $timeout = $timeout?$timeout:600; # default is 10 minutes
+ $timeout = time + $timeout;
+
+ debug(1, "Starting the server: $startcmd\n");
+ $? = 0; # clear error condition
+ my $output = `$startcmd 2>&1`;
+ $code = $?;
+ debug(1, "Started the server: code $code\n");
+ if ($code) {
+ debug(0, $output);
+ } else {
+ debug(1, $output);
+ }
+
+ # try to open the server error log
+ my $ii = 0;
+ while (time < $timeout) {
+ if (open(IN, $errLog)) {
+ last;
+ }
+ sleep(1);
+ if (!($ii % 10)) {
+ debug(0, "Attempting to obtain server status . . .\n");
+ }
+ ++$ii;
+ }
+
+ if (! -f $errLog) {
+ debug(0, "Error: Could not read error log $errLog to get server startup status. Error: $!\n");
+ return ('error_starting_server', $startcmd, "no status", $!);
+ }
+ if (time >= $timeout) {
+ debug(0, "Error: timed out waiting for the server to start and write to $errLog");
+ return ('error_starting_server', $startcmd, "timeout", 0);
+ }
+
+ my $pos = tell(IN);
+ while (($done == 0) && (time < $timeout)) {
+ for (; ($done == 0) && ($_ = <IN>); $pos = tell(IN)) {
+ $lastLine = $_;
+ debug(1, $_);
+ if (/$cmdPat/) {
+ $done = 1;
+ $started = 1;
+ } elsif (/Initialization Failed/) {
+ debug(1, "Server failed to start, retrying . . .\n");
+ $code = system($startcmd);
+ } elsif (/exiting\./) {
+ debug(1, "Server failed to start, retrying . . .\n");
+ $code = system($startcmd);
+ }
+ }
+ if ($lastLine =~ /PR_Bind/) {
+ # server port conflicts with another one, just report and punt
+ debug(0, $lastLine);
+ @errs = ('error_port_available', $inf->{slapd}->{ServerPort}, $!);
+ $done = 1;
+ }
+ if ($done == 0) {
+ # rest a bit, then . . .
+ sleep(2);
+ # . . . reset the EOF status of the file desc
+ seek(IN, $pos, 0);
+ }
+ }
+ close(IN);
+
+ if (!$started) {
+ $! = $code;
+ my $now = time;
+ if ($now > $timeout) {
+ debug(0, "Possible timeout starting server: timeout=$timeout now=$now\n");
+ }
+ @errs = ('error_starting_server', $startcmd, $lastLine, $!);
+ } else {
+ debug(1, "Your new directory server has been started.\n");
+ }
+
+ return @errs;
+}
+
+sub set_path_attribute {
+ my $val = shift;
+ my $defaultval = shift;
+ my $prefix = shift;
+
+ if ($val) {
+ return "$prefix" . "$val";
+ } else {
+ return "$prefix" . "$defaultval";
+ }
+}
+
+sub setDefaults {
+ my $inf = shift;
+ # set default values
+
+ # this turns off the warnings
+ if (!defined($inf->{General}->{prefix})) {
+ $inf->{General}->{prefix} = "";
+ }
+
+ if (!$inf->{General}->{FullMachineName}) {
+ $inf->{General}->{FullMachineName} = hostfqdn;
+ }
+
+ if (!$inf->{General}->{SuiteSpotUserID}) {
+ if ($> != 0) { # if not root, use the user's uid
+ $inf->{General}->{SuiteSpotUserID} = getlogin;
+ }
+ # otherwise, the uid must be specified
+ }
+
+ if (!$inf->{slapd}->{RootDN}) {
+ $inf->{slapd}->{RootDN} = "cn=Directory Manager";
+ }
+
+ if (!$inf->{slapd}->{Suffix}) {
+ my $suffix = $inf->{General}->{FullMachineName};
+ # convert fqdn to dc= domain components
+ $suffix =~ s/^[^\.]*\.//; # just the domain part
+ $suffix = "dc=$suffix";
+ $suffix =~ s/\./, dc=/g;
+ $inf->{slapd}->{Suffix} = $suffix;
+ }
+
+ if (!$inf->{slapd}->{ServerIdentifier}) {
+ my $servid = $inf->{General}->{FullMachineName};
+ # strip out the leftmost domain component
+ $servid =~ s/\..*$//;
+ $inf->{slapd}->{ServerIdentifier} = $servid;
+ }
+
+ if ("@with_fhs_opt@") {
+ $inf->{General}->{ServerRoot} = "$inf->{General}->{prefix}/opt/@PACKAGE_NAME@";
+ } else {
+ $inf->{General}->{ServerRoot} = "$inf->{General}->{prefix}@serverdir@";
+ }
+
+ if (!defined($inf->{slapd}->{sasl_path})) {
+ if ($ ne "linux") {
+ $inf->{slapd}->{sasl_path} = "$inf->{General}->{prefix}@libdir@/sasl2";
+ }
+ }
+
+ if (!defined($inf->{slapd}->{ServerPort}) and
+ !defined($inf->{slapd}->{ldapifilepath})) {
+ if ("@enable_ldapi@") {
+ return ('error_missing_port_and_ldapi');
+ } else {
+ return ('error_missing_port');
+ }
+ }
+
+ if (!defined($inf->{slapd}->{ServerPort})) {
+ $inf->{slapd}->{ServerPort} = 0;
+ }
+
+ $inf->{slapd}->{HashedRootDNPwd} = getHashedPassword($inf->{slapd}->{RootDNPwd});
+
+ $inf->{slapd}->{localstatedir} = set_path_attribute($inf->{slapd}->{localstatedir},
+ "@localstatedir@",
+ $inf->{General}->{prefix});
+ my $localstatedir = $inf->{slapd}->{localstatedir};
+ my $servid = $inf->{slapd}->{ServerIdentifier};
+ $inf->{slapd}->{sysconfdir} = set_path_attribute($inf->{slapd}->{sysconfdir},
+ "@sysconfdir@",
+ $inf->{General}->{prefix});
+ my $sysconfdir = $inf->{slapd}->{sysconfdir};
+ $inf->{slapd}->{bindir} = set_path_attribute($inf->{slapd}->{bindir},
+ "@bindir@",
+ $inf->{General}->{prefix});
+ $inf->{slapd}->{sbindir} = set_path_attribute($inf->{slapd}->{sbindir},
+ "@sbindir@",
+ $inf->{General}->{prefix});
+ $inf->{slapd}->{datadir} = set_path_attribute($inf->{slapd}->{datadir},
+ "@datadir@",
+ $inf->{General}->{prefix});
+
+ if (!defined($inf->{slapd}->{inst_dir})) {
+ $inf->{slapd}->{inst_dir} = "$inf->{General}->{ServerRoot}/slapd-$servid";
+ }
+
+ if (!defined($inf->{slapd}->{config_dir})) {
+ $inf->{slapd}->{config_dir} = "$inf->{General}->{prefix}@instconfigdir@/slapd-$servid";
+ }
+ $ENV{DS_CONFIG_DIR} = $inf->{slapd}->{config_dir};
+
+ if (!defined($inf->{slapd}->{schema_dir})) {
+ $inf->{slapd}->{schema_dir} = "$sysconfdir/@PACKAGE_NAME@/slapd-$servid/schema";
+ }
+
+ if (!defined($inf->{slapd}->{lock_dir})) {
+ if ("@with_fhs_opt@") {
+ $inf->{slapd}->{lock_dir} = "$localstatedir/@PACKAGE_NAME@/slapd-$servid/lock";
+ } else {
+ $inf->{slapd}->{lock_dir} = "$localstatedir/lock/@PACKAGE_NAME@/slapd-$servid";
+ }
+ }
+
+ if (!defined($inf->{slapd}->{log_dir})) {
+ if ("@with_fhs_opt@") {
+ $inf->{slapd}->{log_dir} = "$localstatedir/@PACKAGE_NAME@/slapd-$servid/log";
+ } else {
+ $inf->{slapd}->{log_dir} = "$localstatedir/log/@PACKAGE_NAME@/slapd-$servid";
+ }
+ }
+
+ if (!defined($inf->{slapd}->{run_dir})) {
+ if ("@with_fhs_opt@") {
+ $inf->{slapd}->{run_dir} = "$localstatedir/@PACKAGE_NAME@/slapd-$servid/run";
+ } else {
+ $inf->{slapd}->{run_dir} = "$localstatedir/run/@PACKAGE_NAME@";
+ }
+ }
+ $ENV{DS_RUN_DIR} = $inf->{slapd}->{run_dir};
+
+ if (!defined($inf->{slapd}->{db_dir})) {
+ if ("@with_fhs_opt@") {
+ $inf->{slapd}->{db_dir} = "$localstatedir/@PACKAGE_NAME@/slapd-$servid/db";
+ } else {
+ $inf->{slapd}->{db_dir} = "$localstatedir/lib/@PACKAGE_NAME@/slapd-$servid/db";
+ }
+ }
+
+ if (!defined($inf->{slapd}->{bak_dir})) {
+ if ("@with_fhs_opt@") {
+ $inf->{slapd}->{bak_dir} = "$localstatedir/@PACKAGE_NAME@/slapd-$servid/bak";
+ } else {
+ $inf->{slapd}->{bak_dir} = "$localstatedir/lib/@PACKAGE_NAME@/slapd-$servid/bak";
+ }
+ }
+ $ENV{DS_BAK_DIR} = $inf->{slapd}->{bak_dir};
+
+ if (!defined($inf->{slapd}->{ldif_dir})) {
+ if ("@with_fhs_opt@") {
+ $inf->{slapd}->{ldif_dir} = "$localstatedir/@PACKAGE_NAME@/slapd-$servid/ldif";
+ } else {
+ $inf->{slapd}->{ldif_dir} = "$localstatedir/lib/@PACKAGE_NAME@/slapd-$servid/ldif";
+ }
+ }
+
+ if (!defined($inf->{slapd}->{tmp_dir})) {
+ if ("@with_fhs_opt@") {
+ $inf->{slapd}->{tmp_dir} = "$localstatedir/@PACKAGE_NAME@/slapd-$servid/tmp";
+ } else {
+ $inf->{slapd}->{tmp_dir} = "$localstatedir/tmp/@PACKAGE_NAME@/slapd-$servid";
+ }
+ }
+ $ENV{DS_TMP_DIR} = $inf->{slapd}->{tmp_dir};
+
+ if (!defined($inf->{slapd}->{cert_dir})) {
+ $inf->{slapd}->{cert_dir} = $inf->{slapd}->{config_dir};
+ }
+
+ return ();
+}
+
+sub createDSInstance {
+ my $inf = shift;
+ my @errs;
+
+ if (@errs = setDefaults($inf)) {
+ return @errs;
+ }
+
+ if (@errs = sanityCheckParams($inf)) {
+ return @errs;
+ }
+
+ if (@errs = makeDSDirs($inf)) {
+ return @errs;
+ }
+
+ if (@errs = createConfigFile($inf)) {
+ return @errs;
+ }
+
+ if (@errs = makeOtherConfigFiles($inf)) {
+ return @errs;
+ }
+
+ if (@errs = createInstanceScripts($inf)) {
+ return @errs;
+ }
+
+ if (@errs = installSchema($inf)) {
+ return @errs;
+ }
+
+ if (@errs = initDatabase($inf)) {
+ return @errs;
+ }
+
+ if (@errs = startServer($inf)) {
+ return @errs;
+ }
+
+ return @errs;
+}
+
+1;
+
+# emacs settings
+# Local Variables:
+# mode:perl
+# indent-tabs-mode: nil
+# tab-width: 4
+# End:
diff --git a/ldap/admin/src/scripts/DSMigration.pm.in b/ldap/admin/src/scripts/DSMigration.pm.in
index 070c909b..09f0e034 100644
--- a/ldap/admin/src/scripts/DSMigration.pm.in
+++ b/ldap/admin/src/scripts/DSMigration.pm.in
@@ -50,6 +50,7 @@ package DSMigration;
use Migration;
use Util;
use Inf;
+use DSCreate;
# tempfiles
use File::Temp qw(tempfile tempdir);
@@ -91,6 +92,7 @@ my %ignoreOld =
'nsslapd-certdir' => 'nsslapd-certdir',
'nsslapd-ldifdir' => 'nsslapd-ldifdir',
'nsslapd-bakdir' => 'nsslapd-bakdir',
+ 'nsslapd-instancedir' => 'nsslapd-instancedir',
'nsslapd-ldapifilepath' => 'nsslapd-ldapifilepath',
'nsslapd-ldapilisten' => 'nsslapd-ldapilisten',
'nsslapd-ldapiautobind' => 'nsslapd-ldapiautobind',
@@ -187,19 +189,28 @@ sub copyDatabaseDirs {
return ("error_dbsrcdir_not_exist", $srcdir);
} else {
debug(1, "The destination directory $destdir already exists, copying files/dirs individually\n");
+ $! = 0;
+ debug(1, "Removing any existing db files in $destdir\n");
+ unlink glob("$destdir/*");
+ if ($!) {
+ return ("error_removing_temp_db_files", $destdir, $!);
+ }
foreach my $file (glob("$srcdir/*")) {
- debug(3, "Copying $file to $destdir\n");
if (-f $file) {
+ debug(3, "Copying $file to $destdir\n");
if (system ("cp -p $file $destdir")) {
return ('error_copying_dbfile', $file, $destdir, $?);
}
} elsif (-d $file && !$filesonly) {
+ debug(3, "Copying $file to $destdir\n");
if (system ("cp -p -r $file $destdir")) {
return ('error_copying_dbdir', $file, $destdir, $?);
}
}
}
}
+
+ return ();
}
# migrate all of the databases in an instance
@@ -216,11 +227,14 @@ sub migrateDatabases {
my $foundldif;
for (glob("$mig->{oldsroot}/$inst/db/*.ldif")) {
my $dbname = basename($_, '.ldif');
- my @cmd = ("@serverdir@/$inst/ldif2db", "-n", $dbname, "-i", $_);
- debug(1, "migrateDatabases: executing command ", @cmd);
- if (system(@cmd)) {
- return ('error_importing_migrated_db', $_, $?);
+ my $cmd = "@serverdir@/$inst/ldif2db -n \"$dbname\" -i \"$_\"";
+ debug(1, "migrateDatabases: executing command $cmd\n");
+ $? = 0; # clear error condition
+ my $output = `$cmd 2>&1`;
+ if ($?) {
+ return ('error_importing_migrated_db', $_, $?, $output);
}
+ debug(1, $output);
$foundldif = 1;
}
@@ -284,13 +298,13 @@ sub migrateDatabases {
my $srcdir = $dir || "$olddefault/db/$cn";
my $newent = $dest->search($ent->getDN(), "base", "(objectclass=*)");
my $newdbdir = $newent->getValues('nsslapd-directory') ||
- "@localstatedir@/lib/$mig->{pkgname}/$inst/db";
+ "@localstatedir@/lib/$mig->{pkgname}/$inst/db/$cn";
if (-d $srcdir and ($srcdir !~ /^$olddefault/)) {
debug(2, "Not copying database indexes from [$srcdir]\n");
} else {
# replace the old sroot value with the actual physical location on the target/dest
$srcdir =~ s/^$mig->{actualsroot}/$mig->{oldsroot}/;
- if (@errs = copyDatabaseDirs($srcdir, "$newdbdir/$cn")) {
+ if (@errs = copyDatabaseDirs($srcdir, "$newdbdir")) {
return @errs;
}
}
@@ -317,9 +331,14 @@ sub migrateChangelogs {
# replace the old sroot value with the actual physical location on the target/dest
$oldcldir =~ s/^$mig->{actualsroot}/$mig->{oldsroot}/;
my $newcldir = $newent->getValues('nsslapd-changelogdir');
- copyDatabaseDirs($oldcldir, $newcldir);
+ my @errs = copyDatabaseDirs($oldcldir, $newcldir);
+ if (@errs) {
+ return @errs;
+ }
}
}
+
+ return ();
}
sub fixAttrsInEntry {
@@ -358,27 +377,37 @@ sub mergeEntries {
# iterate through the attr lists
my $cn = lc $new->getValues("cn");
foreach my $attr (keys %inoldonly, keys %innewonly, @attrs) {
+ debug(3, "mergeEntries: merging entry ", $old->getDN(), " attr $attr\n");
my $lcattr = lc $attr;
if ($ignoreOld{$lcattr}) {
+ debug(3, "mergeEntries: ignoring old invalid or obsolete attr $attr\n");
next; # use new value or just omit if attr is obsolete
} elsif ($transformAttr{$lcattr}) {
# only transform if the value is in the old entry
if (!$innewonly{$attr}) {
- $new->setValues($attr, &{$transformAttr{$lcattr}}($old, $attr, $mig, $inst));
+ my $oldval = $old->getValues($attr);
+ my $newval = &{$transformAttr{$lcattr}}($old, $attr, $mig, $inst);
+ $new->setValues($attr, $newval);
+ debug(3, "mergeEntries: transformed old value $oldval to $newval\n");
}
} elsif ($cn eq "internationalization plugin" and $lcattr eq "nsslapd-pluginarg0") {
+ debug(3, "mergeEntries: using new value of internationalization plugin nsslapd-pluginarg0\n");
next; # use the new value of this path name
} elsif ($cn eq "referential integrity postoperation" and $lcattr eq "nsslapd-pluginarg1") {
+ debug(3, "mergeEntries: using new value of referential integrity postoperation nsslapd-pluginarg1\n");
next; # use the new value of this path name
} elsif ($innewonly{$attr}) {
+ debug(3, "mergeEntries: removing attr $attr from new entry\n");
$new->remove($attr); # in new but not old - just remove it
} else {
+ my $oldval = $old->getValues($attr);
+ my $newval = $new->getValues($attr);
$new->setValues($attr, $old->getValues($attr)); # use old value
+ debug(3, "mergeEntries: using old val $oldval instead of new val $newval\n");
}
}
}
-
my @allattrlist = ('*', 'aci', 'createTimestamp', 'creatorsName',
'modifyTimestamp', 'modifiersName');
@@ -598,14 +627,14 @@ sub migrateDS {
}
# create the new instance
- my ($rc, $output) = createDSInstance($inf, \@errs);
+ @errs = createDSInstance($inf);
unlink($inf->{filename});
- if ($rc) {
+ if (@errs) {
$mig->msg(@errs);
- $mig->msg($FATAL, 'error_creating_dsinstance', $rc, $output);
+ $mig->msg($FATAL, 'error_creating_dsinstance', $inst);
return 0;
} else {
- $mig->msg('created_dsinstance', $output);
+ $mig->msg('created_dsinstance', $inst);
}
my $src = new FileConn("$oldconfigdir/dse.ldif", 1); # read-only
@@ -627,3 +656,10 @@ sub migrateDS {
# Mandatory TRUE return value.
#
1;
+
+# emacs settings
+# Local Variables:
+# mode:perl
+# indent-tabs-mode: nil
+# tab-width: 4
+# End:
diff --git a/ldap/admin/src/scripts/FileConn.pm b/ldap/admin/src/scripts/FileConn.pm
index ea68d41f..7e62d8b2 100644
--- a/ldap/admin/src/scripts/FileConn.pm
+++ b/ldap/admin/src/scripts/FileConn.pm
@@ -46,6 +46,8 @@ use Mozilla::LDAP::API qw(:constant ldap_explode_dn ldap_err2string); # Direct a
use Mozilla::LDAP::Utils qw(normalizeDN);
use Mozilla::LDAP::LDIF;
+use Carp;
+
require Exporter;
@ISA = qw(Exporter Mozilla::LDAP::Conn);
@EXPORT = qw();
@@ -55,11 +57,16 @@ sub new {
my $class = shift;
my $filename = shift;
my $readonly = shift;
+ my @namingContexts = @_;
my $self = {};
$self = bless $self, $class;
$self->{readonly} = $readonly;
+ for (@namingContexts) {
+ $self->setNamingContext($_);
+ }
+ $self->setNamingContext(""); # root DSE
$self->read($filename);
return $self;
@@ -86,16 +93,31 @@ sub read {
return;
}
- open( MYLDIF, "$filename" ) || die "Can't open $filename: $!";
+ open( MYLDIF, "$filename" ) || confess "Can't open $filename: $!";
my $in = new Mozilla::LDAP::LDIF(*MYLDIF);
+ $self->{reading} = 1;
while ($ent = readOneEntry $in) {
if (!$self->add($ent)) {
- die "Error: could not add entry ", $ent->getDN(), ":", $self->getErrorString();
+ confess "Error: could not add entry ", $ent->getDN(), ":", $self->getErrorString();
}
}
+ delete $self->{reading};
close( MYLDIF );
}
+sub setNamingContext {
+ my $self = shift;
+ my $nc = shift;
+ my $ndn = normalizeDN($nc);
+ $self->{namingContexts}->{$ndn} = $ndn;
+}
+
+sub isNamingContext {
+ my $self = shift;
+ my $ndn = shift;
+ return exists($self->{namingContexts}->{$ndn});
+}
+
# return all nodes below the given node
sub iterate {
my $self = shift;
@@ -152,12 +174,16 @@ sub write {
$filename = $self->{filename};
}
- if (!$self->{filename} or $self->{readonly}) {
+ if (!$self->{filename} or $self->{readonly} or $self->{reading}) {
return;
}
- open( MYLDIF, ">$filename" ) || die "Can't write $filename: $!";
+ open( MYLDIF, ">$filename" ) || confess "Can't write $filename: $!";
$self->iterate("", LDAP_SCOPE_SUBTREE, \&writecb, \*MYLDIF);
+ for (keys %{$self->{namingContexts}}) {
+ next if (!$_); # skip "" - we already did that
+ $self->iterate($_, LDAP_SCOPE_SUBTREE, \&writecb, \*MYLDIF);
+ }
close( MYLDIF );
}
@@ -307,9 +333,30 @@ sub search {
return $self->nextEntry();
}
+sub cloneEntry {
+ my $src = shift;
+ if (!$src) {
+ return undef;
+ }
+ my $dest = new Mozilla::LDAP::Entry();
+ $dest->setDN($src->getDN());
+ for (keys %{$src}) {
+ if (ref($src->{$_})) {
+ my @copyary = @{$src->{$_}};
+ $dest->{$_} = [ @copyary ]; # make a deep copy
+ } else {
+ $dest->{$_} = $src->{$_};
+ }
+ }
+
+ return $dest;
+}
+
+# have to return a copy of the entry - disallow inplace updates
sub nextEntry {
my $self = shift;
- return shift @{$self->{entries}};
+ my $ent = shift @{$self->{entries}};
+ return cloneEntry($ent);
}
sub add {
@@ -320,10 +367,9 @@ sub add {
my $parentdn = getParentDN($dn);
my $nparentdn = normalizeDN($parentdn);
-
$self->setErrorCode(0);
- # special case of root DSE
- if (!$ndn and exists($self->{$ndn}) and
+ # special case of naming context - has no parent
+ if ($self->isNamingContext($ndn) and
!exists($self->{$ndn}->{data})) {
$self->{$ndn}->{data} = $entry;
$self->write();
@@ -357,6 +403,8 @@ sub update {
my $dn = $entry->getDN();
my $ndn = normalizeDN($dn);
+ confess "Attempt to modify read only $self->{filename} entry $dn" if ($self->{readonly});
+
$self->setErrorCode(0);
if (!exists($self->{$ndn})) {
$self->setErrorCode(LDAP_NO_SUCH_OBJECT);
@@ -373,6 +421,8 @@ sub delete {
my $self = shift;
my $dn = shift;
+ confess "Attempt to modify read only $self->{filename} entry $dn" if ($self->{readonly});
+
if (ref($dn)) {
$dn = $dn->getDN(); # an Entry
}
diff --git a/ldap/admin/src/scripts/Migration.pm.in b/ldap/admin/src/scripts/Migration.pm.in
index 21122709..8bd2e344 100644
--- a/ldap/admin/src/scripts/Migration.pm.in
+++ b/ldap/admin/src/scripts/Migration.pm.in
@@ -217,7 +217,7 @@ sub init {
$self->{pkgname} = $pkgname;
$self->{oldsroot} = $oldsroot || "/opt/$oldpkgname";
- $self->{actualsroot} = $actualsroot || $oldsroot;
+ $self->{actualsroot} = $actualsroot || $self->{oldsroot};
$self->{silent} = $silent;
$self->{inffile} = $inffile;
$self->{keep} = $keep;
diff --git a/ldap/admin/src/scripts/Util.pm.in b/ldap/admin/src/scripts/Util.pm.in
index 364e9115..ce20bfb3 100644
--- a/ldap/admin/src/scripts/Util.pm.in
+++ b/ldap/admin/src/scripts/Util.pm.in
@@ -47,18 +47,19 @@ require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(portAvailable getAvailablePort isValidDN addSuffix getMappedEntries
process_maptbl check_and_add_entry getMappedEntries
- getHashedPassword debug createDSInstance createInfFromConfig
- isValidServerID);
+ getHashedPassword debug createInfFromConfig
+ isValidServerID isValidUser makePaths);
@EXPORT_OK = qw(portAvailable getAvailablePort isValidDN addSuffix getMappedEntries
process_maptbl check_and_add_entry getMappedEntries
- getHashedPassword debug createDSInstance createInfFromConfig
- isValidServerID);
+ getHashedPassword debug createInfFromConfig
+ isValidServerID isValidUser makePaths);
use strict;
use Socket;
use File::Temp qw(tempfile tempdir);
+use File::Basename qw(dirname);
$Util::debuglevel = 0;
# use like this:
@@ -131,7 +132,7 @@ sub isValidUser {
return ("dialog_ssuser_error", $user);
}
if (!$nuid) {
- return ("dialog_ssuser_root_warning");
+ debug(0, "Warning: using root as the server user id. You are strongly encouraged to use a non-root user.\n");
}
}
@@ -367,13 +368,17 @@ sub check_and_add_entry
my $attr;
foreach $attr ( @addtypes )
{
- debug(3, "Adding attr=$attr values=" . $aentry->getValues($attr) . " to entry $aentry->{dn}\n");
- $sentry->addValue( $attr, $aentry->getValues($attr) );
+ foreach my $val ($aentry->getValues($attr))
+ {
+ debug(3, "Adding attr=$attr value=$val to entry $aentry->{dn}\n");
+ $sentry->addValue( $attr, $val );
+ }
}
foreach $attr ( @reptypes )
{
+ my @vals = $aentry->getValues($attr);
debug(3, "Replacing attr=$attr values=" . $aentry->getValues($attr) . " to entry $aentry->{dn}\n");
- $sentry->setValues($attr, $aentry->getValues($attr));
+ $sentry->setValues($attr, @vals);
}
foreach $attr ( @deltypes )
{
@@ -761,23 +766,6 @@ sub getHashedPassword {
return $hashedpwd;
}
-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|;
- if (! -x $ds_newinst) {
- $ds_newinst = "@bindir@/ds_newinst.pl";
- }
- if (! -x $ds_newinst) {
- $ds_newinst = "ds_newinst.pl"; # just get from path
- }
- $? = 0; # clear error condition
- my $output = `$ds_newinst $inf->{filename}`;
- return ($?, $output);
-}
-
# this creates an Inf suitable for passing to createDSInstance
# except that it has a bogus suffix
sub createInfFromConfig {
@@ -787,35 +775,93 @@ sub createInfFromConfig {
my $fname = "$configdir/dse.ldif";
my $id;
($id = $inst) =~ s/^slapd-//;
- if (!open( DSELDIF, "$fname" )) {
+ if (! -f $fname) {
+ push @{$errs}, "error_opening_dseldif", $fname, $!;
+ return 0;
+ }
+ my $conn = new FileConn($fname, 1);
+
+ my $ent = $conn->search("cn=config", "base", "(objectclass=*)");
+ if (!$ent) {
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) {
- my $dn = $ent->getDN();
- if ($dn =~ /cn=config/) {
- print $outfh "[General]\n";
- print $outfh "FullMachineName = ", $ent->getValues('nsslapd-localhost'), "\n";
- print $outfh "SuiteSpotUserID = ", $ent->getValues('nsslapd-localuser'), "\n";
- print $outfh "ServerRoot = @serverdir@\n";
- print $outfh "[slapd]\n";
- print $outfh "RootDN = ", $ent->getValues('nsslapd-rootdn'), "\n";
- print $outfh "RootDNPwd = ", $ent->getValues('nsslapd-rootpw'), "\n";
- print $outfh "ServerPort = ", $ent->getValues('nsslapd-port'), "\n";
- print $outfh "ServerIdentifier = $id\n";
- print $outfh "Suffix = o=deleteAfterMigration\n";
- print $outfh "start_server= 0\n";
- last;
- }
+ print $outfh "[General]\n";
+ print $outfh "FullMachineName = ", $ent->getValues('nsslapd-localhost'), "\n";
+ print $outfh "SuiteSpotUserID = ", $ent->getValues('nsslapd-localuser'), "\n";
+ print $outfh "[slapd]\n";
+ print $outfh "RootDN = ", $ent->getValues('nsslapd-rootdn'), "\n";
+ print $outfh "RootDNPwd = ", $ent->getValues('nsslapd-rootpw'), "\n";
+ print $outfh "ServerPort = ", $ent->getValues('nsslapd-port'), "\n";
+ print $outfh "ServerIdentifier = $id\n";
+ print $outfh "start_server= 0\n";
+
+ my $suffix;
+ my $ent = $conn->search("cn=ldbm database,cn=plugins,cn=config",
+ "one", "(objectclass=*)");
+ if (!$ent) {
+ push @{$errs}, "error_opening_dseldif", $fname, $!;
+ close $outfh;
+ $conn->close();
+ return 0;
}
+ # use the userRoot suffix if available
+ while ($ent) {
+ $suffix = $ent->getValues('nsslapd-suffix');
+ last if ($ent->hasValue('cn', 'userRoot', 1));
+ $ent = $conn->nextEntry();
+ }
+ $conn->close();
+
+ print $outfh "Suffix = $suffix\n";
close $outfh;
- close DSELDIF;
my $inf = new Inf($inffile);
return $inf;
}
+# like File::Path mkpath, except we can set the owner and perm
+# of each new path and parent path created
+sub makePaths {
+ my ($path, $mode, $user, $group) = @_;
+ my $uid = getpwnam $user;
+ my $gid = -1; # default to leave it alone
+
+ if ($group) {
+ $gid = getgrnam $group;
+ }
+ my @dirnames = ($path);
+ my $parent = $path;
+ for ($parent = dirname($parent);
+ $parent and ($parent ne "/");
+ $parent = dirname($parent)) {
+ unshift @dirnames, $parent;
+ }
+ for (@dirnames) {
+ next if (-d $_);
+ $! = 0; # clear
+ mkdir $_, $mode;
+ if ($!) {
+ return ('error_creating_directory', $_, $!);
+ }
+ chown $uid, $gid, $_;
+ if ($!) {
+ return ('error_chowning_directory', $_, $!);
+ }
+ debug(1, "makePaths: created directory $_ mode $mode user $user group $group\n");
+ }
+
+ return ();
+}
+
1;
+
+# emacs settings
+# Local Variables:
+# mode:perl
+# indent-tabs-mode: nil
+# tab-width: 4
+# End:
diff --git a/ldap/admin/src/scripts/dscreate.map.in b/ldap/admin/src/scripts/dscreate.map.in
new file mode 100644
index 00000000..a475416a
--- /dev/null
+++ b/ldap/admin/src/scripts/dscreate.map.in
@@ -0,0 +1,67 @@
+# 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
+#
+# [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 = FullMachineName
+dsid = ServerIdentifier
+ds_user = SuiteSpotUserID
+ds_port = ServerPort
+rootdn = RootDN
+ds_suffix = Suffix
+ds_bename = ds_bename
+ds_passwd = HashedRootDNPwd
+
+schema_dir = schema_dir
+lock_dir = lock_dir
+tmp_dir = tmp_dir
+cert_dir = cert_dir
+ldif_dir = ldif_dir
+bak_dir = bak_dir
+inst_dir = inst_dir
+log_dir = log_dir
+config_dir = config_dir
+db_dir = db_dir
diff --git a/ldap/admin/src/scripts/dsorgentries.map.in b/ldap/admin/src/scripts/dsorgentries.map.in
new file mode 100644
index 00000000..2d59c226
--- /dev/null
+++ b/ldap/admin/src/scripts/dsorgentries.map.in
@@ -0,0 +1,50 @@
+# 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
+#
+# [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.
+#
+ds_suffix = Suffix
+naming_value = naming_value
diff --git a/ldap/admin/src/scripts/migrate-ds.pl.in b/ldap/admin/src/scripts/migrate-ds.pl.in
index e11d810c..7c5ea83d 100644
--- a/ldap/admin/src/scripts/migrate-ds.pl.in
+++ b/ldap/admin/src/scripts/migrate-ds.pl.in
@@ -61,5 +61,17 @@ my $res = new Resource("@propertydir@/migrate-ds.res",
my $mig = new Migration($res);
$mig->msg('begin_ds_migration', $mig->{oldsroot});
-migrateDS($mig);
+if (!migrateDS($mig)) {
+ exit 1;
+}
$mig->msg('end_ds_migration');
+
+END {
+ if ($mig) {
+ if (!$mig->{keep}) {
+ unlink $mig->{inffile};
+ }
+
+ $mig->doExit();
+ }
+}
diff --git a/ldap/admin/src/scripts/migrate-ds.res b/ldap/admin/src/scripts/migrate-ds.res
index f5cfef15..b98e0943 100644
--- a/ldap/admin/src/scripts/migrate-ds.res
+++ b/ldap/admin/src/scripts/migrate-ds.res
@@ -4,10 +4,11 @@ migration_exiting = Exiting . . .\nLog file is '%s'\n\n
instance_already_exists = The target directory server instance already exists at %s. Skipping migration. Note that if you want to migrate the old instance you will have to first remove the new one of the same name.\n\n
error_reading_entry = Could not read the entry '%s'. Error: %s\n
error_updating_merge_entry = Could not %s the migrated entry '%s' in the target directory server. Error: %s\n
-error_importing_migrated_db = Could not import the LDIF file '%s' for the migrated database. Error: %s. Please check the directory server error log for more details.\n
+error_importing_migrated_db = Could not import the LDIF file '%s' for the migrated database. Error: %s. Output: %s\n
error_reading_olddbconfig = Could not read the old database configuration information. Error: %s\n
error_migrating_schema = Could not copy old schema file '%s'. Error: %s\n
error_copying_dbdir = Could not copy database directory '%s' to '%s'. Error: %s\n
error_copying_dbfile = Could not copy database file '%s' to '%s'. Error: %s\n
error_dbsrcdir_not_exist = Could not copy from the database source directory '%s' because it does not exist. Please check your configuration.\n
error_no_instances = Could not find any instances in the old directory '%s' to migrate.\n
+error_removing_temp_db_files = Could not remove the temporary db files in '%s' to clear the directory in preparation for the migrated db files. Error: %s\n
diff --git a/ldap/admin/src/scripts/setup-ds.pl.in b/ldap/admin/src/scripts/setup-ds.pl.in
index b455a579..99969a22 100644
--- a/ldap/admin/src/scripts/setup-ds.pl.in
+++ b/ldap/admin/src/scripts/setup-ds.pl.in
@@ -47,6 +47,7 @@ use Inf;
use Resource;
use DialogManager;
use Util;
+use DSCreate;
my $res = new Resource("@propertydir@/setup-ds.res");
@@ -70,13 +71,14 @@ if (!$setup->{silent}) {
$setup->{inf}->write();
}
-my @errs;
-my ($rc, $output) = createDSInstance($setup->{inf}, \@errs);
-if ($rc) {
+my @errs = createDSInstance($setup->{inf});
+if (@errs) {
$setup->msg(@errs);
- $setup->msg($FATAL, 'error_creating_dsinstance', $rc, $output);
+ $setup->msg($FATAL, 'error_creating_dsinstance',
+ $setup->{inf}->{slapd}->{ServerIdentifier});
} else {
- $setup->msg('created_dsinstance', $output);
+ $setup->msg('created_dsinstance',
+ $setup->{inf}->{slapd}->{ServerIdentifier});
}
END {
diff --git a/ldap/admin/src/scripts/setup-ds.res.in b/ldap/admin/src/scripts/setup-ds.res.in
index 329a7c24..5d2cdd89 100644
--- a/ldap/admin/src/scripts/setup-ds.res.in
+++ b/ldap/admin/src/scripts/setup-ds.res.in
@@ -87,8 +87,8 @@ error_creating_suffix_backend = Could not create the suffix '%s'. There was an
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
+error_creating_dsinstance = Error: Could not create directory server instance '%s'.\n
+created_dsinstance = Your new DS instance '%s' was successfully created.\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
@@ -96,7 +96,6 @@ error_deleteall_entries = Error deleting entry '%s' and all children. Error: %s
error_adding_entry = Error adding entry '%s'. Error: %s\n
error_updating_entry = Error updating entry '%s'. Error: %s\n
-
error_invalid_param = The parameter '%s' has an invalid value '%s'.\n
error_port_available = The port number '%s' is not available for use. This may be due to an\
invalid port number, or the port already being in use by another\
@@ -104,3 +103,19 @@ program, or low port restriction. Please choose another value for\
ServerPort. Error: $!\n
error_invalid_serverid = The ServerIdentifier '%s' contains invalid characters. It must\
contain only alphanumeric characters and the following: #%,.:@_-\n
+error_opening_scripttmpl = Could not open the script template file '%s'. Error: %s\n
+error_creating_directory = Could not create directory '%s'. Error: %s\n
+error_chowning_directory = Could not change ownership of directory '%s' to userid '%s': Error: %s\n
+error_chowning_file = Could not change ownership of '%s' to userid '%s': Error: %s\n
+error_chmoding_file = Could not change permissions of '%s': Error: %s\n
+error_chgrping_directory = Could not change group of directory '%s' to group '%s': Error: %s\n
+error_creating_file = Could not create file '%s'. Error: %s\n
+error_copying_file = Could not copy file '%s' to '%s'. Error: %s\n
+error_enabling_feature = Could not enable the directory server feature '%s'. Error: %s\n
+error_importing_ldif = Could not import LDIF file '%s'. Error: %s. Output: %s\n
+error_starting_server = Could not start the directory server using command '%s'. The last line from the error log was '%s'. Error: %s\n
+error_missing_port_and_ldapi = Either ServerPort or ldapifilepath must be specified. The server must listen to something.\n
+error_missing_port = No ServerPort specified. The server must have a port number to listen to (default 389).\n
+error_server_already_exists = Error: the server already exists at '%s'\
+Please remove it first if you really want to recreate it,\
+or use a different ServerIdentifier to create another instance.\n
diff --git a/ldap/admin/src/scripts/template-restart-slapd.in b/ldap/admin/src/scripts/template-restart-slapd.in
new file mode 100644
index 00000000..6f5c0c89
--- /dev/null
+++ b/ldap/admin/src/scripts/template-restart-slapd.in
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Script that restarts the ns-slapd server.
+# Exit status can be:
+# 0: Server restarted successfully
+# 1: Server could not be started
+# 2: Server started successfully (was not running)
+# 3: Server could not be stopped
+
+server_already_stopped=0
+{{INST-DIR}}/stop-slapd
+status=$?
+if [ $status -eq 1 ] ; then
+ exit 3;
+else
+ if [ $status -eq 2 ] ; then
+ server_already_stopped=1
+ fi
+fi
+{{INST-DIR}}/start-slapd
+status=$?
+if [ $server_already_stopped -eq 1 ] && [ $status -eq 0 ] ; then
+ exit 2;
+fi
+exit $status