> On Thu, Nov 15, 2001 at 09:58:09AM -0600, John Wade wrote:
>
> > If anyone is interested in the full set of steps, I could post it to the
> > list.

Hi All,

Since a number of people requested it, I am sending my complete list of steps (with 
added comments) for moving from one Cyrus server to another. Sorry about the size of 
this posting

I used this procedure to migrate two servers from older Pentium Pro hardware running 
Cyrus 1.5.19 to  newer P3 Xeon servers running Cyrus 2.0.16.   One server had ~20,000 
accounts and 10GB of mail, the other had ~1300 accounts and 35GB of mail.   These 
instructions assume that you have both servers set up and fully tested before moving 
the users' data.   Our new environment uses:

RedHat 7.0 (2.2.19 kernel)
Cyrus 2.0.16 for IMAP
Cyrus SASL 1.5.24 with LDAP authentication (via hacked pwcheck)
qmail 1.0.3 as the MTA
ezmlm-idx for mailing lists
WebSieve and Easysieve for sieve

The mail on the old server was all stored in a single 35GB ext2fs file system mounted 
as /var.  Within this file system, we had hashed the mail spool via cyrus partitions 
using the first letter of the user's login id  to choose the partition (i.e. 
/var/spool/imap/a/  for abelincoln )  This is similar to the new hashmailspool option. 
 On the new server, we had a 190GB array and I was afraid to make this a single file 
system.    In order to end up with a managable number of file systems (of manageable 
size) , we decided to store mail in  5 - 33GB file systems ( mounted 
as/var/spool/imap/0, /var/spool/imap/1, /var/spool/imap/2, /var/spool/imap/3 and 
/var/spool/imap/4)  This corresponded to 5 matching Cyrus partitions (0,1,2,3,4)

IMPORTANT DISCLAIMER:  While I sometimes feel like I know what I am doing, there is no 
guarranty that I did this in the most efficient way or even that I did it correctly, 
all I know is that it seems to have worked for me

Warning, Since I was using external authentication (via LDAP), there is nothing here 
about moving the authentication database.

The following instructions were designed so that I could cut and paste it to reduce 
mistakes
and speed the conversion.  All comments are proceeded by a #    Sometimes the 
instructions
call for editing files with vi, in this case, the next set of lines separated by 
#--------
are what should be the new contents of the edited file.
----------------------------------------------------------------------------------
#Cleanup newserver

# On new server shutdown services
# The cyrus and pwcheck scripts are ones I put together to control cyrus and pwcheck.
# basically this step was just to kill all existing services on the new box
# your steps will differ.

/etc/rc.d/init.d/cyrus stop
/etc/rc.d/init.d/pwcheck stop
/etc/rc.d/init.d/qmailctl stop
/etc/rc.d/init.d/httpd stop

# Cleanup any existing mail directories, quotas, seen and subscription files, etc that 
might be
#left over from testing

rm -f /var/imap/proc/*
rm -f /var/imap/mailboxes*
rm -f /var/imap/db/*.*
rm -f /var/imap/deliverdb/*.db
rm -f /var/imap/deliverdb/db/*

# delete subscriptions and seen files
cd /var/imap/user
for dir in `ls -d ?`; do rm -f /var/imap/user/$dir/* ; done

# delete quotas
cd /var/imap/quota
for dir in `ls -d ?`; do rm -f /var/imap/quota/$dir/* ; done

# delete sieve scripts (note this is not the default sieve directory)
cd /var/imap/sieve
for dir in `ls -d ?`; do rm -Rf /var/imap/sieve/$dir/* ; done

#Delete the mail spool  (note we use multiple partitions in /var/spool/imap)
cd /var/spool/imap
for dir in `ls -d ?`; do rm -Rf /var/spool/imap/$dir/* ; done

# cleanp ezmlm mailing lists
# (This step omited from this posting since this is ezmlm specific)

# done with cleanup
# At this point the new server should be completely cleaned up and
# ready for the copy

-------------------------------------------------------------

# Restore Overview
# We need to restore all items in
# /var/imap/user/
# /var/imap/quota/
# /var/imap/mailboxes (file)
# /var/spool/imap/

#NFS Setup.  I mounted the new server's file systems on the old server
# because we had a problem with the nfs install on the old server,  ideally,
# I would have mounted the old on the new because then I could have done
# it read only and not risked any mistakes.

#on newserver, setup an export for each mount point that will need to have files 
copied to it.
vi /etc/exports
#-------------------------------
/var oldserver.oakton.edu(rw,no_root_squash)
/var/imap oldserver.oakton.edu(rw,no_root_squash)
/var/spool/imap/0 oldserver.oakton.edu(rw,no_root_squash)
/var/spool/imap/1 oldserver.oakton.edu(rw,no_root_squash)
/var/spool/imap/2 oldserver.oakton.edu(rw,no_root_squash)
/var/spool/imap/3 oldserver.oakton.edu(rw,no_root_squash)
/var/spool/imap/4 oldserver.oakton.edu(rw,no_root_squash)
#-------------------------------

/etc/rc.d/init.d/nfs stop
/etc/rc.d/init.d/nfslock stop
/etc/rc.d/init.d/portmap stop

/etc/rc.d/init.d/portmap start
/etc/rc.d/init.d/nfslock start
/etc/rc.d/init.d/nfs start

# to reload (if you make future changes to /etc/exports )
#exportfs -a

#on old server mount nfs shares from new server
mkdir -p /mnt/newserver/var
mount -t nfs newserver.oakton.edu:/var /mnt/newserver/var
mount -t nfs newserver.oakton.edu:/var/imap /mnt/newserver/var/imap
mount -t nfs newserver.oakton.edu:/var/spool/imap/0 /mnt/newserver/var/spool/imap/0
mount -t nfs newserver.oakton.edu:/var/spool/imap/1 /mnt/newserver/var/spool/imap/1
mount -t nfs newserver.oakton.edu:/var/spool/imap/2 /mnt/newserver/var/spool/imap/2
mount -t nfs newserver.oakton.edu:/var/spool/imap/3 /mnt/newserver/var/spool/imap/3
mount -t nfs newserver.oakton.edu:/var/spool/imap/4 /mnt/newserver/var/spool/imap/4

# On Old Server
#increase quotas to allow mail to be delivered (We often have users over quota,
# and their mail is hanging out in the queue waiting for either the user to clean up
# their mailbox or for 10 days to elapse so it can bounce
# by increasing the quota, I allowed all this mail to be delivered and did not have
# to move the MTA's queue (We were going to increase the quota on the new
# server anyway).  Note this script could have been writen to use the IMAP::Admin
# module instead of Net::Telnet, but we already had the basic framework and
# IMAP::Admin was not a part of cyrus 1.5

# get a listof all existing quotas
ls /var/imap/quota > /root/currentusers.txt

#create script
vi /root/adjquota.pl
---------------------------
#!/usr/bin/perl -w

use Net::Telnet;
use File::Find;
$hostname = "oldserver.oakton.edu";
$username = "<cyrus admin>";
$passwd = "password";
$quota = 60000;

## Open up a new session to imap server
$imap = new Net::Telnet (Telnetmode => 0);
$imap->open(Host => $hostname, Port => 143);

## Read connection message.
$line = $imap->getline;
die $line unless $line =~ /^\* OK/;
print "connected to imap server ok\n";

## Send admin user name.
$imap->print(". login $username $passwd");
$line = $imap->getline;
die $line unless $line =~ /^\. OK/;
print "logged in to imap server ok\n";

## Read each entry in file
open (P, "currentusers.txt") or die "Can't find the currentusers.txt file\n";
while (<P>) {
        chomp;
        $imap->print(qq{. setquota $_ (storage $quota)});
        $line = $imap->getline;
        die "$_ " . $line unless $line =~ /^\. OK/;
        print "quota root set to $quota for $_\n";
}
close(P);
$imap->print(". logout");
exit;
-------------------------------
chmod 700 /root/adjquota.pl
/root/adjquota.pl

# Signal qmail to re-attempt delivery  (Your MTA will work differently)

ps -ef | grep qmail-send
#Get process id
kill -SIGALRM <PID>
#check queue
qmHandle -s
qmHandle -L | less
#Adjust quotas if necessary to allow delivery
cyradm -u <cyrus admin> localhost
lqm user.<username>
sql user.<username> 65000
quit
#repeat SIGALRM and queue check until no mail is queued locally


#shutdown services on old server
Stop all mail services (shutdown qmail)
Comment out imapd line in /etc/inetd.conf - this disables people's ability to use IMAP 
to access their
email. Then kill -HUP <inetd pid>


#Copy mailboxes file (on old server)
cp /var/imap/mailboxes /mnt/newserver/var/imap/mailboxes

#on old server
# (in Cyrus 1.5 quotas were all in one directory, in 2.0.16, the are hashed by the 
first letter
# of the username, this script will put all of them in the correct directory (unless 
they begin with a
# number or other character :-)

vi /root/CopyImapQuotas.sh
-------------------------------
# To copy quotas
for letter in 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
  do
     echo $letter
     cp /var/imap/quota/user.$letter* /mnt/newserver/var/imap/quota/$letter/
  done
---------------------------------
chmod 700 CopyImapQuotas.sh
/root/CopyImapQuotas.sh

# Same thing for subscriptions
vi /root/CopyImapSub.sh
-------------------------------
# To copy subscriptions
for letter in 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
  do
     echo $letter
     cp /var/imap/user/$letter*.sub /mnt/newserver/var/imap/user/$letter/
  done
---------------------------------
chmod 700 CopyImapSub.sh
/root/CopyImapSub.sh


# Create CopyImapSpool.sh script on old server and execute

# Note that this script is more complicated than others might need
# because we were trying to redistribute users into a new partitioning
# structure. On the old server a user's mail would have been in a partition
# based on the first letter of their name.   For example, my directory would
#have been /var/spool/imap/j/user/jwade
#On the new server, we wanted to evenly distribute users into 5 partitions
#so that we could keep the file system size managable and evenly distribute
#disk space usage between the mount points.
# The idhash program that I use in the following script is a little program I wrote
#C (I also have a perl version) that calculates the partition number by adding
# up the ascii values of all the characters in the user's name, dividing by five
# and using the remainder. (modulus operator)   This fairly simple hash function
# gives a pretty good distribution of users.
#Our script to add users uses this same "idhash" program to assing new users
#to partitions in the same way.

vi /root/CopyImapSpool.sh
------------------------------------------------------
# To copy users
# make sure directories exist
for num in 0 1 2 3 4
  do
    mkdir /mnt/newserver/var/spool/imap/$num/user/
  done
# copy mail
for letter in 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
  do
     echo $letter
     cd /var/spool/imap/$letter/user
     for uid in *
        do
           echo $letter $uid `/root/idhash -n $uid`
           cp -R /var/spool/imap/$letter/user/$uid 
/mnt/newserver/var/spool/imap/`/root/idhash -n $uid`/user/
        done
  done
-----------------------------------
chmod 700 CopyImapSpool.sh
/root/CopyImapSpool.sh


# for 35GB of mail (1,668,019 files), this process took 6 hours 32 minutes.  This was 
far faster than when
# we tested it doing a backup and restore from tape


#on old server copy ezmlm files
(Step omitted here for brevity


#----------------------------------------------------------------------

#Steps to complete After Restore
# on newserver

#Next sections are to fix up file ownership, hopefully the umask took
# care of permissions

#fix subscrptions
chown -R cyrus:mail /var/imap/user/*

#fix quotas
chown -R cyrus:mail /var/imap/quota/*

#fix mail spool
chown -R cyrus:mail /var/spool/imap/*

#fix ezmlm
# (step omitted here for brevity)

# fix Mailboxes file
# I needed to do three things with the mailboxes file, change everyone's partitions
#to match our new partitioning structure (switch from a-z to 0-4), change the cyrus 
admin user's permissions
#from "d" to"c" so that we could delete mailboxes (This was a change between
# 1.5.x and 2.0.x) and convert the flat text mailboxes file into the Berkeley DB that 
2.0.x
# needs

cp /var/imap/mailboxes /var/imap/mailboxes.old

# the following perl script is what fixes the partition (using that same idhash 
program)
# and fixes the permissions for the cyrus admin user,   I can cheat here, since I
# know the cyrus admin user's acl  is the last entry on each line in our mailboxes 
file.

vi /root/fixmailboxes.pl
------------------------------------
while (<>) {
$line = $_;
#  find login id
/^user\.(\w+)/;
# calculate new partition
$idhash = `idhash -n $1`;
# fix partition replace a-z with calculated 0-4
$line =~ s/(^user\.\w+[^\t]*\t)([a-z])/$1$idhash/ ;
# fix permissions for cyrus admin user
$line =~ s/d\t$/c\t/;
print $line;
}
-----------------------------------
perl -w /root/fixmailboxes.pl < /var/imap/mailboxes.old > /var/imap/mailboxes


# The following steps are used to convert the old malbox text file (after cleanup)
# to the new berkeley db
# for those who need more info about ctl_mboxlist, see the man page
#basically, the two options that apply to conversions are -u to convert
#from text file to db and -d to dump from db to text file

chown cyrus:mail /var/imap/mailboxes
su cyrus
cd /var/imap
/usr/cyrus/bin/ctl_mboxlist -u < mailboxes
/usr/cyrus/bin/ctl_mboxlist -c
exit


# Disconnect on old server

cat /etc/mtab
umount -t nfs newserver.oakton.edu:/var/imap
umount -t nfs newserver.oakton.edu:/var/spool/imap/0
umount -t nfs 1newserver.oakton.edu:/var/spool/imap/1
umount -t nfs newserver.oakton.edu:/var/spool/imap/2
umount -t nfs newserver.oakton.edu:/var/spool/imap/3
umount -t nfs newserver.oakton.edu:/var/spool/imap/4
umount -t nfs newserver.oakton.edu:/var

#shutdown rpc and nfs on new server (for security)
/etc/rc.d/init.d/nfs stop
/etc/rc.d/init.d/nfslock stop
/etc/rc.d/init.d/portmap stop
chkconfig --level 123456 nfs off
chkconfig --level 123456 nfslock off
chkconfig --level 123456 portmap off
chkconfig --list | less

#verify copy  (do on both boxes)

#Verify count of subscriptions

#on old server
ls /var/imap/user/* | wc -l
#on new server
ls /var/imap/user/?/* | wc -l

#Verify count of quotas

#on old server
ls /var/imap/quota/* | wc -l
#on new server
ls /var/imap/quota/?/* | wc -l

#Verify count of spool dirs

#on old server
 ls -ld /var/spool/imap/?/user/* | wc -l

#on new server
ls -ld /var/spool/imap/?/user/* | wc -l

#check count of files
#on old server
 ls -R /var/spool/imap/?/user/* | wc -l
#on new server
 ls -R /var/spool/imap/?/user/* | wc -l

# restart services

/etc/rc.d/init.d/pwcheck start
/etc/rc.d/init.d/cyrus start
qmailctl start
/etc/rc.d/init.d/httpd start

# test everything !!!!!
#if it is really bad, you can just go back to the old server at this point


# Change IP Address and hostname.  Verify files with :

#convert name and ip
#Since we wanted to use the same dns name and ip address for the new server,
#at this point, we powered off the old server
#to make sure I found all references to the host name and ip address,  I had previosly 
searched the
#file system fir them


#on new server before copy
for dir in bin boot command dev etc home  lib mnt nsr opt package root sbin service tmp
usr var
do
echo checking $dir
find /$dir -type f -exec grep -l "192\.168\.5\.105" {} \;
done

for dir in bin boot command dev etc home  lib  mnt nsr opt package root sbin service 
tmp
usr var
do
echo checking $dir
find /$dir -type f -exec grep -l "newserver" {} \;
done

#this found the following files
# edit each and replace new ip (192.168.5.105) with old ip (192.168.5.5)

/etc/sysconfig/network-scripts/ifcfg-eth0
/etc/hosts
#these two are from qmail
/etc/smtp.txt
/etc/smtp.cdb

# edit following files and replace "newserver" with "oldserver" in

/etc/sysconfig/network
/etc/hosts
#qmail specific
/var/qmail/control/me
/var/qmail/control/locals
/var/qmail/control/rcpthosts
# paths omitted below for web stuff
websieve.conf
easysieve.pl
horde/imp/config/defaults.php3


#reboot
shutdown -r now

#At this point queued mail on our mail relay started to be delivered, and everything 
was fine.
#I have omtted a couple of steps here that were specific to imp (moving prefs and 
addressbook) and ezmlm
# ( moving mailing lists)

I still wonder if I should have reconstructed all the mailboxes (with 
/usr/cyrus/bin/reconstruct) and fixed the quotas (/usr/cyrus/bin/quota -f ) before 
proceeding, but I did not

Hope this was helpful,

John






Reply via email to