Migration.pm.in 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. # BEGIN COPYRIGHT BLOCK
  2. # Copyright (C) 2007 Red Hat, Inc.
  3. # All rights reserved.
  4. #
  5. # License: GPL (version 3 or any later version).
  6. # See LICENSE for details.
  7. # END COPYRIGHT BLOCK
  8. #
  9. ###########################
  10. #
  11. # This perl module provides a way to set up a new installation after
  12. # the binaries have already been extracted. This is typically after
  13. # using native packaging support to install the package e.g. RPM,
  14. # pkgadd, depot, etc. This script will show the license, readme,
  15. # dsktune, then run the usual setup pre and post installers.
  16. #
  17. ##########################
  18. package Migration;
  19. use Setup;
  20. use Exporter ();
  21. @ISA = qw(Exporter Setup);
  22. @EXPORT = qw();
  23. @EXPORT_OK = qw();
  24. # hostname
  25. use Sys::Hostname;
  26. # load perldap
  27. use Mozilla::LDAP::Conn;
  28. use Mozilla::LDAP::Utils qw(normalizeDN);
  29. use Mozilla::LDAP::API qw(ldap_explode_dn);
  30. use Mozilla::LDAP::LDIF;
  31. use Getopt::Long;
  32. use SetupLog;
  33. use DSUtil;
  34. # process command line options
  35. Getopt::Long::Configure(qw(bundling)); # bundling allows -ddddd
  36. sub VersionMessage {
  37. print "@capbrand@ Directory Server Migration Program Version @PACKAGE_VERSION@\n";
  38. }
  39. sub HelpMessage {
  40. print <<EOF;
  41. INTRODUCTION
  42. This script will copy instances (data and configuration) from the old
  43. server root directory to their new FHS locations. This script does a
  44. copy only - the data in the old instances will be left untouched. The
  45. old instances must be shutdown first to ensure that the databases are
  46. copied safely. During migration your migrated instances will be started.
  47. USAGE
  48. $0 [--options] -- [args]
  49. options:
  50. --help This message
  51. --version Print the version and exit
  52. --debug Turn on debugging
  53. --oldsroot The old server root directory to migrate from
  54. --actualsroot This is the old location of the old server root.
  55. See below.
  56. --silent Use silent setup - no user input
  57. --file=name Use the file 'name' in .inf format to supply the
  58. default answers
  59. --keepcache Do not delete the temporary .inf file generated by
  60. this program
  61. --logfile Log migration messages to this file - otherwise, a temp
  62. file will be used
  63. --instance By default, all directory server instances will be
  64. migrated. You can use this argument to specify one
  65. or more (e.g. -i slapd-foo -i slapd-bar) if you do
  66. not want to migrate all of them.
  67. --cross See below.
  68. For all options, you can also use the short name e.g. -h, -d, etc.
  69. For the -d argument, specifying it more than once will increase the
  70. debug level e.g. -ddddd
  71. args:
  72. You can supply default .inf data in this format:
  73. section.param=value
  74. e.g.
  75. General.FullMachineName=foo.example.com
  76. or
  77. "slapd.Suffix=dc=example,dc=com"
  78. Values passed in this manner will override values in an .inf file
  79. given with the -f argument.
  80. actualsroot:
  81. This is used when you must migrate from one machine to another. The
  82. usual case is that you have mounted the old server root on a different
  83. root directory, either via a network mount, or by copying a tarball
  84. made using a relative directory on the source machine to the
  85. destination machine and untarring it.
  86. For example: machineA is a 32bit machine, and you want to migrate your
  87. servers to a new 64bit machine. Lets assume your old server root on
  88. machineA was /opt/myds, and your new machine also wants to use a
  89. server root of /opt/myds. There are a couple of different ways to
  90. proceed. Either make a tarball of opt/myds from machineA using a
  91. relative path (i.e. NOT /opt/myds) or use NFS to mount
  92. machineA:/opt/myds on a different mount point
  93. (e.g. machineB:/migration/opt/myds).
  94. If you do this, you should give the old "real" server root (/opt/myds)
  95. as the --actualsroot argument, and use /migration/opt/myds for the
  96. --oldsroot argument. That is, the oldsroot is the physical location of
  97. the files on disk. The actualsroot is the old value of the server root
  98. on the source machine.
  99. cross:
  100. Also known as crossplatform, or 'c', or 'x'.
  101. This is when the source machine is a different architecture than the
  102. destination machine. In this case, only certain data will be available
  103. for migration. Changelog information will not be migrated, and replicas
  104. will need to be reinitialized (if migrating masters or hubs). This type
  105. of migration requires that all of your old databases have been dumped
  106. to LDIF format, and the LDIF file must be in the default database directory
  107. (usually /opt/@brand@-ds/slapd-instance/db), and the LDIF file must have
  108. the same name as the database instance directory, with a ".ldif". For
  109. example, if you have
  110. /opt/@brand@-ds/slapd-instance/db/userRoot/ and
  111. /opt/@brand@-ds/slapd-instance/db/NetscapeRoot/
  112. you must first use db2ldif to export these databases to LDIF e.g.
  113. cd /opt/@brand@-ds/slapd-instance
  114. ./db2ldif -n userRoot -a /opt/@brand@-ds/slapd-instance/db/userRoot.ldif and
  115. ./db2ldif -n NetscapeRoot -a /opt/@brand@-ds/slapd-instance/db/NetscapeRoot.ldif
  116. Then you must somehow make your old server root directory available on
  117. the destination machine, either by creating a tar archive on the source
  118. and copying it to the destination, or by network mounting the source
  119. directory on the destination machine.
  120. EOF
  121. }
  122. sub init {
  123. my $self = shift;
  124. $self->{res} = shift;
  125. my ($silent, $inffile, $keep, $preonly, $logfile, $oldsroot, $actualsroot, $crossplatform);
  126. my @instances;
  127. GetOptions('help|h|?' => sub { VersionMessage(); HelpMessage(); exit 0 },
  128. 'version|v' => sub { VersionMessage(); exit 0 },
  129. 'debug|d+' => \$DSUtil::debuglevel,
  130. 'silent|s' => \$silent,
  131. 'file|f=s' => \$inffile,
  132. 'keepcache|k' => \$keep,
  133. 'preonly|p' => \$preonly,
  134. 'logfile|l=s' => \$logfile,
  135. 'oldsroot|o=s' => \$oldsroot,
  136. 'actualsroot|a=s' => \$actualsroot,
  137. 'crossplatform|cross|c|x' => \$crossplatform,
  138. 'instance|i=s' => \@instances
  139. );
  140. my $pkgname = "@package_name@";
  141. # this is the new pkgname which may be something like
  142. # 389-ds-base - we have to strip off the -suffix
  143. if ($pkgname =~ /-(core|base)$/) {
  144. $pkgname =~ s/-(core|base)$//;
  145. }
  146. my $oldpkgname = "@brand@-ds";
  147. $self->{pkgname} = $pkgname;
  148. $oldsroot =~ s/\/+$//; # trim trailing '/'s, if any
  149. $self->{oldsroot} = $oldsroot || "/opt/$oldpkgname";
  150. $actualsroot =~ s/\/+$//; # trim trailing '/'s, if any
  151. $self->{actualsroot} = $actualsroot || $self->{oldsroot};
  152. $self->{silent} = $silent;
  153. $self->{keep} = $keep;
  154. $self->{preonly} = $preonly;
  155. $self->{logfile} = $logfile;
  156. $self->{crossplatform} = $crossplatform;
  157. $self->{log} = new SetupLog($self->{logfile}, "migrate");
  158. DSUtil::setDebugLog($self->{log});
  159. $self->{start_servers} = 1; # start servers as soon as they are migrated
  160. # if user supplied inf file, use that to initialize
  161. if (defined($inffile)) {
  162. $self->{inf} = new Inf($inffile);
  163. } else {
  164. $self->{inf} = new Inf;
  165. }
  166. # see if user passed in default inf values - also, command line
  167. # arguments override those passed in via an inf file - this
  168. # allows the reuse of .inf files with some parameters overridden
  169. if (!$self->{inf}->updateFromArgs(@ARGV)) {
  170. HelpMessage();
  171. exit 1;
  172. }
  173. # this is the base config directory - the directory containing
  174. # the slapd-instance instance specific config directories
  175. $self->{configdir} = $ENV{DS_CONFIG_DIR} || "@instconfigdir@";
  176. # get list of instances to migrate
  177. if (! @instances) {
  178. # an instance must be a directory called $oldsroot/slapd-something and the file
  179. # $oldsroot/slapd-something/config/dse.ldif must exist
  180. @instances = grep { -d && -f "$_/config/dse.ldif" && ($_ =~ s,$self->{oldsroot}/,,) }
  181. glob("$self->{oldsroot}/slapd-*");
  182. }
  183. if (!@instances) {
  184. $self->msg($FATAL, "error_no_instances", $self->{oldsroot});
  185. VersionMessage();
  186. HelpMessage();
  187. exit 1;
  188. }
  189. $self->{instances} = \@instances;
  190. }
  191. # log only goes the the logfile
  192. sub log {
  193. my $self = shift;
  194. my $level = shift;
  195. $self->{log}->logMessage($level, "Migration", @_);
  196. }
  197. sub doExit {
  198. my $self = shift;
  199. my $code = shift;
  200. if (!defined($code)) {
  201. $code = 1;
  202. }
  203. if ($code) {
  204. $self->msg($FATAL, 'migration_exiting', $self->{log}->{filename});
  205. } else {
  206. $self->msg($SUCCESS, 'migration_exiting', $self->{log}->{filename});
  207. }
  208. exit $code;
  209. }
  210. sub migrateSecurityFiles {
  211. my $self = shift;
  212. my $inst = shift;
  213. my $destdir = shift;
  214. my $oldroot = $self->{oldsroot};
  215. if (! -d "$oldroot/alias") {
  216. $self->msg('old_secdir_error', "$oldroot/alias", $!);
  217. return 0;
  218. } elsif (! -d $destdir) {
  219. $self->msg('new_secdir_error', $destdir, $!);
  220. return 0;
  221. } else {
  222. if (-f "$oldroot/alias/$inst-cert8.db") {
  223. $self->log($INFO, "Copying $oldroot/alias/$inst-cert8.db to $destdir/cert8.db\n");
  224. if (system ("cp -p $oldroot/alias/$inst-cert8.db $destdir/cert8.db")) {
  225. $self->msg($FATAL, 'error_copying_certdb', "$oldroot/alias/$inst-cert8.db",
  226. "$destdir/cert8.db", $!);
  227. return 0;
  228. }
  229. } else {
  230. $self->log($DEBUG, "No file to migrate: $oldroot/alias/$inst-cert8.db\n");
  231. }
  232. if (-f "$oldroot/alias/$inst-key3.db") {
  233. $self->log($INFO, "Copying $oldroot/alias/$inst-key3.db to $destdir/key3.db\n");
  234. if (system ("cp -p $oldroot/alias/$inst-key3.db $destdir/key3.db")) {
  235. $self->msg($FATAL, 'error_copying_keydb', "$oldroot/alias/$inst-key3.db",
  236. "$destdir/key3.db", $!);
  237. return 0;
  238. }
  239. } else {
  240. $self->log($DEBUG, "No file to migrate: $oldroot/alias/$inst-key3.db\n");
  241. }
  242. if (-f "$oldroot/alias/secmod.db") {
  243. $self->log($INFO, "Copying $oldroot/alias/secmod.db to $destdir/secmod.db\n");
  244. if (system ("cp -p $oldroot/alias/secmod.db $destdir/secmod.db")) {
  245. $self->msg($FATAL, 'error_copying_secmoddb', "$oldroot/alias/secmod.db",
  246. "$destdir/secmod.db", $!);
  247. return 0;
  248. }
  249. } else {
  250. $self->log($DEBUG, "No file to migrate: $oldroot/alias/secmod.db\n");
  251. }
  252. if (-f "$oldroot/alias/$inst-pin.txt") {
  253. $self->log($INFO, "Copying $oldroot/alias/$inst-pin.txt to $destdir/pin.txt\n");
  254. if (system ("cp -p $oldroot/alias/$inst-pin.txt $destdir/pin.txt")) {
  255. $self->msg($FATAL, 'error_copying_pinfile', "$oldroot/alias/$inst-pin.txt",
  256. "$destdir/pin.txt", $!);
  257. return 0;
  258. }
  259. } else {
  260. $self->log($INFO, "No $oldroot/alias/$inst-pin.txt to migrate\n");
  261. }
  262. if (-f "$oldroot/shared/config/certmap.conf") {
  263. $self->log($INFO, "Copying $oldroot/shared/config/certmap.conf to $destdir/certmap.conf\n");
  264. if (system ("cp -p $oldroot/shared/config/certmap.conf $destdir/certmap.conf")) {
  265. $self->msg($FATAL, 'error_copying_certmap', "$oldroot/shared/config/certmap.conf",
  266. "$destdir/certmap.conf", $!);
  267. return 0;
  268. }
  269. } else {
  270. $self->log($INFO, "No $oldroot/shared/config/certmap.conf to migrate\n");
  271. }
  272. }
  273. return 1;
  274. }
  275. #############################################################################
  276. # Mandatory TRUE return value.
  277. #
  278. 1;
  279. # emacs settings
  280. # Local Variables:
  281. # mode:perl
  282. # indent-tabs-mode: nil
  283. # tab-width: 4
  284. # End: