~ubuntu-branches/ubuntu/karmic/vzctl/karmic

« back to all changes in this revision

Viewing changes to bin/vzmigrate.in

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2007-04-10 18:08:16 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070410180816-0uuzj9fnna7gmzxv
Tags: 3.0.16-4
Etch has been released which means that this version can be uploaded
to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/bin/bash
 
2
#
 
3
# vzmigrate is used for VE migration to another node
 
4
# Copyright (C) 2000-2007 SWsoft. All rights reserved.
 
5
#
 
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.
 
10
 
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.
 
15
 
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
 
19
#
 
20
#
 
21
# Usage:
 
22
# vzmigrate [-r yes|no] [--ssh=<options>] [--keep-dst] [--online] [-v]
 
23
#           destination_address VEID
 
24
# Options:
 
25
#       -r, --remove-area yes|no
 
26
#               Whether to remove VE on source HN for successfully migrated VE.
 
27
#       --ssh=<ssh options>
 
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.
 
31
#       --keep-dst
 
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.
 
36
#       --online
 
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.
 
40
#       -v      
 
41
#               Verbose mode. Causes vzmigrate to print debugging messages about
 
42
#               its progress (including some time statistics).
 
43
#
 
44
# Examples:
 
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
 
49
# NOTE:
 
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.
 
53
 
 
54
 
 
55
ACT_SCRIPTS_SFX="start stop mount umount"
 
56
SSH_OPTIONS=""
 
57
SSH="ssh $SSH_OPTIONS"
 
58
SCP="scp $SSH_OPTIONS"
 
59
 
 
60
online=0
 
61
verbose=0
 
62
remove_area=1
 
63
keep_dst=0
 
64
debug=0
 
65
confdir="@PKGCONFDIR@/conf"
 
66
vzconf="@PKGCONFDIR@/vz.conf"
 
67
tmpdir="/var/tmp"
 
68
act_scripts=
 
69
 
 
70
# Errors:
 
71
MIG_ERR_USAGE=1
 
72
MIG_ERR_VPS_IS_STOPPED=2
 
73
MIG_ERR_CANT_CONNECT=4
 
74
MIG_ERR_COPY=6
 
75
MIG_ERR_START_VPS=7
 
76
MIG_ERR_STOP_SOURCE=8
 
77
MIG_ERR_EXISTS=9
 
78
MIG_ERR_NOEXIST=10
 
79
MIG_ERR_IP_IN_USE=12
 
80
MIG_ERR_QUOTA=13
 
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
 
86
 
 
87
usage() {
 
88
        cat <<EOF
 
89
This program is used for VE migration to another node
 
90
Usage:
 
91
vzmigrate [-r yes|no] [--ssh=<options>] [--keep-dst] [--online] [-v]
 
92
        destination_address <VEID>
 
93
Options:
 
94
-r, --remove-area yes|no
 
95
        Whether to remove VE on source HN for successfully migrated VE.
 
96
--ssh=<ssh options>
 
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.
 
100
--keep-dst
 
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.
 
105
--online
 
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.
 
109
-v      
 
110
        Verbose mode. Causes vzmigrate to print debugging messages about
 
111
        its progress (including some time statistics).
 
112
EOF
 
113
        exit $MIG_ERR_USAGE
 
114
}
 
115
 
 
116
# Logs message
 
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)
 
121
log () {
 
122
        if [ $1 -eq 0 ]; then
 
123
                shift
 
124
                echo -e "Error: " $@ >&2
 
125
        elif [ $1 -eq 1 ]; then
 
126
                shift
 
127
                echo -e $@
 
128
        elif [ $verbose -eq 1 ]; then
 
129
                shift
 
130
                echo -e "   " $@
 
131
        fi
 
132
}
 
133
 
 
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)
 
139
logexec () {
 
140
        if [ $1 -eq 1 -o $verbose -eq 1 ]; then
 
141
                shift
 
142
                $@
 
143
        else
 
144
                shift
 
145
                $@ &> /dev/null
 
146
        fi
 
147
        return $?
 
148
}
 
149
 
 
150
undo_conf () {
 
151
        $SSH "root@$host" "rm -f $vpsconf"
 
152
}
 
153
 
 
154
undo_act_scripts () {
 
155
        if [ -n "$act_scripts" ] ; then
 
156
                $SSH "root@$host" "rm -f $act_scripts"
 
157
        fi
 
158
        undo_conf
 
159
}
 
160
 
 
161
undo_private () {
 
162
        if [ $keep_dst -eq 0 ]; then
 
163
                $SSH "root@$host" "rm -rf $VE_PRIVATE"
 
164
        fi
 
165
        undo_act_scripts
 
166
}
 
167
 
 
168
undo_root () {
 
169
        $SSH "root@$host" "rm -rf $VE_ROOT"
 
170
        undo_private
 
171
}
 
172
 
 
173
undo_quota_init () {
 
174
        $SSH "root@$host" "vzquota drop $VEID"
 
175
        undo_root
 
176
}
 
177
 
 
178
undo_quota_on () {
 
179
        $SSH "root@$host" "vzquota off $VEID"
 
180
        undo_quota_init
 
181
}
 
182
 
 
183
undo_sync () {
 
184
        # Root will be destroed in undo_root
 
185
        undo_quota_on
 
186
}
 
187
 
 
188
undo_suspend () {
 
189
        logexec 2 vzctl chkpnt $VEID --resume
 
190
        undo_sync
 
191
}
 
192
 
 
193
undo_dump () {
 
194
        if [ $debug -eq 0 ]; then
 
195
                rm -f "$VE_DUMPFILE"
 
196
        fi
 
197
        undo_suspend
 
198
}
 
199
 
 
200
undo_copy_dump () {
 
201
        $SSH "root@$host" "rm -f $VE_DUMPFILE"
 
202
        undo_suspend
 
203
}
 
204
 
 
205
undo_stop () {
 
206
        if [ "$state" = "running" ]; then
 
207
                vzctl start $VEID
 
208
        elif [ "$mounted" = "mounted" ]; then
 
209
                vzctl mount $VEID
 
210
        fi
 
211
        undo_sync
 
212
}
 
213
 
 
214
undo_source_stage() {
 
215
        if [ $online -eq 1 ]; then
 
216
                undo_copy_dump
 
217
        else
 
218
                undo_stop
 
219
        fi
 
220
}
 
221
 
 
222
undo_quota_dump () {
 
223
        rm -f "$VE_QUOTADUMP"
 
224
        undo_source_stage
 
225
}
 
226
 
 
227
undo_copy_quota () {
 
228
        $SSH "root@$host" "rm -f $VE_QUOTADUMP"
 
229
        undo_quota_dump
 
230
}
 
231
 
 
232
undo_undump () {
 
233
        logexec 2 $SSH root@$host vzctl restore $VEID --kill
 
234
        undo_copy_quota
 
235
}
 
236
 
 
237
get_status() {
 
238
        exist=$3
 
239
        mounted=$4
 
240
        state=$5
 
241
}
 
242
 
 
243
get_time () {
 
244
        awk -v t2=$2 -v t1=$1 'BEGIN{print t2-t1}'
 
245
}
 
246
 
 
247
if [ $# -lt 2 ]; then
 
248
        usage
 
249
fi
 
250
 
 
251
while [ ! -z "$1" ]; do
 
252
        log 1 "OPT:$1"
 
253
        case "$1" in
 
254
        --online)
 
255
                online=1
 
256
                ;;
 
257
        -v)
 
258
                verbose=1
 
259
                ;;
 
260
        --remove-area|-r)
 
261
                shift
 
262
                if [ "$1" = "yes" ]; then
 
263
                        remove_area=1
 
264
                elif [ "$1" = "no" ]; then
 
265
                        remove_area=0;
 
266
                else
 
267
                        usage
 
268
                fi
 
269
                ;;
 
270
        --keep-dst)
 
271
                keep_dst=1
 
272
                ;;
 
273
        --ssh=*)
 
274
                SSH_OPTIONS="$SSH_OPTIONS $(echo $1 | cut -c7-)"
 
275
                SSH="ssh $SSH_OPTIONS"
 
276
                SCP="scp $SSH_OPTIONS"
 
277
                ;;
 
278
        *)
 
279
                break
 
280
                ;;
 
281
        esac
 
282
        shift
 
283
done
 
284
 
 
285
host=$1
 
286
shift
 
287
VEID=$1
 
288
shift
 
289
 
 
290
if [ -z "$host" -o -z "$VEID" -o $# -ne 0 ]; then
 
291
        usage
 
292
fi
 
293
 
 
294
vpsconf="$confdir/$VEID.conf"
 
295
 
 
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
 
299
fi
 
300
 
 
301
get_status $(vzctl status $VEID)
 
302
if [ "$exist" = "deleted" ]; then
 
303
        log 0 "VE #$VEID doesn't exist"
 
304
        exit $MIG_ERR_NOEXIST
 
305
fi
 
306
 
 
307
if [ $online -eq 1 ]; then
 
308
        log 1 "Starting online migration of VE $VEID on $host"
 
309
else
 
310
        log 1 "Starting migration of VE $VEID on $host"
 
311
fi
 
312
 
 
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
 
318
fi
 
319
 
 
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
 
325
fi
 
326
 
 
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"
 
330
        exit $MIG_ERR_EXISTS
 
331
fi
 
332
 
 
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
 
336
fi
 
337
 
 
338
log 2 "Loading $vzconf and $vpsconf files"
 
339
 
 
340
. "$vzconf"
 
341
. "$vpsconf"
 
342
VE_DUMPFILE="$tmpdir/dump.$VEID"
 
343
VE_QUOTADUMP="$tmpdir/quotadump.$VEID"
 
344
 
 
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 ];
 
348
        then
 
349
                log 0 "IP address $IP already in use on destination node"
 
350
                exit $MIG_ERR_IP_IN_USE
 
351
        fi
 
352
done
 
353
 
 
354
log 1 "Preparing remote node"
 
355
 
 
356
log 2 "Copying config file"
 
357
if ! logexec 2 $SCP $vpsconf root@$host:$vpsconf ; then
 
358
        log 0 "Failed to copy config file"
 
359
        exit $MIG_ERR_COPY
 
360
fi
 
361
 
 
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"
 
366
        undo_conf
 
367
        exit $MIG_ERR_APPLY_CONFIG
 
368
fi
 
369
 
 
370
for sfx in $ACT_SCRIPTS_SFX; do
 
371
        file="$confdir/$VEID.$sfx"
 
372
        if [ -f "$file" ]; then
 
373
                act_scripts="$act_scripts $file"
 
374
        fi
 
375
done
 
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"
 
380
                undo_conf
 
381
                exit $MIG_ERR_COPY
 
382
        fi
 
383
fi
 
384
 
 
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"
 
388
        undo_act_scripts
 
389
        exit $MIG_ERR_COPY
 
390
fi
 
391
 
 
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"
 
395
        undo_private
 
396
        exit $MIG_ERR_COPY
 
397
fi
 
398
 
 
399
log 1 "Initializing remote quota"
 
400
 
 
401
log 2 "Quota init"
 
402
if ! $SSH "root@$host" "vzctl quotainit $VEID"; then
 
403
        log 0 "Failed to initialize quota"
 
404
        undo_root
 
405
        exit $MIG_ERR_QUOTA
 
406
fi
 
407
 
 
408
log 2 "Turning remote quota on"
 
409
if ! $SSH "root@$host" "vzctl quotaon $VEID"; then
 
410
        log 0 "Failed to turn quota on"
 
411
        undo_quota_init
 
412
        exit $MIG_ERR_QUOTA
 
413
fi
 
414
 
 
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"
 
420
        undo_quota_on
 
421
        exit $MIG_ERR_COPY
 
422
fi
 
423
 
 
424
if [ $online -eq 1 ]; then
 
425
        log 1 "Live migrating VE"
 
426
 
 
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"
 
431
                undo_sync
 
432
                exit $MIG_ERR_CHECKPOINT 
 
433
        fi
 
434
 
 
435
        log 2 "Dumping VE"
 
436
        if ! logexec 2 vzctl chkpnt $VEID --dump --dumpfile $VE_DUMPFILE ; then
 
437
                log 0 "Failed to dump VE"
 
438
                undo_suspend
 
439
                exit $MIG_ERR_CHECKPOINT
 
440
        fi
 
441
 
 
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"
 
446
                undo_dump
 
447
                exit $MIG_ERR_COPY
 
448
        fi
 
449
else
 
450
        if [ "$state" = "running" ]; then
 
451
                log 1 "Stopping VE"
 
452
                if ! logexec 2 vzctl stop $VEID ; then
 
453
                        log 0 "Failed to stop VE"
 
454
                        undo_sync
 
455
                        exit $MIG_ERR_STOP_SOURCE
 
456
                fi
 
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"
 
461
                        undo_sync
 
462
                        exit $MIG_ERR_STOP_SOURCE
 
463
                fi
 
464
        fi
 
465
fi
 
466
 
 
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"
 
473
                undo_source_stage
 
474
                exit $MIG_ERR_COPY
 
475
        fi
 
476
fi
 
477
 
 
478
log 1 "Syncing 2nd level quota"
 
479
 
 
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"
 
484
        undo_quota_dump
 
485
        exit $MIG_ERR_QUOTA
 
486
fi
 
487
 
 
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"
 
491
        undo_quota_dump
 
492
        exit $MIG_ERR_COPY
 
493
fi
 
494
 
 
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"
 
499
        undo_copy_quota
 
500
        exit $MIG_ERR_QUOTA
 
501
fi
 
502
 
 
503
if [ $online -eq 1 ]; then
 
504
        log 2 "Undumping VE"
 
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"
 
509
                undo_copy_quota
 
510
                exit $MIG_ERR_RESTORE_VPS
 
511
        fi
 
512
 
 
513
        log 2 "Resuming VE"
 
514
        if ! logexec 2 $SSH root@$host vzctl restore $VEID --resume ; then
 
515
                log 0 "Failed to resume VE"
 
516
                undo_undump
 
517
                exit $MIG_ERR_RESTORE_VPS
 
518
        fi
 
519
        time_finish=$(date +%s.%N)
 
520
        log 2 "Times:"
 
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)
 
527
 
 
528
        log 1 "Cleanup"
 
529
 
 
530
        log 2 "Killing VE"
 
531
        logexec 2 vzctl chkpnt $VEID --kill
 
532
        logexec 2 vzctl umount $VEID
 
533
 
 
534
        log 2 "Removing dumpfiles"
 
535
        rm -f "$VE_DUMPFILE"
 
536
        $SSH "root@$host" "rm -f $VE_DUMPFILE"
 
537
else
 
538
        if [ "$state" = "running" ]; then
 
539
                log 1 "Starting VE"
 
540
                if ! logexec 2 $SSH root@$host vzctl start $VEID ; then
 
541
                        log 0 "Failed to start VE"
 
542
                        undo_copy_quota
 
543
                        exit $MIG_ERR_START_VPS
 
544
                fi
 
545
        elif [ "$mounted" = "mounted" ]; then
 
546
                log 1 "Mounting VE"
 
547
                if ! logexec 2 $SSH root@$host vzctl mount $VEID ; then
 
548
                        log 0 "Failed to mount VE"
 
549
                        undo_copy_quota
 
550
                        exit $MIG_ERR_MOUNT_VPS
 
551
                fi
 
552
        else
 
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"
 
556
                        undo_copy_quota
 
557
                        exit $MIG_ERR_QUOTA
 
558
                fi
 
559
        fi
 
560
 
 
561
        log 1 "Cleanup"
 
562
fi
 
563
 
 
564
if [ $remove_area -eq 1 ]; then
 
565
        log 2 "Destroying VE"
 
566
        logexec 2 vzctl destroy $VEID
 
567
else
 
568
        # Move config as veid.migrated to allow backward migration
 
569
        mv -f $vpsconf $vpsconf.migrated 
 
570
fi