#{{PERL-EXEC}} # # BEGIN COPYRIGHT BLOCK # Copyright 2001 Sun Microsystems, Inc. # Portions copyright 1999, 2001-2004 Netscape Communications Corporation. # All rights reserved. # END COPYRIGHT BLOCK # use Time::localtime; BEGIN { require 'uname.lib'; $| = 1; $isNT = -d '\\'; $PATHSEP = $isNT ? "\\" : "/"; $SEP = $isNT ? ";" : ":" ; $exitCode = 0; @INC = ( '.', '../../../admin/admin/bin'); grep { s@/@\\@g } @INC if $isNT; $script_suffix = $isNT ? ".bat" : ""; $exe_suffix = $isNT ? ".exe" : ""; # NT needs quotes around some things unix doesn't $quote = $isNT ? "\"" : ""; if ($isNT) { # we have to pass batch files directly to the NT command interpreter $com_spec = $ENV{ComSpec}; if (!$com_spec) { $com_spec = $ENV{COMSPEC}; } if (!$com_spec || ! -f $com_spec) { # find the first available command interpreter foreach $drive (c..z) { $com_spec = "$drive:\\winnt\\system32\\cmd.exe"; last if (-f $com_spec); $com_spec = undef; } if (! $com_spec) { # punt and pray $com_spec = 'c:\winnt\system32\cmd.exe'; } } $os = "WINNT"; } else { $os = &uname("-s"); if ($os eq "SunOS") { $isSolaris9 = ( &uname("-r") eq "5.9" ); } } if ( ($os eq "AIX") || ($os eq "HP-UX") ) { $sigChildHandler = 'sigChildHandler'; } SWITCH: { if ($os eq "AIX") { $LIB_PATH = "LIBPATH" ; last SWITCH ; } if ($os eq "HP-UX") { $LIB_PATH = "SHLIB_PATH" ; last SWITCH ; } if ($isNT) { $LIB_PATH = "PATH" ; last SWITCH ; } else { $LIB_PATH = "LD_LIBRARY_PATH" ; last SWITCH ; } } $slapdExecName = $isNT ? 'slapd.exe' : 'ns-slapd'; select STDERR; $| = 1; select STDOUT; $| = 1; } $TRACELEVEL = 0; ${root} = "{{DS-ROOT}}" ; ${type} = "" ; ${newname} = "" ; ${newport} = "" ; ${rootDN} = "" ; ${rootpwd} = "" ; ${localhost} = "" ; ${LogFileReport} = "" ; # get input users &getParameters() ; ${oldHome} = "${oldDir}${PATHSEP}$type-$oldname" ; ${oldConfDir} = "${oldHome}${PATHSEP}config${PATHSEP}" ; ${oldSlapdConf} = "${oldConfDir}slapd.conf" ; ${serverHome} = "${root}${PATHSEP}$type-$newname" ; ${ldif_rep} = "${oldConfDir}ldif${PATHSEP}" ; ${curdir} = getCwd(); if (!(-d $serverHome)) { print("\n$serverHome doesn't exist\n"); exit(1); } if (!(-d $oldHome)) { print("\n$oldHome doesn't exist\n"); exit(1); } if ($olddatadir && !(-d $olddatadir)) { print("\n$olddatadir doesn't exist\n"); exit(1); } $ENV{"$LIB_PATH"} = "$root${PATHSEP}lib${SEP}".$ENV{"$LIB_PATH"} ; if ($isSolaris9) { $ENV{"$LIB_PATH"} = "$root${PATHSEP}lib${PATHSEP}nsPerl5.6.1${PATHSEP}lib${PATHSEP}sun4-solaris${PATHSEP}CORE${SEP}".$ENV{"$LIB_PATH"} ; } if ($isNT) { $ENV{"PERL5LIB"} = "$root${PATHSEP}lib${PATHSEP}nsPerl5.6.1${PATHSEP}site${PATHSEP}lib${SEP}".$ENV{"PERL5LIB"} ; } else { $ENV{"PERL5LIB"} = "$root${PATHSEP}lib${PATHSEP}nsPerl5.6.1${PATHSEP}lib${PATHSEP}site${SEP}".$ENV{"PERL5LIB"} ; } # get the version of the DS to migrate ($oldVersion, $oldMinor) = &getVersion($oldDir, $oldversionstr); # get the version of the new DS ($Version, $Minor) = &getVersion($root); if ($Version >= 6) { if ($oldVersion == 4) { $myscript = "migrateTo6" ; printMsg("\n******* Migration from $oldVersion.$oldMinor to $Version.$Minor Directory Server *********\n"); } elsif ($oldVersion == 5 ) { printMsg("\nWarning. You may experience some problems if the version of directory server you want to migrate is not a 5.0 or 5.1") if ($oldMinor > 1); $myscript = "migrate5to6" ; printMsg("\n******* Migration from $oldVersion.$oldMinor to $Version.$Minor Directory Server *********\n"); } else { die "We don't support the version of directory server you want to migrate"; } } else { die "\n\nThe version of directory you want to upgrade is not a 6.x product\nMigration aborted\n"; } my $start_time = gmtime ; @args = ($^X, $myscript, @ARGV, '-L', $LogFileReport); $exitCode = &mySystem(@args); #die "Error: @args: $!" if ($exitCode != 0); open(LOGFILE,">> $LogFileReport") or die "\nCan't write to $LogFileReport\n$!\n"; if (! $exitCode) { my $end_time = gmtime ; printMsg("-> Migration started at $start_time\n"); printMsg("-> Migration ended at $end_time\n\n"); } printMsg("***********************************************\n\n"); print("-> The migration report file is available at: $LogFileReport\n\n"); close(LOGFILE); ####################################################################################################################### sub usage { print(STDERR "\nUsage: $0 -D rootdn { -w password | -w - | -j filename } -p port \n"); print(STDERR " -o oldInstancePath -n newInstancePath [-t tracelevel] \n"); print(STDERR " [-L logfile] [-noinput]\n"); print(STDERR "************** parameters in brackets are optionals, others are required **************\n"); print(STDERR " Opts: -D rootdn - new Directory Manager\n"); print(STDERR " : -w password - new Directory Manager's password\n"); print(STDERR " : -w - - Prompt for new Directory Manager's password\n"); print(STDERR " : -j filename - Read new Directory Manager's password from file\n"); print(STDERR " : -p port - new Directory Server port\n"); print(STDERR " : -o oldInstancePath - Path of the old instance to migrate \n"); print(STDERR " : -n newInstancePath - Path of the new instance\n"); print(STDERR " : [-d dataPath] - Path to directory containing data files to import into new instance\n"); print(STDERR " : [-v oldVersion] - Version of old instance (obtained by running $slapdExecName -v\n"); print(STDERR " : [-t tracelevel] - specify the level of trace (0..3) by default setup to 1\n"); print(STDERR " : [-L logfile] - specify the file to log the migration report \n"); print(STDERR " : [-noinput] - no user interventions during migration processing to solve conflicts\n"); } ####################################################################################################################### # get input users sub getParameters { my $exit = 0 ; my $i = 0; my $pwdfile= ""; while ($i <= $#ARGV) { if ( "$ARGV[$i]" eq "-D" ) { # directory manager if (! $rootDN) { $rootDN = $ARGV[++$i] ; } else { &usage() ; exit(1); } } elsif ("$ARGV[$i]" eq "-w") { # password if (! $rootpwd) { $rootpwd = $ARGV[++$i] ; } else { &usage() ; exit(1); } } elsif ("$ARGV[$i]" eq "-j") { # password file if (! $pwdfile) { $pwdfile = $ARGV[++$i] ; } else { &usage() ; exit(1); } } elsif ("$ARGV[$i]" eq "-o") { # old instance path if (! $oldHome ) { $oldHome = $ARGV[++$i] ; grep { s@\\@/@g } $oldHome if $isNT ; if ($oldHome =~ /[\"]?(.*)?[\"]?/) { $oldHome = $1 ; } if ($oldHome =~ m@^(.*)/([^-/]*)-([^/]*)[/]?$@) { $oldDir = $1 ; $type = $2 ; $oldname = $3 ; if ($isNT) { $oldDir = lc($oldDir) ; $type = lc($type) ; $oldname = lc($oldname) ; $oldHome = lc($oldHome) ; grep { s@/@\\@g } $oldDir ; grep { s@/@\\@g } $oldHome ; } } else { print("\nThe old instance path is not correct. It must be like slapd-instancename"); &usage(); exit(1); } } else { &usage() ; exit(1); } } elsif ("$ARGV[$i]" eq "-n") { # 5.x instance path if (! $serverHome ) { $serverHome = $ARGV[++$i] ; grep { s@\\@/@g } $root if $isNT ; grep { s@\\@/@g } $serverHome if $isNT ; if ($serverHome =~ /[\"]?(.*)?[\"]?/) { $serverHome = $1 ; } if ($serverHome =~ m@^(.*?)/?([^/-]*)-([^/]*)[/]?$@) { $root = $1 if ($1); $type = $2 ; $newname = $3 ; if ($isNT) { $root = lc($root) ; $type = lc($type) ; $newname = lc($newname) ; $serverHome = lc($serverHome) ; grep { s@/@\\@g } $root ; grep { s@/@\\@g } $serverHome ; } } else { print("\nThe new instance path is not correct. It must be like slapd-instancename"); &usage(); exit(1); } } else { &usage() ; exit(1); } } elsif ("$ARGV[$i]" eq "-p") { # 5.x DS port if (! $newport ) { $newport = $ARGV[++$i] ; } else { &usage() ; exit(1); } } elsif ("$ARGV[$i]" eq "-d") { # old instance LDIF data dir if (! $olddatadir ) { $olddatadir = $ARGV[++$i] ; } else { &usage() ; exit(1); } } elsif ("$ARGV[$i]" eq "-v") { # old version if (! $oldversionstr ) { $oldversionstr = $ARGV[++$i] ; } else { &usage() ; exit(1); } } elsif ("$ARGV[$i]" eq "-t") { # TRACELEVEL my $value = $ARGV[++$i] ; if ($value =~ /[0-3]/) { $TRACELEVEL = $value ; } else { print("\nThe tracelevel must belong to 0..3 interval"); &usage(); exit(); } } elsif ("$ARGV[$i]" eq "-noinput") { # no user interventions during processing } elsif ("$ARGV[$i]" eq "-L") { # user defined logfile for the migration $LogFileReport = $ARGV[++$i]; } else { &usage() ; exit(1); } $i++; } if (! $rootDN) { print("\nThe rootDN is missing"); $exit = 1; } if ($pwdfile ne "") { # Open file and get the password unless (open (RPASS, $pwfile)) { die "Error, cannot open password file $passwdfile\n"; } $rootpwd = ; chomp($rootpwd); close(RPASS); } elsif ($rootpwd eq "-"){ # Read the password from terminal die "The '-w -' option requires an extension library (Term::ReadKey) which is not\n", "part of the standard perl distribution. If you want to use it, you must\n", "download and install the module. You can find it at\n", "http://www.perl.com/CPAN/CPAN.html\n"; # Remove the previous line and uncomment the following 6 lines once you have installed Term::ReadKey module. # use Term::ReadKey; # print "Bind Password: "; # ReadMode('noecho'); # $rootpwd = ReadLine(0); # chomp($rootpwd); # ReadMode('normal'); } if (! $rootpwd) { print("\nThe rootpwd is missing"); $exit = 1 ; } if (! $newport) { print("\nThe port is missing"); $exit = 1; } if (! $serverHome) { print("\nThe new instance path is missing"); $exit = 1; } if (! $oldHome) { print("\nThe old instance path is missing"); $exit = 1; } if ((! $LogFileReport) && $serverHome) { ($sec, $min, $hour, $dd, $mm, $yy) = &GetTime(); $LogFileReport = "${serverHome}${PATHSEP}logs${PATHSEP}Migration_${dd}${mm}${yy}_${hour}${min}${sec}.log"; } if ($exit) { &usage() ; exit(1); } } ############################################################################# # printMsg print message to the user standard output. sub printMsg { my $TypeMsg = shift ; my $Msg = shift ; my $LineNb = shift ; if ($LineNb) { printTrace("Line: $LineNb, $TypeMsg, $Msg"); } else { printTrace("$TypeMsg $Msg"); } } ############################################################################# # print message error to the user standard output. sub printTrace { my $Msg = shift ; my $level = shift ; if ($level <= $TRACELEVEL) { print($Msg); print LOGFILE $Msg; } } ############################################################################# sub mySystem { my $cmd = $_[0]; # the system {$cmd} avoids some NT shell quoting problems if the $cmd # needs to be quoted e.g. contains spaces; the map puts double quotes # around the arguments on NT which are stripped by the command # interpreter cmd.exe; but don't quote things which are already quoted my @fixargs = map { /^[\"].*[\"]$/ ? $_ : $quote . $_ . $quote } @_; my $rc = 0; if ($cmd =~ /[.](bat|cmd)$/) { # we have to pass batch files directly to the NT command interpreter $cmd = $com_spec; # print "system $cmd /c \"@fixargs\"\n"; $rc = system {$cmd} '/c', "\"@fixargs\""; } else { # print "system $cmd \"@fixargs\"\n"; if($isNT) { $rc = system "\"@fixargs\""; } else { $rc = system @fixargs; } } return $rc; } ############################################################################# sub GetTime { my $tm = localtime; (my $sec, my $min, my $hour, my $dd, my $mm, my $yy) = ($tm->sec, $tm->min, $tm->hour, $tm->mday, ($tm->mon)+1, ($tm->year)+1900); $sec = "0$sec" unless $sec > 9 ; $min = "0$min" unless $min > 9 ; $hour = "0$hour" unless $hour > 9 ; $dd = "0$dd" unless $dd > 9 ; $mm = "0$mm" unless $mm > 9 ; return ($sec, $min, $hour, $dd, $mm, $yy); } ############################################################################# sub getVersion { my $dir = shift; my $versionstr = shift; my $version = 0; my $minor = 0; my $buildNumber = 0; my $progDir = "${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server${PATHSEP}"; my $progDir2 = "${PATHSEP}bin${PATHSEP}slapd${PATHSEP}"; # find the slapd executable if (!$versionstr) { # version not specified on cmd line - find it $prog = $dir . $progDir . $slapdExecName; if (! -f $prog) { $prog = $dir . $progDir2 . $slapdExecName; if (-f $prog && $isNT) { # if slapd is in bin/slapd and we're on NT, just assume version 1; # apparently, slapd.exe doesn't like the -v argument . . . return ( '1', $minor ); } else{ die "Could not run slapd program $prog: $!"; } } else { chdir($dir . $progDir); } $ENV{"$LIB_PATH"}= "$dir${PATHSEP}lib${SEP}". "$dir${PATHSEP}bin${PATHSEP}slapd${PATHSEP}lib${SEP}". "$dir${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server${SEP}". $ENV{"$LIB_PATH"}; # read the old version from the old slapd program open(F, "${quote}${quote}$prog${quote} -v${quote} 2>&1 |") or die "Could not run slapd program $prog: $!"; sleep(1); # allow some data to accumulate in the pipe # print "Output from $prog -v:\n"; while () { if (/^Netscape-Directory/ || /^iPlanet-Directory/i) { $versionstr = $_; last; } } $code = close(F); # print "$prog returned code=$code status=$?\n"; $ENV{"$LIB_PATH"}="$root${PATHSEP}lib${SEP}".$ENV{"$LIB_PATH"}; } if ($versionstr =~ /^Netscape-Directory\/(\d+)\.(\d+)(?:b\d)*\s+(\S+)/) { $version = $1; $minor = $2; $buildNumber = $3; } elsif ($versionstr =~ /^Netscape-Directory\(restrict?ed-mode\)\/(\d+)\.(\d+)\s+(\S+)/) { # we can have restricted-mode or restriced-mode ... $version = $1; $minor = $2; $buildNumber = $3; } elsif ($versionstr =~ /^iPlanet-Directory\/(\d+)\.(\d+)\s+(\S+)/i) { $version = $1; $minor = $2; $buildNumber = $3; } elsif ($versionstr =~ /(\d+)\.(\d+)/) { $version = $1; $minor = $2; } if ($version == 0) { die "\nCould not determine version of the directory server in $dir: \n"; } # distinguish the 4.1 and the 4.11 thanks to the buildNumber if (($version == 4) && ($minor == 1)){ if (! ($buildNumber =~ /^B99\.16/)) { # it's not a 4.1 Netscape Directory Server => it's a 4.11 $minor = 11 ; } } chdir($curdir) or die "Could not change directory to $curdir: $!" ; return ( $version, $minor ); } ############################################################################################### # get current directory sub getCwd { my $command = $isNT ? "cd" : "/bin/pwd"; open(PWDCMD, "$command 2>&1 |") or die "Error: could not execute $command: $!"; # without the following sleep, reading from the pipe will # return nothing; I guess it gives the pwd command time # to get some data to read . . . sleep(1); my $currentdir; while () { if (!$currentdir) { chomp($currentdir = $_); } } my $code = close(PWDCMD); # if ($code || $?) { # print "$command returned code=$code status=$? dir=$curdir\n"; # } # print "getCwd curdir=\[$curdir\]\n"; return $currentdir; }