migrate_mail_data.pl [plain text]
$CAT = "/bin/cat";
$CP = "/bin/cp";
$MV = "/bin/mv";
$RM = "/bin/rm";
$DSCL = "/usr/bin/dscl";
$DU = "/usr/bin/du";
$ECHO = "/bin/echo";
$GREP = "/usr/bin/grep";
$CHOWN = "/usr/sbin/chown";
$LAUNCHCTL = "/bin/launchctl";
$POSTCONF = "/usr/sbin/postconf";
$MKDIR = "/bin/mkdir";
$PLISTBUDDY = "/usr/libexec/PlistBuddy";
$TAR = "/usr/bin/tar";
$DOVECOT_CONF="/etc/dovecot/dovecot.conf";
$MIGRATION_LOG= "/Library/Logs/MailDataMigration.log";
$g_move_mail = 0;
$g_cyrus_bin = "";
$g_database_root = "/var/imap";
$g_source_root = "/var/spool/imap";
$g_target_root = "/Library/Server/Mail/Data/mail";
$g_single_user = "";
$g_imapd_conf ="";
$DEBUG = 0;
$FUNC_LOG = 0;
use Foundation;
use File::Copy;
use File::Basename;
if ($ENV{DEBUG} eq 1) {
$DEBUG = '1'; }
if ( $ENV{FUNC_LOG} eq 1 ) {
$FUNC_LOG = '1'; }
parse_options();
if ( ${DEBUG} ) {
print_script_args( @ARGV ); }
open ( LOG_FILE, ">> ${MIGRATION_LOG}" ) or die("$MIGRATION_LOG: $!\n");
$g_imapd_conf="/tmp/" . make_random_string() . "-imapd.conf";
do_migration( @ARGV );
exit();
sub print_message ()
{
my ( $line_0 ) = $_[0];
my ( $line_1 ) = $_[1];
my ( $line_2 ) = $_[2];
my ( $line_3 ) = $_[3];
if ( ${FUNC_LOG} ) {
printf( "::print_message : S\n" ); }
print LOG_FILE "*************************************************************\n";
if ( ! ("${line_0}" eq "") ) {
print LOG_FILE "** ${line_0}\n"; }
if ( ! ("${line_1}" eq "") ) {
print LOG_FILE "** ${line_1}\n"; }
if ( ! ("${line_2}" eq "") ) {
print LOG_FILE "** ${line_2}\n"; }
if ( ! ("${line_3}" eq "") ) {
print LOG_FILE "** ${line_3}\n"; }
print LOG_FILE "** Please refer to the Migration and Upgrade Guide for\n";
print LOG_FILE "** instructions on how to manually migrate configuration data.\n";
print LOG_FILE "*************************************************************\n";
if ( ${FUNC_LOG} ) {
printf( "::print_message : E\n" ); }
}
sub obj_value
{
my ( $object ) = @_;
return( $object->description()->UTF8String() );
}
sub get_server_version ($)
{
my ($VERS) = @_;
if ( ${FUNC_LOG} ) {
print( "::get_server_version : S\n"); }
if ( ${DEBUG} ) {
printf( "- sourceVersion: %s\n", "${VERS}"); }
@SRV_VER_PARTS = split(/\./, $VERS);
if ( ${DEBUG} )
{
print( "- Major : " . ${SRV_VER_PARTS}[0] . "\n" );
print( "- Minor : " . ${SRV_VER_PARTS}[1] . "\n" );
print( "- Update: " . ${SRV_VER_PARTS}[2] . "\n" );
}
$SRV_MAJOR = ${SRV_VER_PARTS}[0];
$SRV_MINOR = ${SRV_VER_PARTS}[1];
$SRV_UPDATE = ${SRV_VER_PARTS}[2];
if (${FUNC_LOG}) {
print( "::get_server_version : E\n"); }
}
sub do_cyrus_dovecot_migration ()
{
if ( ${FUNC_LOG} ) {
printf( "::do_cyrus_dovecot_migration : S\n" ); }
$cvt_flag = "-c";
if ( ${g_move_mail} == 1 )
{
$cvt_flag = "-m";
}
chdir( "${g_source_root}/user" ) or die "can't chdir ${g_source_root}/user: $!";
if ( $g_single_user eq "" )
{
@mail_accts = <*>;
}
else
{
@mail_accts = ( $g_single_user );
}
foreach $user_id (@mail_accts)
{
print LOG_FILE "--------------------\n";
print LOG_FILE "Migrating account: ${user_id} to: ${g_target_root}\n";
$user_tag = substr( $user_id, 0, 1 );
if ( ${DEBUG} ) {
printf( "- verifying user seen db: \"${g_database_root}/user/${user_tag}/${user_id}.seen\"\n" ); }
if ( path_exists( "${g_database_root}/user/${user_tag}/${user_id}.seen" ) )
{
print LOG_FILE "-- Seen file conversion: ";
qx( "${g_cyrus_bin}/cvt_cyrusdb" -C ${g_imapd_conf} "${g_database_root}/user/${user_tag}/${user_id}.seen" skiplist "${g_database_root}/user/${user_tag}/${user_id}.seen.flat" flat >> "${MIGRATION_LOG}" 2>>"${MIGRATION_LOG}" );
if ( ${DEBUG} )
{
printf( "- /usr/bin/cvt_mail_data -g ${cvt_flag} -d ${g_database_root} -s ${g_source_root} -t ${g_target_root} -a ${user_id}\n" );
qx( /usr/bin/cvt_mail_data -g ${cvt_flag} -d "${g_database_root}" -s "${g_source_root}" -t "${g_target_root}" -a ${user_id} >> "${MIGRATION_LOG}" 2>>"${MIGRATION_LOG}" );
} else {
qx( /usr/bin/cvt_mail_data ${cvt_flag} -d "${g_database_root}" -s "${g_source_root}" -t "${g_target_root}" -a ${user_id} >> "${MIGRATION_LOG}" 2>>"${MIGRATION_LOG}" );
}
qx( ${RM} "${g_database_root}/user/${user_tag}/${user_id}.seen.flat" >> "${MIGRATION_LOG}" );
}
else
{
if ( ${DEBUG} )
{
printf( "- /usr/bin/cvt_mail_data -g ${cvt_flag} -d ${g_database_root} -s ${g_source_root} -t ${g_target_root} -a ${user_id}\n" );
qx( /usr/bin/cvt_mail_data -g ${cvt_flag} -d "${g_database_root}" -s "${g_source_root}" -t "${g_target_root}" -a ${user_id} >> "${MIGRATION_LOG}" 2>>"${MIGRATION_LOG}" );
} else {
qx( /usr/bin/cvt_mail_data ${cvt_flag} -d "${g_database_root}" -s "${g_source_root}" -t "${g_target_root}" -a ${user_id} >> "${MIGRATION_LOG}" 2>>"${MIGRATION_LOG}" );
}
}
$user_guid = qx( /usr/bin/cvt_mail_data -i ${user_id} );
chomp( ${user_guid} );
if ( substr(${user_guid}, 0, 13) eq "No GUID found" ) {
qx( chown -R _dovecot:mail "${g_target_root}/${user_id}" >>"${MIGRATION_LOG}" 2>>"${MIGRATION_LOG}" ); }
else {
qx( chown -R _dovecot:mail "${g_target_root}/${user_guid}" >>"${MIGRATION_LOG}" 2>>"${MIGRATION_LOG}" ); }
}
if ( ${FUNC_LOG} ) {
printf( "::do_cyrus_dovecot_migration : S\n" ); }
}
sub parse_options
{
local (@optval) = @_;
local ($opt, @opts, %valFollows, @newargs);
while (@optval)
{
$opt = shift(@optval);
push(@opts,$opt);
$valFollows{$opt} = shift(@optval);
}
@optArgs = ();
%opt = ();
arg: while (defined($arg = shift(@ARGV)))
{
foreach $opt (@opts)
{
if ($arg eq $opt)
{
push(@optArgs, $arg);
if ($valFollows{$opt})
{
$opt{$opt} = shift(@ARGV);
push(@optArgs, $opt{$opt});
} else {
$opt{$opt} = 1;
}
next arg;
}
}
push(@newargs,$arg);
}
@ARGV = @newargs;
}
sub print_script_args ()
{
%script_args = @_;
while(($theKey, $theVal) = each (%script_args))
{
print "key/value: $theKey: $theVal\n";
}
}
sub path_exists ($)
{
if (${FUNC_LOG}) {
print( "::path_exists : S\n"); }
my $exists = 0;
my ($in_path) = @_;
if (${DEBUG}) {
printf( "- path: %s\n", "${in_path}"); }
if (-e "${in_path}")
{
$exists = 1;
if (${DEBUG}) {
printf( "-- Exists\n"); }
}
else
{
if (${DEBUG}) {
printf( "-- Does not exist\n"); }
}
if (${FUNC_LOG}) {
print( "::path_exists : E\n"); }
return( $exists );
}
sub do_cleanup ($)
{
if (${FUNC_LOG}) {
print( "::do_cleanup : S\n"); }
my ($in_path) = @_;
if ( path_exists("${in_path}") )
{
print LOG_FILE "Removing source: ${in_path}\n";
qx( ${RM} -rf "${in_path}" >> ${MIGRATION_LOG} );
}
if ( ${FUNC_LOG} ) {
printf( "::do_cleanup : S\n" ); }
}
sub make_random_string
{
my $out_string;
my $my_rand;
my $my_length = 10;
my @my_chars = split(" ",
"a b c d e f g h i j k l m n o
p q r s t u v w x y z 0 1 2 3
4 5 6 7 8 9");
srand;
for ( my $i = 0; $i <= $my_length ; $i++)
{
$my_rand = int( rand(31) );
$out_string .= $my_chars[$my_rand];
}
return( $out_string );
}
sub Usage()
{
print("\n");
print("--moveMail <0 | 1> A value of \"1\" will cause migrated mail to be \"moved\" and not copied where the original will be destroyed (default: 0)" . "\n");
print("--cyrusBin <path> Path to directory containing original cvt_cyrusdb binary" . "\n");
print("--database <path> Path to original cyrus database (default: /var/imap)" . "\n");
print("--sourceSpool <path> Path to original cyrus data store (default: /var/spool/imap)" . "\n");
print("--targetSpool <path> Path to target dovecot mail data store (default: /Library/Server/Mail/Data/mail)" . "\n");
print("--accountID <account> Optional account ID if migrating a single user account (default is all accounts)" . "\n");
print("\n");
print("Example: migrate_mail_data.pl --cyrusBin \"/Volumes/Tiger/usr/bin/cyrus/bin\" --database \"/Volumes/Tiger/var/imap\" --sourceSpool \"/Volumes/Tiger/var/spool/imap\" --targetSpool \"/Library/Server/Mail/Data/mail\"" . "\n");
print(" " . "\n");
if ( LOG_FILE )
{
close( LOG_FILE );
}
exit( 1 );
}
sub do_migration()
{
%script_args = @_;
$g_move_mail = $script_args{"--moveMail"};
$g_cyrus_bin = $script_args{"--cyrusBin"};
$g_database_root = $script_args{"--database"};
$g_source_root = $script_args{"--sourceSpool"};
$g_target_root = $script_args{"--targetSpool"};
$g_single_user = $script_args{"--accountID"};
my $my_time = localtime();
print LOG_FILE "-------------------------------------------------------------\n";
print LOG_FILE "Begin Mail Migration: $my_time" . "\n";
print LOG_FILE "-------------------------------------------------------------\n";
if ( !($g_move_mail eq "0") ) {
print LOG_FILE "Move Mail : No\n"; }
else {
print LOG_FILE "Move Mail : Yes\n"; }
print LOG_FILE "Database Path : ${g_database_root}\n";
print LOG_FILE "Source Path : ${g_source_root}\n";
print LOG_FILE "Destination Path : ${g_target_root}\n";
print LOG_FILE "Cyrus Binaries Path : ${g_cyrus_bin}\n";
if ( !($g_single_user eq "") ) {
print LOG_FILE "Account ID : ${g_single_user}\n"; }
else {
print LOG_FILE "Account ID : All User Accounts\n"; }
if ( ! path_exists( "${g_cyrus_bin}/cvt_cyrusdb" ) )
{
print LOG_FILE "Error: cvt_cyrusdb does not exist in: ${g_cyrus_bin}.\n";
print LOG_FILE "Exiting.\n";
print( "\nError: cvt_cyrusdb does not exist in: ${g_cyrus_bin}.\n" );
Usage();
}
if ( ! path_exists( "${g_database_root}" ) )
{
print LOG_FILE "Error: Cyrus database path: ${g_database_root} does not exist.\n";
print LOG_FILE "Exiting.\n";
print( "\nError: Cyrus database path: ${g_database_root} does not exist.\n" );
Usage();
}
if ( ! path_exists( "${g_source_root}/user" ) )
{
print LOG_FILE "Error: Cyrus data store path: ${g_source_root}/user does not exist.\n";
print LOG_FILE "Exiting.\n";
print( "\nError: Cyrus data store path: ${g_source_root}/user does not exist.\n" );
Usage();
}
if ( ! path_exists("${g_target_root}") )
{
print LOG_FILE "Error: Dovecot destination path: ${g_target_root} does not exist.\n";
print LOG_FILE "Exiting.\n";
print( "\nError: Dovecot destination path: ${g_target_root} does not exist.\n" );
Usage();
}
if ( path_exists( "${g_imapd_conf}" ) )
{
qx( ${RM} -rf "${g_imapd_conf}" >> ${MIGRATION_LOG} );
}
open ( IMAPD_CONF, ">> ${g_imapd_conf}" ) or die("g_imapd_conf: $!\n");
print IMAPD_CONF "admins: _cyrus\n";
print IMAPD_CONF "postmaster: postmaster\n";
print IMAPD_CONF "configdirectory: ${g_database_root}\n";
print IMAPD_CONF "defaultpartition: default\n";
print IMAPD_CONF "partition-default: ${g_source_root}\n";
close( IMAPD_CONF );
do_cyrus_dovecot_migration();
if ( path_exists( "${g_imapd_conf}" ) )
{
qx( ${RM} -rf "${g_imapd_conf}" >> ${MIGRATION_LOG} );
}
my $my_time = localtime();
print LOG_FILE "-------------------------------------------------------------\n";
print LOG_FILE "Mail Migration Complete: $my_time" . "\n";
print LOG_FILE "-------------------------------------------------------------\n";
}