3
# vzmigrate is used for VE migration to another node
4
# Copyright (C) 2000-2007 SWsoft. All rights reserved.
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License
8
# as published by the Free Software Foundation; either version 2
9
# of the License, or (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
# vzmigrate [-r yes|no] [--ssh=<options>] [--keep-dst] [--online] [-v]
23
# destination_address VEID
25
# -r, --remove-area yes|no
26
# Whether to remove VE on source HN for successfully migrated VE.
28
# Additional options that will be passed to ssh while establishing
29
# connection to destination HN. Please be careful with options
30
# passed, DO NOT pass destination hostname.
32
# Do not clean synced destination VE private area in case of some
33
# error. It makes sense to use this option on big VE migration to
34
# avoid syncing VE private area again in case some error
35
# (on VE stop for example) occurs during first migration attempt.
37
# Perform online (zero-downtime) migration: during the migration the
38
# VE hangs for a while and after the migration it continues working
39
# as though nothing has happened.
41
# Verbose mode. Causes vzmigrate to print debugging messages about
42
# its progress (including some time statistics).
45
# Online migration of VE #101 to foo.com:
46
# vzmigrate --online foo.com 101
47
# Migration of VE #102 to foo.com with downtime:
48
# vzmigrate foo.com 102
50
# This program uses ssh as a transport layer. You need to put ssh
51
# public key to destination node and be able to connect without
52
# entering a password.
55
ACT_SCRIPTS_SFX="start stop mount umount"
57
SSH="ssh $SSH_OPTIONS"
58
SCP="scp $SSH_OPTIONS"
65
confdir="@PKGCONFDIR@/conf"
66
vzconf="@PKGCONFDIR@/vz.conf"
72
MIG_ERR_VPS_IS_STOPPED=2
73
MIG_ERR_CANT_CONNECT=4
81
MIG_ERR_CHECKPOINT=$MIG_ERR_STOP_SOURCE
82
MIG_ERR_MOUNT_VPS=$MIG_ERR_START_VPS
83
MIG_ERR_RESTORE_VPS=$MIG_ERR_START_VPS
84
MIG_ERR_OVZ_NOT_RUNNING=14
85
MIG_ERR_APPLY_CONFIG=15
89
This program is used for VE migration to another node
91
vzmigrate [-r yes|no] [--ssh=<options>] [--keep-dst] [--online] [-v]
92
destination_address <VEID>
94
-r, --remove-area yes|no
95
Whether to remove VE on source HN for successfully migrated VE.
97
Additional options that will be passed to ssh while establishing
98
connection to destination HN. Please be careful with options
99
passed, DO NOT pass destination hostname.
101
Do not clean synced destination VE private area in case of some
102
error. It makes sense to use this option on big VE migration to
103
avoid syncing VE private area again in case some error
104
(on VE stop for example) occurs during first migration attempt.
106
Perform online (zero-downtime) migration: during the migration the
107
VE hangs for a while and after the migration it continues working
108
as though nothing has happened.
110
Verbose mode. Causes vzmigrate to print debugging messages about
111
its progress (including some time statistics).
117
# There are 3 types of messages:
118
# 0 - error messages (print to stderr)
119
# 1 - normal messages (print to stdout)
120
# 2 - debug messages (print to stdout if in verbose mode)
122
if [ $1 -eq 0 ]; then
124
echo -e "Error: " $@ >&2
125
elif [ $1 -eq 1 ]; then
128
elif [ $verbose -eq 1 ]; then
134
# Executes command and returns result of execution
135
# There are 2 types of execution:
136
# 1 - normal execution (all output will be printed)
137
# 2 - debug execution (output will be printed if verbose mode is set,
138
# in other case stdout and stderr redirected to /dev/null)
140
if [ $1 -eq 1 -o $verbose -eq 1 ]; then
151
$SSH "root@$host" "rm -f $vpsconf"
154
undo_act_scripts () {
155
if [ -n "$act_scripts" ] ; then
156
$SSH "root@$host" "rm -f $act_scripts"
162
if [ $keep_dst -eq 0 ]; then
163
$SSH "root@$host" "rm -rf $VE_PRIVATE"
169
$SSH "root@$host" "rm -rf $VE_ROOT"
174
$SSH "root@$host" "vzquota drop $VEID"
179
$SSH "root@$host" "vzquota off $VEID"
184
# Root will be destroed in undo_root
189
logexec 2 vzctl chkpnt $VEID --resume
194
if [ $debug -eq 0 ]; then
201
$SSH "root@$host" "rm -f $VE_DUMPFILE"
206
if [ "$state" = "running" ]; then
208
elif [ "$mounted" = "mounted" ]; then
214
undo_source_stage() {
215
if [ $online -eq 1 ]; then
223
rm -f "$VE_QUOTADUMP"
228
$SSH "root@$host" "rm -f $VE_QUOTADUMP"
233
logexec 2 $SSH root@$host vzctl restore $VEID --kill
244
awk -v t2=$2 -v t1=$1 'BEGIN{print t2-t1}'
247
if [ $# -lt 2 ]; then
251
while [ ! -z "$1" ]; do
262
if [ "$1" = "yes" ]; then
264
elif [ "$1" = "no" ]; then
274
SSH_OPTIONS="$SSH_OPTIONS $(echo $1 | cut -c7-)"
275
SSH="ssh $SSH_OPTIONS"
276
SCP="scp $SSH_OPTIONS"
290
if [ -z "$host" -o -z "$VEID" -o $# -ne 0 ]; then
294
vpsconf="$confdir/$VEID.conf"
296
if [ ! -r "$vzconf" -o ! -r "$vpsconf" ]; then
297
log 0 "Can't read global config or VE #$VEID config file"
298
exit $MIG_ERR_NOEXIST
301
get_status $(vzctl status $VEID)
302
if [ "$exist" = "deleted" ]; then
303
log 0 "VE #$VEID doesn't exist"
304
exit $MIG_ERR_NOEXIST
307
if [ $online -eq 1 ]; then
308
log 1 "Starting online migration of VE $VEID on $host"
310
log 1 "Starting migration of VE $VEID on $host"
313
# Try to connect to destination
314
if ! logexec 2 $SSH -o BatchMode=yes root@$host /bin/true; then
315
log 0 "Can't connect to destination address using public key"
316
log 0 "Please put your public key to destination node"
317
exit $MIG_ERR_CANT_CONNECT
320
# Check if OpenVZ is running
321
if ! logexec 2 $SSH -o BatchMode=yes root@$host /etc/init.d/vz status ; then
322
log 0 "OpenVZ is not running on the target machine"
323
log 0 "Can't continue migration"
324
exit $MIG_ERR_OVZ_NOT_RUNNING
327
dst_exist=$($SSH "root@$host" "vzctl status $VEID" | awk '{print $3}')
328
if [ "$dst_exist" = "exist" ]; then
329
log 0 "VE #$VEID already exists on destination node"
333
if [ $online -eq 1 -a "$state" != "running" ]; then
334
log 0 "Can't perform online migration of stopped VE"
335
exit $MIG_ERR_VPS_IS_STOPPED
338
log 2 "Loading $vzconf and $vpsconf files"
342
VE_DUMPFILE="$tmpdir/dump.$VEID"
343
VE_QUOTADUMP="$tmpdir/quotadump.$VEID"
345
log 2 "Check IPs on destination node: $IP_ADDRESS"
346
for IP in $IP_ADDRESS; do
347
if [ $($SSH "root@$host" "grep -c \" $IP \" /proc/vz/veip") -gt 0 ];
349
log 0 "IP address $IP already in use on destination node"
350
exit $MIG_ERR_IP_IN_USE
354
log 1 "Preparing remote node"
356
log 2 "Copying config file"
357
if ! logexec 2 $SCP $vpsconf root@$host:$vpsconf ; then
358
log 0 "Failed to copy config file"
362
logexec 2 $SSH root@$host vzctl set $VEID --applyconfig_map name --save
363
# vzctl return code 20 or 21 in case of unrecognized option
364
if [[ $? != 20 && $? != 21 && $? != 0 ]]; then
365
log 0 "Failed to apply config on destination node"
367
exit $MIG_ERR_APPLY_CONFIG
370
for sfx in $ACT_SCRIPTS_SFX; do
371
file="$confdir/$VEID.$sfx"
372
if [ -f "$file" ]; then
373
act_scripts="$act_scripts $file"
376
if [ -n "$act_scripts" ]; then
377
log 2 "Copying action scripts"
378
if ! logexec 2 $SCP $act_scripts root@$host:$confdir ; then
379
log 0 "Failed to copy action scripts"
385
log 2 "Creating remote VE root dir"
386
if ! $SSH "root@$host" "mkdir -p $VE_ROOT"; then
387
log 0 "Failed to make VE root"
392
log 2 "Creating remote VE private dir"
393
if ! $SSH "root@$host" "mkdir -p $VE_PRIVATE"; then
394
log 0 "Failed to make VE private area"
399
log 1 "Initializing remote quota"
402
if ! $SSH "root@$host" "vzctl quotainit $VEID"; then
403
log 0 "Failed to initialize quota"
408
log 2 "Turning remote quota on"
409
if ! $SSH "root@$host" "vzctl quotaon $VEID"; then
410
log 0 "Failed to turn quota on"
415
log 1 "Syncing private"
416
if ! rsync -aH --delete --progress \
417
"$VE_PRIVATE" "root@$host:${VE_PRIVATE%/*}" | \
418
grep "% of" | awk -v ORS="\r" '{print $10}'; then
419
log 0 "Failed to sync VE private areas"
424
if [ $online -eq 1 ]; then
425
log 1 "Live migrating VE"
427
log 2 "Suspending VE"
428
time_suspend=$(date +%s.%N)
429
if ! logexec 2 vzctl chkpnt $VEID --suspend ; then
430
log 0 "Failed to suspend VE"
432
exit $MIG_ERR_CHECKPOINT
436
if ! logexec 2 vzctl chkpnt $VEID --dump --dumpfile $VE_DUMPFILE ; then
437
log 0 "Failed to dump VE"
439
exit $MIG_ERR_CHECKPOINT
442
log 2 "Copying dumpfile"
443
time_copy_dump=$(date +%s.%N)
444
if ! logexec 2 $SCP $VE_DUMPFILE root@$host:$VE_DUMPFILE ; then
445
log 0 "Failed to copy dump"
450
if [ "$state" = "running" ]; then
452
if ! logexec 2 vzctl stop $VEID ; then
453
log 0 "Failed to stop VE"
455
exit $MIG_ERR_STOP_SOURCE
457
elif [ "$mounted" = "mounted" ]; then
458
log 1 "Unmounting VE"
459
if ! logexec 2 vzctl umount $VEID ; then
460
log 0 "Failed to umount VE"
462
exit $MIG_ERR_STOP_SOURCE
467
if [ "$state" = "running" ]; then
468
log 2 "Syncing private (2nd pass)"
469
time_rsync2=$(date +%s.%N)
470
if ! rsync -aH --delete \
471
"$VE_PRIVATE" "root@$host:${VE_PRIVATE%/*}"; then
472
log 0 "Failed to sync VE private areas"
478
log 1 "Syncing 2nd level quota"
480
log 2 "Dumping 2nd level quota"
481
time_quota=$(date +%s.%N)
482
if ! vzdqdump $VEID -U -G -T > "$VE_QUOTADUMP"; then
483
log 0 "Failed to dump 2nd level quota"
488
log 2 "Copying 2nd level quota"
489
if ! logexec 2 $SCP $VE_QUOTADUMP root@$host:$VE_QUOTADUMP ; then
490
log 0 "Failed to copy 2nd level quota dump"
495
log 2 "Load 2nd level quota"
496
if ! $SSH "root@$host" "(vzdqload $VEID -U -G -T < $VE_QUOTADUMP && \
497
vzquota reload2 $VEID)"; then
498
log 0 "Failed to load 2nd level quota"
503
if [ $online -eq 1 ]; then
505
time_undump=$(date +%s.%N)
506
if ! logexec 2 $SSH root@$host vzctl restore $VEID --undump \
507
--dumpfile $VE_DUMPFILE --skip_arpdetect ; then
508
log 0 "Failed to undump VE"
510
exit $MIG_ERR_RESTORE_VPS
514
if ! logexec 2 $SSH root@$host vzctl restore $VEID --resume ; then
515
log 0 "Failed to resume VE"
517
exit $MIG_ERR_RESTORE_VPS
519
time_finish=$(date +%s.%N)
521
log 2 "\tSuspend + Dump:\t" $(get_time $time_suspend $time_copy_dump)
522
log 2 "\tCopy dump file:\t" $(get_time $time_copy_dump $time_rsync2)
523
log 2 "\tSecond rsync:\t" $(get_time $time_rsync2 $time_quota)
524
log 2 "\t2nd level quota:\t" $(get_time $time_quota $time_undump)
525
log 2 "\tUndump + Resume:\t" $(get_time $time_undump $time_finish)
526
log 2 "Total time: " $(get_time $time_suspend $time_finish)
531
logexec 2 vzctl chkpnt $VEID --kill
532
logexec 2 vzctl umount $VEID
534
log 2 "Removing dumpfiles"
536
$SSH "root@$host" "rm -f $VE_DUMPFILE"
538
if [ "$state" = "running" ]; then
540
if ! logexec 2 $SSH root@$host vzctl start $VEID ; then
541
log 0 "Failed to start VE"
543
exit $MIG_ERR_START_VPS
545
elif [ "$mounted" = "mounted" ]; then
547
if ! logexec 2 $SSH root@$host vzctl mount $VEID ; then
548
log 0 "Failed to mount VE"
550
exit $MIG_ERR_MOUNT_VPS
553
log 1 "Turning quota off"
554
if ! logexec 2 $SSH root@$host vzquota off $VEID ; then
555
log 0 "failed to turn quota off"
564
if [ $remove_area -eq 1 ]; then
565
log 2 "Destroying VE"
566
logexec 2 vzctl destroy $VEID
568
# Move config as veid.migrated to allow backward migration
569
mv -f $vpsconf $vpsconf.migrated