From 55c83d30be3ef65e859ee380f5fce343f31dd8d9 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Thu, 19 Apr 2012 02:11:08 +0200 Subject: LDAP migration (not tested!). --- ldap-migrate.pl | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100755 ldap-migrate.pl diff --git a/ldap-migrate.pl b/ldap-migrate.pl new file mode 100755 index 0000000..014f868 --- /dev/null +++ b/ldap-migrate.pl @@ -0,0 +1,169 @@ +#!/usr/bin/perl + +####################################################################### +# Migration from MySQL to LDAP. # +####################################################################### + +# This file depends on the LDAP version of Fripost::Schema. +# (git checkout ldap) +# +# It reads LDAP's configuration from `~/.fripost.yml', and the MySQL +# configuration from `./dbh.yml'. (The MySQL configuration is the old +# configuration (default.yml) that was read by the vanilla fripost-tools +# (from the master branch). +# +# Set the flag `--pretend' to only simulate the migration. +# REMARK: The migration has not been tested yet! +# +# The changes and warnings are dumped both into the standard error, and +# into a log file "fripost-migration-$$.log", where "$$" is the current +# PID. +# +# REMARK: the columns `create_date' and `change_date' are ignored +# (reseted, actually), since the corresponding LDAP attributes are set +# by the server and there is no way for the client to force their value. +# +# Some other columns may be ignored during the migration (e.g., +# `domain.description' if it does not have the right form), but the +# program is supposed to say so. +# +# REMARK: The columns `alias.domain', and `mailbox.domain' are not in +# the LDAP schema. + +use 5.010_000; +use strict; +use warnings; +use utf8; + +use FindBin qw($Bin); +use lib "$Bin/lib"; + +use Env qw /HOME/; +use File::Spec::Functions; + +use Fripost::Schema; +use DBI; +use Getopt::Long; +use YAML::Syck; + +my $pretend = 0; +GetOptions( 'pretend' => \$pretend ); + + +# Log the inserts and errors. +open LOG, '>', "fripost-migration-$$.log" or die $!; + +# Connect to the LDAP server +my $ldapconf = LoadFile ( catfile ($HOME, '.fripost.yml') ); +my $ldap = Fripost::Schema->new( $ldapconf ); + + +# Connection to the MySQL sever +my $dbhconf = LoadFile ( 'dbh.yml' ); +my $dbh = DBI->connect( $dbhconf->{dbi_dsn}, $dbhconf->{admuser}, $dbhconf->{admpass} ); +$dbh->do( "SET NAMES UTF8" ) or die "Error: Can't set names to UTF-8.\n"; + + +# Migrate mailboxes +{ + my $rs = $dbh->selectall_hashref( "SELECT * FROM mailbox", 'username' ) + or die "Can't select: $!\n"; + foreach my $username (keys $rs) { + my $user = $rs->{$username}; + if ($ldap->user->search({ username => $username })->count) { + &mesg ("WARN: Skipping user `$username': Already exists.\n"); + next; + } + &mesg ("WARN: Ignoring user name `$user->{name}'") + if defined $user->{name} and $user->{name} ne ''; + &mesg ("Inserting user `$username'... "); + $ldap->user->add({ username => $username + , userPassword => $user->{password} + , maildir => $user->{maildir} + , isActive => &isActive($user) + }) + unless $pretend; + &mesg ("Done.\n"); + } +} +&mesg ("\n================================\n\n"); + + +# Migrate domains +{ + my $rs = $dbh->selectall_hashref( "SELECT * FROM domains", 'domain' ) + or die "Can't select: $!\n"; + foreach my $domainname (keys $rs) { + my $domain = $rs->{$domainname}; + if ($ldap->domain->search({ domain => $domainname })->count) { + &mesg ("WARN: Skipping domain `$domainname': Already exists.\n"); + next; + } + my $mesg = "Inserting domain `$domainname'"; + if (defined $domain->{description} and $domain->{description} ne '') { + if ($ldap->user->search({ username => $domain->{description} })->count) { + $mesg .= " (for owner `$domain->{description}')" + } + else { + &mesg ("WARN: Skipping ownership of `$domainname': Unknown owner `$domain->{description}'.\n"); + delete $domain->{description}; + } + } + else { + delete $domain->{description} if exists $domain->{description}; + } + &mesg ($mesg ."... "); + $ldap->domain->add({ domain => $domainname + , owner => $domain->{description} + , isActive => &isActive($domain) + }) + unless $pretend; + &mesg ("Done.\n"); + } +} +&mesg ("\n================================\n\n"); + + +# Migrate aliases +{ + my $rs = $dbh->selectall_hashref( "SELECT * FROM aliases", 'address' ) + or die "Can't select: $!\n"; + foreach my $address (keys $rs) { + my $alias = $rs->{$address}; + if ($ldap->alias->search({ address => $address })->count) { + &mesg ("WARN: Skipping alias `$address': Already exists.\n"); + next; + } + unless (defined $alias->{goto} and $alias->{goto} ne '') { + &mesg ("WARN: Skipping alias `$address': Empty goto.\n"); + next; + } + + &mesg ("Inserting alias `$address' -> `$alias->{goto}'... "); + $ldap->alias->add({ address => $address + , goto => $alias->{goto} + , isActive => &isActive($alias) + }) + unless $pretend; + &mesg ("Done.\n"); + } +} +&mesg ("\n================================\n\n"); + + +# Disconnect +$dbh->disconnect(); +$ldap->unbind(); +close LOG; + +sub mesg { + print STDERR @_; + print LOG @_; +} + +sub isActive { + if ($_[0]->{isActive}) { + return 'TRUE'; + } + return 'FALSE'; +} -- cgit v1.2.3